Remove multitexturing support

Multitexturing was never part of any official Quake II release. It was
added in version 3.21, which was released only in source. Over the years
many developers tried to fix multitexturing, including myself. Yamagi
Quake II had it even enabled by default for several releases... But:

  * Multitexturing is poorly implemented and **slow**
  * Multitexturing leads to render errors, for example in city3
  * Multitextring is ortogonal to the normal render path and adds a
    lot of special cases to the renderer

Remove it for good. Ciao, it wasn't a nice time. :) The last version
before this commit was at least somewhat fixed, read some of the worst
problems were fixed. If someone's ever going to resurrect it, it would
be a good idea to start at that point.
This commit is contained in:
Yamagi Burmeister 2016-12-03 09:46:08 +01:00
parent 6dab39d7d6
commit 68a12d4ee1
5 changed files with 27 additions and 493 deletions

View file

@ -273,10 +273,8 @@ extern float r_world_matrix[16];
void R_TranslatePlayerSkin(int playernum);
void R_Bind(int texnum);
void R_MBind(GLenum target, int texnum);
void R_TexEnv(GLenum value);
void R_EnableMultitexture(qboolean enable);
void R_SelectTexture(GLenum);
void R_LightPoint(vec3_t p, vec3_t color);
void R_PushDlights(void);
@ -365,8 +363,6 @@ typedef struct
// ----
qboolean anisotropic;
qboolean mtexcombine;
qboolean multitexture;
qboolean npottextures;
qboolean palettedtexture;
qboolean pointparameters;

View file

