r_world: Add a new R_DrawTextureChains_Multitexture_VBO function. Draws lightmapped surfaces with fulbrights in one pass, using the VBO. Requires 3 TMUs, GL_COMBINE_EXT, and GL_ADD.

R_DrawTextureChains_Multitexture: revert to the way it was before VBO support was added.
gl_texmgr: expose GL_SelectTexture. make the implementation less convoluted and support 3 TMUs.
gl_vidsdl: check GL_MAX_TEXTURE_UNITS
r_brush: only create VBOs if 3 TMUs available

git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@1035 af15c1b1-3010-417e-b628-4374ebc0bcbd
This commit is contained in:
Eric Wasylishen 2014-09-20 01:08:13 +00:00
parent d37b1574fe
commit 90b26fc215
6 changed files with 136 additions and 73 deletions

View File

@ -1401,7 +1401,8 @@ void TexMgr_ReloadNobrightImages (void)
================================================================================
*/
static GLuint currenttexture = (GLuint)-1; // to avoid unnecessary texture sets
static GLuint currenttexture[3] = {-1, -1, -1}; // to avoid unnecessary texture sets
static GLenum currenttarget = GL_TEXTURE0_ARB;
qboolean mtexenabled = false;
/*
@ -1409,27 +1410,12 @@ qboolean mtexenabled = false;
GL_SelectTexture -- johnfitz -- rewritten
================
*/
static void GL_SelectTexture (GLenum target)
void GL_SelectTexture (GLenum target)
{
static GLenum currenttarget;
static GLuint ct0, ct1;
if (target == currenttarget)
return;
GL_SelectTextureFunc(target);
if (target == GL_TEXTURE0_ARB)
{
ct1 = currenttexture;
currenttexture = ct0;
}
else //target == GL_TEXTURE1_ARB
{
ct0 = currenttexture;
currenttexture = ct1;
}
currenttarget = target;
}
@ -1473,10 +1459,10 @@ void GL_Bind (gltexture_t *texture)
if (!texture)
texture = nulltexture;
if (texture->texnum != currenttexture)
if (texture->texnum != currenttexture[currenttarget - GL_TEXTURE0_ARB])
{
currenttexture = texture->texnum;
glBindTexture (GL_TEXTURE_2D, currenttexture);
currenttexture[currenttarget - GL_TEXTURE0_ARB] = texture->texnum;
glBindTexture (GL_TEXTURE_2D, texture->texnum);
texture->visframe = r_framecount;
}
}

View File

@ -98,6 +98,7 @@ int TexMgr_PadConditional (int s);
// TEXTURE BINDING & TEXTURE UNIT SWITCHING
void GL_SelectTexture (GLenum target);
void GL_DisableMultitexture (void); //selects texture unit 0
void GL_EnableMultitexture (void); //selects texture unit 1
void GL_Bind (gltexture_t *texture);

View File

