mirror of
https://github.com/yquake2/yquake2remaster.git
synced 2024-11-22 04:31:09 +00:00
GL1 unified draw calls, cont.
Batching procedure from previous commit, applied this time to GLPoly / single texture surfaces; alpha and liquid included.
This commit is contained in:
parent
50aebd2de4
commit
4461128255
4 changed files with 166 additions and 147 deletions
|
@ -61,16 +61,17 @@ R_ApplyGLBuffer(void)
|
|||
{
|
||||
// Properties of batched draws here
|
||||
GLint vtx_size;
|
||||
qboolean texture;
|
||||
qboolean texture, alpha, texenv_set;
|
||||
|
||||
if (gl_buf.vtx_ptr == 0 || gl_buf.idx_ptr == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// defaults for drawing
|
||||
// defaults for drawing (mostly buf_singletex features)
|
||||
vtx_size = 3;
|
||||
texture = true;
|
||||
alpha = texenv_set = false;
|
||||
|
||||
// choosing features by type
|
||||
switch (gl_buf.type)
|
||||
|
@ -78,10 +79,52 @@ R_ApplyGLBuffer(void)
|
|||
case buf_2d:
|
||||
vtx_size = 2;
|
||||
break;
|
||||
case buf_alpha:
|
||||
alpha = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (alpha)
|
||||
{
|
||||
// the textures are prescaled up for a better
|
||||
// lighting range, so scale it back down
|
||||
glColor4f(gl_state.inverse_intensity, gl_state.inverse_intensity,
|
||||
gl_state.inverse_intensity, gl_buf.alpha);
|
||||
|
||||
}
|
||||
else if (gl_buf.flags & SURF_DRAWTURB)
|
||||
{
|
||||
texenv_set = true;
|
||||
|
||||
// This is a hack ontop of a hack. Warping surfaces like those generated
|
||||
// by R_EmitWaterPolys() don't have a lightmap. Original Quake II therefore
|
||||
// negated the global intensity on those surfaces, because otherwise they
|
||||
// would show up much too bright. When we implemented overbright bits this
|
||||
// hack modified the global GL state in an incompatible way. So implement
|
||||
// a new hack, based on overbright bits... Depending on the value set to
|
||||
// gl1_overbrightbits the result is different:
|
||||
|
||||
// 0: Old behaviour.
|
||||
// 1: No overbright bits on the global scene but correct lighting on
|
||||
// warping surfaces.
|
||||
// 2,4: Overbright bits on the global scene but not on warping surfaces.
|
||||
// They oversaturate otherwise.
|
||||
|
||||
if (gl1_overbrightbits->value)
|
||||
{
|
||||
R_TexEnv(GL_COMBINE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
R_TexEnv(GL_MODULATE);
|
||||
glColor4f(gl_state.inverse_intensity, gl_state.inverse_intensity,
|
||||
gl_state.inverse_intensity, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
glEnableClientState( GL_VERTEX_ARRAY );
|
||||
glVertexPointer (vtx_size, GL_FLOAT, 0, gl_buf.vtx);
|
||||
|
||||
|
@ -104,13 +147,20 @@ R_ApplyGLBuffer(void)
|
|||
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
|
||||
if (texenv_set)
|
||||
{
|
||||
R_TexEnv(GL_REPLACE);
|
||||
}
|
||||
|
||||
gl_buf.vtx_ptr = gl_buf.idx_ptr = 0;
|
||||
}
|
||||
|
||||
void
|
||||
R_UpdateGLBuffer(buffered_draw_t type, int colortex, int lighttex, int flags, float alpha)
|
||||
{
|
||||
if ( gl_buf.type != type || gl_buf.texture[0] != colortex )
|
||||
if ( gl_buf.type != type || gl_buf.texture[0] != colortex ||
|
||||
(type == buf_singletex && gl_buf.flags != flags) ||
|
||||
(type == buf_alpha && gl_buf.alpha != alpha))
|
||||
{
|
||||
R_ApplyGLBuffer();
|
||||
|
||||
|
@ -169,3 +219,63 @@ R_Buffer2DQuad(GLfloat ul_vx, GLfloat ul_vy, GLfloat dr_vx, GLfloat dr_vy,
|
|||
|
||||
gl_buf.vtx_ptr += 4;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up indices with the proper shape for the next buffered vertices
|
||||
*/
|
||||
void
|
||||
R_SetBufferIndices(GLenum type, GLuint vertices_num)
|
||||
{
|
||||
int i;
|
||||
|
||||
if ( gl_buf.vtx_ptr + vertices_num >= MAX_VERTICES ||
|
||||
gl_buf.idx_ptr + ( (vertices_num - 2) * 3 ) >= MAX_INDICES )
|
||||
{
|
||||
R_ApplyGLBuffer();
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case GL_TRIANGLE_FAN:
|
||||
for (i = 0; i < vertices_num-2; i++)
|
||||
{
|
||||
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr;
|
||||
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr+i+1;
|
||||
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr+i+2;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
R_Printf(PRINT_DEVELOPER, "R_SetBufferIndices: no such type %d\n", type);
|
||||
return;
|
||||
}
|
||||
|
||||
// These affect the functions that follow in this file
|
||||
vt = gl_buf.vtx_ptr * 3; // vertex index
|
||||
tx = gl_buf.vtx_ptr * 2; // texcoord index
|
||||
cl = gl_buf.vtx_ptr * 4; // color index
|
||||
|
||||
// R_BufferVertex() must be called as many times as vertices_num
|
||||
gl_buf.vtx_ptr += vertices_num;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds a single vertex to buffer
|
||||
*/
|
||||
void
|
||||
R_BufferVertex(GLfloat x, GLfloat y, GLfloat z)
|
||||
{
|
||||
gl_buf.vtx[vt++] = x;
|
||||
gl_buf.vtx[vt++] = y;
|
||||
gl_buf.vtx[vt++] = z;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds texture coordinates for color texture (no lightmap coords)
|
||||
*/
|
||||
void
|
||||
R_BufferSingleTex(GLfloat s, GLfloat t)
|
||||
{
|
||||
// tx should be set before this is called, by R_SetBufferIndices
|
||||
gl_buf.tex[0][tx++] = s;
|
||||
gl_buf.tex[0][tx++] = t;
|
||||
}
|
||||
|
|
|
@ -43,63 +43,35 @@ void R_SetCacheState(msurface_t *surf);
|
|||
void R_BuildLightMap(msurface_t *surf, byte *dest, int stride);
|
||||
|
||||
static void
|
||||
R_DrawGLPoly(glpoly_t *p)
|
||||
R_DrawGLPoly(msurface_t *fa)
|
||||
{
|
||||
float *v;
|
||||
int i, nv;
|
||||
float *v, scroll;
|
||||
|
||||
v = p->verts[0];
|
||||
v = fa->polys->verts[0];
|
||||
nv = fa->polys->numverts;
|
||||
|
||||
glEnableClientState( GL_VERTEX_ARRAY );
|
||||
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
|
||||
glVertexPointer( 3, GL_FLOAT, VERTEXSIZE*sizeof(GLfloat), v );
|
||||
glTexCoordPointer( 2, GL_FLOAT, VERTEXSIZE*sizeof(GLfloat), v+3 );
|
||||
glDrawArrays( GL_TRIANGLE_FAN, 0, p->numverts );
|
||||
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
}
|
||||
|
||||
static void
|
||||
R_DrawGLFlowingPoly(msurface_t *fa)
|
||||
{
|
||||
int i;
|
||||
float *v;
|
||||
glpoly_t *p;
|
||||
float scroll;
|
||||
|
||||
p = fa->polys;
|
||||
|
||||
scroll = -64 * ((r_newrefdef.time / 40.0) - (int)(r_newrefdef.time / 40.0));
|
||||
|
||||
if (scroll == 0.0)
|
||||
if (fa->texinfo->flags & SURF_FLOWING)
|
||||
{
|
||||
scroll = -64.0;
|
||||
scroll = -64 * ((r_newrefdef.time / 40.0) - (int)(r_newrefdef.time / 40.0));
|
||||
|
||||
if (scroll == 0.0)
|
||||
{
|
||||
scroll = -64.0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
scroll = 0.0;
|
||||
}
|
||||
|
||||
YQ2_VLA(GLfloat, tex, 2*p->numverts);
|
||||
unsigned int index_tex = 0;
|
||||
R_SetBufferIndices(GL_TRIANGLE_FAN, nv);
|
||||
|
||||
v = p->verts [ 0 ];
|
||||
|
||||
for ( i = 0; i < p->numverts; i++, v += VERTEXSIZE )
|
||||
{
|
||||
tex[index_tex++] = v [ 3 ] + scroll;
|
||||
tex[index_tex++] = v [ 4 ];
|
||||
}
|
||||
v = p->verts [ 0 ];
|
||||
|
||||
glEnableClientState( GL_VERTEX_ARRAY );
|
||||
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
|
||||
glVertexPointer( 3, GL_FLOAT, VERTEXSIZE*sizeof(GLfloat), v );
|
||||
glTexCoordPointer( 2, GL_FLOAT, 0, tex );
|
||||
glDrawArrays( GL_TRIANGLE_FAN, 0, p->numverts );
|
||||
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
|
||||
YQ2_VLAFREE(tex);
|
||||
for ( i = 0; i < nv; i++, v += VERTEXSIZE )
|
||||
{
|
||||
R_BufferVertex(v[0], v[1], v[2]);
|
||||
R_BufferSingleTex(v[3] + scroll, v[4]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -419,47 +391,11 @@ R_RenderBrushPoly(entity_t *currententity, msurface_t *fa)
|
|||
|
||||
if (fa->flags & SURF_DRAWTURB)
|
||||
{
|
||||
/* This is a hack ontop of a hack. Warping surfaces like those generated
|
||||
by R_EmitWaterPolys() don't have a lightmap. Original Quake II therefore
|
||||
negated the global intensity on those surfaces, because otherwise they
|
||||
would show up much too bright. When we implemented overbright bits this
|
||||
hack modified the global GL state in an incompatible way. So implement
|
||||
a new hack, based on overbright bits... Depending on the value set to
|
||||
gl1_overbrightbits the result is different:
|
||||
|
||||
0: Old behaviour.
|
||||
1: No overbright bits on the global scene but correct lighting on
|
||||
warping surfaces.
|
||||
2: Overbright bits on the global scene but not on warping surfaces.
|
||||
They oversaturate otherwise. */
|
||||
if (gl1_overbrightbits->value)
|
||||
{
|
||||
R_TexEnv(GL_COMBINE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
R_TexEnv(GL_MODULATE);
|
||||
glColor4f(gl_state.inverse_intensity, gl_state.inverse_intensity,
|
||||
gl_state.inverse_intensity, 1.0f);
|
||||
}
|
||||
|
||||
R_EmitWaterPolys(fa);
|
||||
R_TexEnv(GL_REPLACE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
R_TexEnv(GL_REPLACE);
|
||||
|
||||
if (fa->texinfo->flags & SURF_FLOWING)
|
||||
{
|
||||
R_DrawGLFlowingPoly(fa);
|
||||
}
|
||||
else
|
||||
{
|
||||
R_DrawGLPoly(fa->polys);
|
||||
}
|
||||
R_DrawGLPoly(fa);
|
||||
|
||||
if (gl_config.multitexture)
|
||||
{
|
||||
|
@ -538,7 +474,7 @@ void
|
|||
R_DrawAlphaSurfaces(void)
|
||||
{
|
||||
msurface_t *s;
|
||||
float intens;
|
||||
float alpha;
|
||||
|
||||
/* go back to the world matrix */
|
||||
glLoadMatrixf(r_world_matrix);
|
||||
|
@ -546,41 +482,35 @@ R_DrawAlphaSurfaces(void)
|
|||
glEnable(GL_BLEND);
|
||||
R_TexEnv(GL_MODULATE);
|
||||
|
||||
/* the textures are prescaled up for a better
|
||||
lighting range, so scale it back down */
|
||||
intens = gl_state.inverse_intensity;
|
||||
|
||||
for (s = r_alpha_surfaces; s; s = s->texturechain)
|
||||
{
|
||||
R_Bind(s->texinfo->image->texnum);
|
||||
c_brush_polys++;
|
||||
|
||||
if (s->texinfo->flags & SURF_TRANS33)
|
||||
{
|
||||
glColor4f(intens, intens, intens, 0.33);
|
||||
alpha = 0.33f;
|
||||
}
|
||||
else if (s->texinfo->flags & SURF_TRANS66)
|
||||
{
|
||||
glColor4f(intens, intens, intens, 0.66);
|
||||
alpha = 0.66f;
|
||||
}
|
||||
else
|
||||
{
|
||||
glColor4f(intens, intens, intens, 1);
|
||||
alpha = 1.0f;
|
||||
}
|
||||
|
||||
R_UpdateGLBuffer(buf_alpha, s->texinfo->image->texnum, 0, 0, alpha);
|
||||
|
||||
if (s->flags & SURF_DRAWTURB)
|
||||
{
|
||||
R_EmitWaterPolys(s);
|
||||
}
|
||||
else if (s->texinfo->flags & SURF_FLOWING)
|
||||
{
|
||||
R_DrawGLFlowingPoly(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
R_DrawGLPoly(s->polys);
|
||||
R_DrawGLPoly(s);
|
||||
}
|
||||
}
|
||||
R_ApplyGLBuffer(); // Flush the last batched array
|
||||
|
||||
R_TexEnv(GL_REPLACE);
|
||||
glColor4f(1, 1, 1, 1);
|
||||
|
@ -842,12 +772,13 @@ R_DrawTextureChains(entity_t *currententity)
|
|||
|
||||
for ( ; s; s = s->texturechain)
|
||||
{
|
||||
R_Bind(image->texnum); // may reset because of dynamic lighting in R_RenderBrushPoly
|
||||
R_UpdateGLBuffer(buf_singletex, image->texnum, 0, s->flags, 1);
|
||||
R_RenderBrushPoly(currententity, s);
|
||||
}
|
||||
|
||||
image->texturechain = NULL;
|
||||
}
|
||||
R_ApplyGLBuffer(); // Flush the last batched array
|
||||
}
|
||||
else // multitexture
|
||||
{
|
||||
|
@ -872,7 +803,7 @@ R_DrawTextureChains(entity_t *currententity)
|
|||
}
|
||||
}
|
||||
|
||||
R_EnableMultitexture(false);
|
||||
R_EnableMultitexture(false); // force disabling, SURF_DRAWTURB surfaces may not exist
|
||||
|
||||
for (i = 0, image = gltextures; i < numgltextures; i++, image++)
|
||||
{
|
||||
|
@ -885,13 +816,14 @@ R_DrawTextureChains(entity_t *currententity)
|
|||
{
|
||||
if (s->flags & SURF_DRAWTURB)
|
||||
{
|
||||
R_Bind(image->texnum);
|
||||
R_UpdateGLBuffer(buf_singletex, image->texnum, 0, s->flags, 1);
|
||||
R_RenderBrushPoly(currententity, s);
|
||||
}
|
||||
}
|
||||
|
||||
image->texturechain = NULL;
|
||||
}
|
||||
R_ApplyGLBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -958,13 +890,14 @@ R_DrawInlineBModel(entity_t *currententity, const model_t *currentmodel)
|
|||
}
|
||||
else
|
||||
{
|
||||
R_EnableMultitexture(false);
|
||||
R_Bind(image->texnum);
|
||||
R_UpdateGLBuffer(buf_singletex, image->texnum, 0, psurf->flags, 1);
|
||||
R_RenderBrushPoly(currententity, psurf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
R_EnableMultitexture(false);
|
||||
R_ApplyGLBuffer();
|
||||
|
||||
if (!(currententity->flags & RF_TRANSLUCENT))
|
||||
{
|
||||
|
|
|
@ -282,7 +282,7 @@ R_EmitWaterPolys(msurface_t *fa)
|
|||
{
|
||||
glpoly_t *p, *bp;
|
||||
float *v;
|
||||
int i;
|
||||
int i, nv;
|
||||
float s, t, os, ot;
|
||||
float scroll;
|
||||
float rdt = r_newrefdef.time;
|
||||
|
@ -296,53 +296,24 @@ R_EmitWaterPolys(msurface_t *fa)
|
|||
scroll = 0;
|
||||
}
|
||||
|
||||
// workaround for lack of VLAs (=> our workaround uses alloca() which is bad in loops)
|
||||
#ifdef _MSC_VER
|
||||
int maxNumVerts = 0;
|
||||
for ( glpoly_t* tmp = fa->polys; tmp; tmp = tmp->next )
|
||||
{
|
||||
if (tmp->numverts > maxNumVerts)
|
||||
maxNumVerts = tmp->numverts;
|
||||
}
|
||||
|
||||
YQ2_VLA( GLfloat, tex, 2 * maxNumVerts );
|
||||
#endif
|
||||
|
||||
for (bp = fa->polys; bp; bp = bp->next)
|
||||
{
|
||||
p = bp;
|
||||
#ifndef _MSC_VER // we have real VLAs, so it's safe to use one in this loop
|
||||
YQ2_VLA(GLfloat, tex, 2*p->numverts);
|
||||
#endif
|
||||
unsigned int index_tex = 0;
|
||||
nv = p->numverts;
|
||||
R_SetBufferIndices(GL_TRIANGLE_FAN, nv);
|
||||
|
||||
for ( i = 0, v = p->verts [ 0 ]; i < p->numverts; i++, v += VERTEXSIZE )
|
||||
for ( i = 0, v = p->verts [ 0 ]; i < nv; i++, v += VERTEXSIZE )
|
||||
{
|
||||
os = v [ 3 ];
|
||||
ot = v [ 4 ];
|
||||
|
||||
s = os + r_turbsin [ (int) ( ( ot * 0.125 + r_newrefdef.time ) * TURBSCALE ) & 255 ];
|
||||
s += scroll;
|
||||
tex[index_tex++] = s * ( 1.0 / 64 );
|
||||
|
||||
s = os + r_turbsin [ (int) ( ( ot * 0.125 + rdt ) * TURBSCALE ) & 255 ] + scroll;
|
||||
t = ot + r_turbsin [ (int) ( ( os * 0.125 + rdt ) * TURBSCALE ) & 255 ];
|
||||
tex[index_tex++] = t * ( 1.0 / 64 );
|
||||
|
||||
R_BufferVertex( v[0], v[1], v[2] );
|
||||
R_BufferSingleTex( s * ( 1.0 / 64 ), t * ( 1.0 / 64 ) );
|
||||
}
|
||||
|
||||
v = p->verts [ 0 ];
|
||||
|
||||
glEnableClientState( GL_VERTEX_ARRAY );
|
||||
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
|
||||
glVertexPointer( 3, GL_FLOAT, VERTEXSIZE*sizeof(GLfloat), v );
|
||||
glTexCoordPointer( 2, GL_FLOAT, 0, tex );
|
||||
glDrawArrays( GL_TRIANGLE_FAN, 0, p->numverts );
|
||||
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
}
|
||||
|
||||
YQ2_VLAFREE( tex );
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -109,7 +109,9 @@ typedef enum
|
|||
|
||||
typedef enum
|
||||
{
|
||||
buf_2d
|
||||
buf_2d,
|
||||
buf_singletex,
|
||||
buf_alpha
|
||||
} buffered_draw_t;
|
||||
|
||||
#include "model.h"
|
||||
|
@ -290,6 +292,9 @@ void R_ApplyGLBuffer(void);
|
|||
void R_UpdateGLBuffer(buffered_draw_t type, int colortex, int lighttex, int flags, float alpha);
|
||||
void R_Buffer2DQuad(GLfloat ul_vx, GLfloat ul_vy, GLfloat dr_vx, GLfloat dr_vy,
|
||||
GLfloat ul_tx, GLfloat ul_ty, GLfloat dr_tx, GLfloat dr_ty);
|
||||
void R_SetBufferIndices(GLenum type, GLuint vertices_num);
|
||||
void R_BufferVertex(GLfloat x, GLfloat y, GLfloat z);
|
||||
void R_BufferSingleTex(GLfloat s, GLfloat t);
|
||||
|
||||
#ifdef DEBUG
|
||||
void glCheckError_(const char *file, const char *function, int line);
|
||||
|
|
Loading…
Reference in a new issue