@ -145,62 +145,6 @@ R_SetTexturePalette(unsigned palette[256])
}
}
void
R_EnableMultitexture(qboolean enable)
{
if (!gl_config.multitexture)
{
return;
}
if (enable)
{
R_SelectTexture(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
R_TexEnv(GL_REPLACE);
}
else
{
R_SelectTexture(GL_TEXTURE1_ARB);
glDisable(GL_TEXTURE_2D);
R_TexEnv(GL_REPLACE);
}
R_SelectTexture(GL_TEXTURE0_ARB);
R_TexEnv(GL_REPLACE);
}
void
R_SelectTexture(GLenum texture)
{
int tmu;
if (!gl_config.multitexture)
{
return;
}
if (texture == GL_TEXTURE0_ARB)
{
tmu = 0;
}
else
{
tmu = 1;
}
if (tmu == gl_state.currenttmu)
{
return;
}
gl_state.currenttmu = tmu;
gl_state.currenttarget = texture;
qglActiveTextureARB(texture);
qglClientActiveTextureARB(texture);
}
void
R_TexEnv(GLenum mode)
{
@ -232,32 +176,6 @@ R_Bind(int texnum)
glBindTexture(GL_TEXTURE_2D, texnum);
}
void
R_MBind(GLenum target, int texnum)
{
if (target != gl_state.currenttarget)
{
R_SelectTexture(target);
}
if (target == GL_TEXTURE0_ARB)
{
if (gl_state.currenttextures[0] == texnum)
{
return;
}
}
else
{
if (gl_state.currenttextures[1] == texnum)
{
return;
}
}
R_Bind(texnum);
}
void
R_TextureMode(char *string)
{

View file

@ -252,9 +252,6 @@ LM_BeginBuildingLightmaps(model_t *m)
r_framecount = 1; /* no dlightcache */
R_EnableMultitexture(true);
R_SelectTexture(GL_TEXTURE1_ARB);
/* setup the base lightstyles so the lightmaps
won't have to be regenerated the first time
they're seen */
@ -289,6 +286,5 @@ void
LM_EndBuildingLightmaps(void)
{
LM_UploadBlock(false);
R_EnableMultitexture(false);
}

View file

@ -90,9 +90,7 @@ cvar_t *gl_particle_att_b;
cvar_t *gl_particle_att_c;
cvar_t *gl_palettedtexture;
cvar_t *gl_multitexture;
cvar_t *gl_pointparameters;
cvar_t *gl_mtexcombine;
cvar_t *gl_drawbuffer;
cvar_t *gl_lightmap;
@ -1235,9 +1233,7 @@ R_Register(void)
gl_lockpvs = Cvar_Get("gl_lockpvs", "0", 0);
gl_palettedtexture = Cvar_Get("gl_palettedtexture", "0", CVAR_ARCHIVE);
gl_multitexture = Cvar_Get("gl_multitexture", "0", CVAR_ARCHIVE);
gl_pointparameters = Cvar_Get("gl_pointparameters", "1", CVAR_ARCHIVE);
gl_mtexcombine = Cvar_Get("gl_mtexcombine", "1", CVAR_ARCHIVE);
gl_drawbuffer = Cvar_Get("gl_drawbuffer", "GL_BACK", 0);
gl_swapinterval = Cvar_Get("gl_swapinterval", "1", CVAR_ARCHIVE);
@ -1471,60 +1467,6 @@ R_Init(void *hinstance, void *hWnd)
VID_Printf(PRINT_ALL, "Disabled\n");
}
// ----
/* Multitexturing */
VID_Printf(PRINT_ALL, " - Multitexturing: ");
if (strstr(gl_config.extensions_string, "GL_ARB_multitexture"))
{
qglMultiTexCoord2fARB = (void *)GLimp_GetProcAddress("glMultiTexCoord2fARB");
qglMultiTexCoord2fvARB = (void *)GLimp_GetProcAddress("glMultiTexCoord2fvARB");
qglActiveTextureARB = (void *)GLimp_GetProcAddress("glActiveTextureARB");
qglClientActiveTextureARB = (void *)GLimp_GetProcAddress("glClientActiveTextureARB");
}
gl_config.multitexture = false;
if (gl_multitexture->value)
{
if (qglMultiTexCoord2fARB && qglMultiTexCoord2fvARB && qglActiveTextureARB && qglClientActiveTextureARB)
{
gl_config.multitexture = true;
VID_Printf(PRINT_ALL, "Okay\n");
}
else
{
VID_Printf(PRINT_ALL, "Failed\n");
}
}
else
{
VID_Printf(PRINT_ALL, "Disabled\n");
}
// ----
/* Multi texturing combine */
VID_Printf(PRINT_ALL, " - Multi texturing combine: ");
if (strstr(gl_config.extensions_string, "GL_ARB_texture_env_combine") && gl_config.multitexture)
{
if (gl_mtexcombine->value)
{
gl_config.mtexcombine = true;
VID_Printf(PRINT_ALL, "Okay\n");
}
else
{
VID_Printf(PRINT_ALL, "Disabled\n");
}
}
else
{
VID_Printf(PRINT_ALL, "Failed\n");
}
// --------
/* Anisotropic */

View file

@ -306,7 +306,6 @@ R_BlendLightmaps(void)
if (gl_overbrightbits->value)
{
R_TexEnv(GL_COMBINE_EXT);
R_SelectTexture(GL_TEXTURE1);
glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, gl_overbrightbits->value);
}
@ -366,7 +365,6 @@ R_BlendLightmaps(void)
if (gl_overbrightbits->value)
{
R_TexEnv(GL_COMBINE_EXT);
R_SelectTexture(GL_TEXTURE1);
glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, gl_overbrightbits->value);
}
@ -411,7 +409,6 @@ R_BlendLightmaps(void)
if (gl_overbrightbits->value)
{
R_TexEnv(GL_COMBINE_EXT);
R_SelectTexture(GL_TEXTURE1);
glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, gl_overbrightbits->value);
}
@ -459,7 +456,6 @@ R_RenderBrushPoly(msurface_t *fa)
if (gl_overbrightbits->value)
{
R_TexEnv(GL_COMBINE_EXT);
R_SelectTexture(GL_TEXTURE1);
glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1);
}
else
@ -621,230 +617,33 @@ R_DrawTextureChains(void)
c_visible_textures = 0;
if (!gl_config.multitexture)
for (i = 0, image = gltextures; i < numgltextures; i++, image++)
{
for (i = 0, image = gltextures; i < numgltextures; i++, image++)
if (!image->registration_sequence)
{
if (!image->registration_sequence)
{
continue;
}
s = image->texturechain;
if (!s)
{
continue;
}
c_visible_textures++;
for ( ; s; s = s->texturechain)
{
R_RenderBrushPoly(s);
}
image->texturechain = NULL;
}
}
else
{
for (i = 0, image = gltextures; i < numgltextures; i++, image++)
{
if (!image->registration_sequence)
{
continue;
}
if (!image->texturechain)
{
continue;
}
c_visible_textures++;
for (s = image->texturechain; s; s = s->texturechain)
{
if (!(s->flags & SURF_DRAWTURB))
{
R_RenderBrushPoly(s);
}
}
continue;
}
R_EnableMultitexture(false);
s = image->texturechain;
for (i = 0, image = gltextures; i < numgltextures; i++, image++)
if (!s)
{
if (!image->registration_sequence)
{
continue;
}
s = image->texturechain;
if (!s)
{
continue;
}
for ( ; s; s = s->texturechain)
{
if (s->flags & SURF_DRAWTURB)
{
R_RenderBrushPoly(s);
}
}
image->texturechain = NULL;
continue;
}
c_visible_textures++;
for ( ; s; s = s->texturechain)
{
R_RenderBrushPoly(s);
}
image->texturechain = NULL;
}
R_TexEnv(GL_REPLACE);
}
void
R_RenderLightmappedPoly(msurface_t *surf)
{
int i;
int map;
int nv;
int smax;
int tmax;
float scroll;
float *v;
glpoly_t *p;
image_t *image;
qboolean is_dynamic;
unsigned lmtex;
unsigned temp[128 * 128];
image = R_TextureAnimation(surf->texinfo);
is_dynamic = false;
lmtex = surf->lightmaptexturenum;
nv = surf->polys->numverts;
// Any dynamic lights on this surface?
for (map = 0; map < MAXLIGHTMAPS && surf->styles[map] != 255; map++)
{
if (r_newrefdef.lightstyles[surf->styles[map]].white != surf->cached_light[map])
{
if (!(surf->texinfo->flags & (SURF_SKY | SURF_TRANS33 | SURF_TRANS66 | SURF_WARP)))
{
is_dynamic = true;
}
}
}
// Normal dynamic lights
if (surf->dlightframe == r_framecount)
{
if (gl_dynamic->value)
{
if (!(surf->texinfo->flags & (SURF_SKY | SURF_TRANS33 | SURF_TRANS66 | SURF_WARP)))
{
is_dynamic = true;
}
}
}
if (is_dynamic)
{
// Dynamic lights on a surface
if (((surf->styles[map] >= 32) || (surf->styles[map] == 0)) && (surf->dlightframe != r_framecount))
{
smax = (surf->extents[0] >> 4) + 1;
tmax = (surf->extents[1] >> 4) + 1;
R_BuildLightMap(surf, (void *) temp, smax * 4);
R_SetCacheState(surf);
R_MBind(GL_TEXTURE1_ARB, gl_state.lightmap_textures + surf->lightmaptexturenum);
lmtex = surf->lightmaptexturenum;
glTexSubImage2D(GL_TEXTURE_2D, 0, surf->light_s, surf->light_t, smax,
tmax, GL_LIGHTMAP_FORMAT, GL_UNSIGNED_BYTE, temp);
}
else // Normal dynamic lights
{
smax = (surf->extents[0] >> 4) + 1;
tmax = (surf->extents[1] >> 4) + 1;
R_BuildLightMap(surf, (void *) temp, smax * 4);
R_MBind(GL_TEXTURE1_ARB, gl_state.lightmap_textures + 0);
lmtex = 0;
glTexSubImage2D(GL_TEXTURE_2D, 0, surf->light_s, surf->light_t, smax,
tmax, GL_LIGHTMAP_FORMAT, GL_UNSIGNED_BYTE, temp);
}
c_brush_polys++;
R_MBind(GL_TEXTURE0_ARB, image->texnum);
R_MBind(GL_TEXTURE1_ARB, gl_state.lightmap_textures + lmtex);
}
else // No dynamic lights
{
c_brush_polys++;
R_MBind(GL_TEXTURE0_ARB, image->texnum);
R_MBind(GL_TEXTURE1_ARB, gl_state.lightmap_textures + lmtex);
}
if (surf->texinfo->flags & SURF_FLOWING)
{
scroll = -64 * ((r_newrefdef.time / 40.0) - (int) (r_newrefdef.time / 40.0));
if (scroll == 0.0)
{
scroll = -64.0;
}
for (p = surf->polys; p; p = p->chain)
{
v = p->verts[0];
glBegin(GL_POLYGON);
for (i = 0; i < nv; i++, v += VERTEXSIZE)
{
qglMultiTexCoord2fARB(GL_TEXTURE0, (v[3] + scroll), v[4]);
qglMultiTexCoord2fvARB(GL_TEXTURE1, &v[5]);
glVertex3fv(v);
}
glEnd();
}
}
else
{
for (p = surf->polys; p; p = p->chain)
{
v = p->verts[0];
// Polygon
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, VERTEXSIZE * sizeof(GLfloat), v);
// Texture
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
qglClientActiveTextureARB(GL_TEXTURE0_ARB);
glTexCoordPointer(2, GL_FLOAT, VERTEXSIZE * sizeof(GLfloat), v + 3);
// Lightmap
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
qglClientActiveTextureARB(GL_TEXTURE1_ARB);
glTexCoordPointer(2, GL_FLOAT, VERTEXSIZE * sizeof(GLfloat), v + 5);
// Draw the crap
glDrawArrays(GL_TRIANGLE_FAN, 0, p->numverts);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
}
}
void
R_DrawInlineBModel(void)
{
@ -892,25 +691,17 @@ R_DrawInlineBModel(void)
psurf->texturechain = r_alpha_surfaces;
r_alpha_surfaces = psurf;
}
else if (gl_config.multitexture && !(psurf->flags & SURF_DRAWTURB))
{
R_RenderLightmappedPoly(psurf);
}
else
{
R_EnableMultitexture(false);
R_RenderBrushPoly(psurf);
R_EnableMultitexture(true);
}
}
}
if (!(currententity->flags & RF_TRANSLUCENT))
{
if (!gl_config.multitexture)
{
R_BlendLightmaps();
}
R_BlendLightmaps();
}
else
{
@ -986,60 +777,18 @@ R_DrawBrushModel(entity_t *e)
e->angles[0] = -e->angles[0];
e->angles[2] = -e->angles[2];
R_EnableMultitexture(true);
R_TexEnv(GL_REPLACE);
R_SelectTexture(GL_TEXTURE0_ARB);
if (!gl_config.mtexcombine)
if (gl_lightmap->value)
{
R_TexEnv(GL_REPLACE);
R_SelectTexture(GL_TEXTURE1);
if (gl_lightmap->value)
{
R_TexEnv(GL_REPLACE);
}
else
{
R_TexEnv(GL_MODULATE);
}
}
else
{
R_TexEnv(GL_COMBINE_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE);
R_SelectTexture(GL_TEXTURE1);
R_TexEnv(GL_COMBINE_EXT);
if (gl_lightmap->value)
{
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE);
}
else
{
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_PREVIOUS_EXT);
}
if (gl_overbrightbits->value)
{
glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT,
gl_overbrightbits->value);
}
R_TexEnv(GL_MODULATE);
}
R_DrawInlineBModel();
R_EnableMultitexture(false);
glPopMatrix();
@ -1167,17 +916,10 @@ R_RecursiveWorldNode(mnode_t *node)
}
else
{
if (gl_config.multitexture && !(surf->flags & SURF_DRAWTURB))
{
R_RenderLightmappedPoly(surf);
}
else
{
/* the polygon is visible, so add it to the texture sorted chain */
image = R_TextureAnimation(surf->texinfo);
surf->texturechain = image->texturechain;
image->texturechain = surf;
}
/* the polygon is visible, so add it to the texture sorted chain */
image = R_TextureAnimation(surf->texinfo);
surf->texturechain = image->texturechain;
image->texturechain = surf;
}
}
@ -1213,69 +955,9 @@ R_DrawWorld(void)
glColor4f(1, 1, 1, 1);
memset(gl_lms.lightmap_surfaces, 0, sizeof(gl_lms.lightmap_surfaces));
R_ClearSkyBox();
if (gl_config.multitexture)
{
R_EnableMultitexture(true);
R_SelectTexture(GL_TEXTURE0_ARB);
if (!gl_config.mtexcombine)
{
R_TexEnv(GL_REPLACE);
R_SelectTexture(GL_TEXTURE1_ARB);
if (gl_lightmap->value)
{
R_TexEnv(GL_REPLACE);
}
else
{
R_TexEnv(GL_MODULATE);
}
}
else
{
R_TexEnv(GL_COMBINE_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE);
R_SelectTexture(GL_TEXTURE1_ARB);
R_TexEnv(GL_COMBINE_EXT);
if (gl_lightmap->value)
{
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE);
}
else
{
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_PREVIOUS_EXT);
}
if (gl_overbrightbits->value)
{
glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, gl_overbrightbits->value);
}
}
R_RecursiveWorldNode(r_worldmodel->nodes);
R_EnableMultitexture(false);
}
else
{
R_RecursiveWorldNode(r_worldmodel->nodes);
}
R_RecursiveWorldNode(r_worldmodel->nodes);
R_DrawTextureChains();
R_BlendLightmaps();
R_DrawSkyBox();