@ -93,6 +93,7 @@ qboolean gl_anisotropy_able = false; //johnfitz
float gl_max_anisotropy; //johnfitz
qboolean gl_texture_NPOT = false; //ericw
qboolean gl_vbo_able = false; //ericw
GLint gl_max_texture_units = 0; //ericw
PFNGLMULTITEXCOORD2FARBPROC GL_MTexCoord2fFunc = NULL; //johnfitz
PFNGLACTIVETEXTUREARBPROC GL_SelectTextureFunc = NULL; //johnfitz
@ -831,6 +832,9 @@ static void GL_CheckExtensions (void)
{
Con_Printf("FOUND: ARB_multitexture\n");
gl_mtexable = true;
glGetIntegerv(GL_MAX_TEXTURE_UNITS, &gl_max_texture_units);
Con_Printf("GL_MAX_TEXTURE_UNITS: %d\n", (int)gl_max_texture_units);
}
else
{

View File

@ -155,6 +155,7 @@ extern qboolean gl_mtexable;
extern PFNGLMULTITEXCOORD2FARBPROC GL_MTexCoord2fFunc;
extern PFNGLACTIVETEXTUREARBPROC GL_SelectTextureFunc;
extern PFNGLCLIENTACTIVETEXTUREARBPROC GL_ClientActiveTextureFunc;
extern GLint gl_max_texture_units; //ericw
//johnfitz -- anisotropic filtering
#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE

View File

@ -975,7 +975,7 @@ void GL_BuildVBOs (void)
qmodel_t *m;
float *varray;
if (!(gl_vbo_able && gl_mtexable))
if (!(gl_vbo_able && gl_mtexable && gl_max_texture_units >= 3))
return;
// ask GL for a name for our VBO
@ -1024,7 +1024,7 @@ void GL_BuildVBOs (void)
// setup vertex array. this will need to move if we use vertex arrays for other things
glVertexPointer (3, GL_FLOAT, VERTEXSIZE * sizeof(float), ((float *)0));
glEnableClientState (GL_VERTEX_ARRAY);
GL_ClientActiveTextureFunc (GL_TEXTURE0_ARB);
glTexCoordPointer (2, GL_FLOAT, VERTEXSIZE * sizeof(float), ((float *)0) + 3);
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
@ -1032,6 +1032,11 @@ void GL_BuildVBOs (void)
GL_ClientActiveTextureFunc (GL_TEXTURE1_ARB);
glTexCoordPointer (2, GL_FLOAT, VERTEXSIZE * sizeof(float), ((float *)0) + 5);
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
// TMU 2 is for fullbrights; same texture coordinates as TMU 0
GL_ClientActiveTextureFunc (GL_TEXTURE2_ARB);
glTexCoordPointer (2, GL_FLOAT, VERTEXSIZE * sizeof(float), ((float *)0) + 3);
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
}
/*

View File

@ -416,29 +416,6 @@ void R_DrawTextureChains_Glow (qmodel_t *model, entity_t *ent, texchain_t chain)
//
//==============================================================================
/*
================
R_MultitexturedDrawGLPoly
Fallback immediate mode code to draw a multitexutred glpoly_t
================
*/
static void R_MultitexturedDrawGLPoly (glpoly_t *p)
{
float *v;
int j;
glBegin(GL_POLYGON);
v = p->verts[0];
for (j=0 ; j<p->numverts ; j++, v+= VERTEXSIZE)
{
GL_MTexCoord2fFunc (GL_TEXTURE0_ARB, v[3], v[4]);
GL_MTexCoord2fFunc (GL_TEXTURE1_ARB, v[5], v[6]);
glVertex3fv (v);
}
glEnd ();
}
static unsigned int R_NumTriangleIndicesForSurf (msurface_t *s)
{
return 3 * (s->numedges - 2);
@ -475,8 +452,6 @@ R_ClearBatch
*/
static void R_ClearBatch ()
{
if (!(gl_vbo_able && gl_mtexable)) return;
num_vbo_indices = 0;
}
@ -489,8 +464,6 @@ Draw the current batch if non-empty and clears it, ready for more R_BatchSurface
*/
static void R_FlushBatch ()
{
if (!(gl_vbo_able && gl_mtexable)) return;
if (num_vbo_indices > 0)
{
glDrawElements (GL_TRIANGLES, num_vbo_indices, GL_UNSIGNED_INT, vbo_indices);
@ -509,13 +482,7 @@ using VBOs.
static void R_BatchSurface (msurface_t *s)
{
int num_surf_indices;
if (!(gl_vbo_able && gl_mtexable))
{
R_MultitexturedDrawGLPoly (s->polys);
return;
}
num_surf_indices = R_NumTriangleIndicesForSurf (s);
if (num_vbo_indices + num_surf_indices > MAX_BATCH_SIZE)
@ -532,11 +499,11 @@ R_DrawTextureChains_Multitexture -- johnfitz
*/
void R_DrawTextureChains_Multitexture (qmodel_t *model, entity_t *ent, texchain_t chain)
{
int i;
int i, j;
msurface_t *s;
texture_t *t;
float *v;
qboolean bound;
int lastlightmap;
for (i=0 ; i<model->numtextures ; i++)
{
@ -545,10 +512,7 @@ void R_DrawTextureChains_Multitexture (qmodel_t *model, entity_t *ent, texchain_
if (!t || !t->texturechains[chain] || t->texturechains[chain]->flags & (SURF_DRAWTILED | SURF_NOTEXTURE))
continue;
R_ClearBatch ();
bound = false;
lastlightmap = 0; // avoid compiler warning
for (s = t->texturechains[chain]; s; s = s->texturechain)
if (!s->culled)
{
@ -561,22 +525,20 @@ void R_DrawTextureChains_Multitexture (qmodel_t *model, entity_t *ent, texchain_
GL_EnableMultitexture(); // selects TEXTURE1
bound = true;
lastlightmap = s->lightmaptexturenum;
}
R_RenderDynamicLightmaps (s);
if (s->lightmaptexturenum != lastlightmap)
R_FlushBatch ();
GL_Bind (lightmap_textures[s->lightmaptexturenum]);
lastlightmap = s->lightmaptexturenum;
R_BatchSurface (s);
glBegin(GL_POLYGON);
v = s->polys->verts[0];
for (j=0 ; j<s->polys->numverts ; j++, v+= VERTEXSIZE)
{
GL_MTexCoord2fFunc (GL_TEXTURE0_ARB, v[3], v[4]);
GL_MTexCoord2fFunc (GL_TEXTURE1_ARB, v[5], v[6]);
glVertex3fv (v);
}
glEnd ();
rs_brushpasses++;
}
R_FlushBatch ();
GL_DisableMultitexture(); // selects TEXTURE0
if (bound && t->texturechains[chain]->flags & SURF_DRAWFENCE)
@ -807,6 +769,103 @@ void R_DrawLightmapChains (void)
}
}
/*
================
R_DrawTextureChains_Multitexture_VBO -- ericw
Draw lightmapped surfaces with fulbrights in one pass, using VBO.
Requires 3 TMUs, GL_COMBINE_EXT, and GL_ADD.
================
*/
void R_DrawTextureChains_Multitexture_VBO (qmodel_t *model, entity_t *ent, texchain_t chain)
{
int i;
msurface_t *s;
texture_t *t;
qboolean bound;
int lastlightmap;
gltexture_t *fullbright = NULL;
// Setup TMU 1 (lightmap)
GL_SelectTexture (GL_TEXTURE1_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, gl_overbright.value ? 2.0f : 1.0f);
glEnable(GL_TEXTURE_2D);
// Setup TMU 2 (fullbrights)
GL_SelectTexture (GL_TEXTURE2_ARB);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
for (i=0 ; i<model->numtextures ; i++)
{
t = model->textures[i];
if (!t || !t->texturechains[chain] || t->texturechains[chain]->flags & (SURF_DRAWTILED | SURF_NOTEXTURE))
continue;
// Enable/disable TMU 2 (fullbrights)
GL_SelectTexture (GL_TEXTURE2_ARB);
if (gl_fullbrights.value && (fullbright = R_TextureAnimation(t, ent != NULL ? ent->frame : 0)->fullbright))
{
glEnable(GL_TEXTURE_2D);
GL_Bind (fullbright);
}
else
glDisable(GL_TEXTURE_2D);
R_ClearBatch ();
bound = false;
lastlightmap = 0; // avoid compiler warning
for (s = t->texturechains[chain]; s; s = s->texturechain)
if (!s->culled)
{
if (!bound) //only bind once we are sure we need this texture
{
GL_SelectTexture (GL_TEXTURE0_ARB);
GL_Bind ((R_TextureAnimation(t, ent != NULL ? ent->frame : 0))->gltexture);
if (t->texturechains[chain]->flags & SURF_DRAWFENCE)
glEnable (GL_ALPHA_TEST); // Flip alpha test back on
bound = true;
lastlightmap = s->lightmaptexturenum;
}
R_RenderDynamicLightmaps (s);
if (s->lightmaptexturenum != lastlightmap)
R_FlushBatch ();
GL_SelectTexture (GL_TEXTURE1_ARB);
GL_Bind (lightmap_textures[s->lightmaptexturenum]);
lastlightmap = s->lightmaptexturenum;
R_BatchSurface (s);
rs_brushpasses++;
}
R_FlushBatch ();
if (bound && t->texturechains[chain]->flags & SURF_DRAWFENCE)
glDisable (GL_ALPHA_TEST); // Flip alpha test back off
}
// Reset TMU states
GL_SelectTexture (GL_TEXTURE2_ARB);
glDisable (GL_TEXTURE_2D);
GL_SelectTexture (GL_TEXTURE1_ARB);
glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.0f);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glDisable (GL_TEXTURE_2D);
GL_SelectTexture (GL_TEXTURE0_ARB);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
}
/*
=============
R_DrawWorld -- johnfitz -- rewritten
@ -859,6 +918,13 @@ void R_DrawTextureChains (qmodel_t *model, entity_t *ent, texchain_t chain)
R_DrawTextureChains_NoTexture (model, chain);
if (gl_vbo_able && gl_texture_env_combine && gl_texture_env_add && gl_mtexable && gl_max_texture_units >= 3)
{
R_DrawTextureChains_Multitexture_VBO (model, ent, chain);
R_EndTransparentDrawing (entalpha);
return;
}
if (gl_overbright.value)
{
if (gl_texture_env_combine && gl_mtexable) //case 1: texture and lightmap in one pass, overbright using texture combiners