+ qglDisable(GL_TEXTURE_SHADER_NV);
+ qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
+ GL_ActiveTexture(0);
+ }
+ else if (texture->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
+ {
+ // normal surface (wall or water)
+ dolightmap = !(texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT);
+ doambient = r_ambient.value >= (1/64.0f);
+ dodetail = r_detailtextures.integer && texture->skin.detail != NULL && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT);
+ doglow = texture->skin.glow != NULL;
+ dofogpass = fogenabled && !(texture->currentmaterialflags & MATERIALFLAG_ADD);
+ fogallpasses = fogenabled && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT);
+ if (ent->colormap >= 0)
+ {
+ int b;
+ qbyte *bcolor;
+ basetexture = texture->skin.base;
+ dopants = texture->skin.pants != NULL;
+ doshirt = texture->skin.shirt != NULL;
+ // 128-224 are backwards ranges
+ b = (ent->colormap & 0xF) << 4;b += (b >= 128 && b < 224) ? 4 : 12;
+ dofullbrightpants = b >= 224;
+ bcolor = (qbyte *) (&palette_complete[b]);
+ VectorScale(bcolor, (1.0f / 255.0f), colorpants);
+ // 128-224 are backwards ranges
+ b = (ent->colormap & 0xF0);b += (b >= 128 && b < 224) ? 4 : 12;
+ dofullbrightshirt = b >= 224;
+ bcolor = (qbyte *) (&palette_complete[b]);
+ VectorScale(bcolor, (1.0f / 255.0f), colorshirt);
+ }
+ else
+ {
+ basetexture = texture->skin.merged ? texture->skin.merged : texture->skin.base;
+ dopants = false;
+ doshirt = false;
+ dofullbrightshirt = false;
+ dofullbrightpants = false;
+ }
+ if (dolightmap && r_textureunits.integer >= 2 && gl_combine.integer)
+ {
+ memset(&m, 0, sizeof(m));
+ m.tex[1] = R_GetTexture(basetexture);
+ if (waterscrolling)
+ m.texmatrix[1] = r_waterscrollmatrix;
+ m.texrgbscale[1] = 2;
+ m.pointer_color = varray_color4f;
+ R_Mesh_State(&m);
+ // transparent is not affected by r_lightmapintensity
+ if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
+ colorscale = r_lightmapintensity;
+ else
+ colorscale = 1;
+ r = ent->colormod[0] * colorscale;
+ g = ent->colormod[1] * colorscale;
+ b = ent->colormod[2] * colorscale;
+ a = texture->currentalpha;
+ // q3bsp has no lightmap updates, so the lightstylevalue that
+ // would normally be baked into the lightmaptexture must be
+ // applied to the color
+ if (ent->model->brushq3.data_lightmaps)
+ {
+ float scale = d_lightstylevalue[0] * (1.0f / 128.0f);
+ r *= scale;
+ g *= scale;
+ b *= scale;
+ }
+ applycolor = r != 1 || g != 1 || b != 1 || a != 1;
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ RSurf_SetVertexPointer(ent, texture, surface, modelorg);
+ R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
+ R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
+ if (surface->lightmaptexture)
+ R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
+ else
+ R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
+ RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmodel, !surface->lightmaptexture, applycolor, fogallpasses);
+ GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
+ GL_LockArrays(0, 0);
+ }
+ }
+ else if (dolightmap && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT) && !lightmodel)
+ {
+ // single texture
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ GL_DepthMask(true);
+ GL_Color(1, 1, 1, 1);
+ memset(&m, 0, sizeof(m));
+ R_Mesh_State(&m);
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ RSurf_SetVertexPointer(ent, texture, surface, modelorg);
+ R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
+ if (surface->lightmaptexture)
+ {
+ R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
+ R_Mesh_ColorPointer(NULL);
+ }
+ else
+ {
+ R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
+ R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
+ }
+ GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
+ GL_LockArrays(0, 0);
+ }
+ GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
+ GL_DepthMask(false);
+ GL_Color(r_lightmapintensity * ent->colormod[0], r_lightmapintensity * ent->colormod[1], r_lightmapintensity * ent->colormod[2], 1);
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(basetexture);
+ if (waterscrolling)
+ m.texmatrix[0] = r_waterscrollmatrix;
+ R_Mesh_State(&m);
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ RSurf_SetVertexPointer(ent, texture, surface, modelorg);
+ R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
+ GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
+ GL_LockArrays(0, 0);
+ }
+ }
+ else
+ {
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(basetexture);
+ if (waterscrolling)
+ m.texmatrix[0] = r_waterscrollmatrix;
+ m.pointer_color = varray_color4f;
+ colorscale = 2;
+ if (gl_combine.integer)
+ {
+ m.texrgbscale[0] = 2;
+ colorscale = 1;
+ }
+ // transparent is not affected by r_lightmapintensity
+ if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
+ colorscale *= r_lightmapintensity;
+ R_Mesh_State(&m);
+ r = ent->colormod[0] * colorscale;
+ g = ent->colormod[1] * colorscale;
+ b = ent->colormod[2] * colorscale;
+ a = texture->currentalpha;
+ if (dolightmap)
+ {
+ // q3bsp has no lightmap updates, so the lightstylevalue that
+ // would normally be baked into the lightmaptexture must be
+ // applied to the color
+ if (ent->model->brushq3.data_lightmaps)
+ {
+ float scale = d_lightstylevalue[0] * (1.0f / 128.0f);
+ r *= scale;
+ g *= scale;
+ b *= scale;
+ }
+ applycolor = r != 1 || g != 1 || b != 1 || a != 1;
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ RSurf_SetVertexPointer(ent, texture, surface, modelorg);
+ R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
+ RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmodel, true, applycolor, fogallpasses);
+ GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
+ GL_LockArrays(0, 0);
+ }
+ }
+ else
+ {
+ applycolor = r != 1 || g != 1 || b != 1 || a != 1;
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ RSurf_SetVertexPointer(ent, texture, surface, modelorg);
+ R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
+ RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, false, false, applycolor, fogallpasses);
+ GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
+ GL_LockArrays(0, 0);
+ }
+ }
+ }
+ if (dopants)
+ {
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(texture->skin.pants);
+ if (waterscrolling)
+ m.texmatrix[0] = r_waterscrollmatrix;
+ m.pointer_color = varray_color4f;
+ colorscale = 1;
+ if (gl_combine.integer)
+ {
+ m.texrgbscale[0] = 2;
+ colorscale *= 0.5f;
+ }
+ // transparent is not affected by r_lightmapintensity
+ if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
+ colorscale *= r_lightmapintensity;
+ R_Mesh_State(&m);
+ r = ent->colormod[0] * colorpants[0] * colorscale;
+ g = ent->colormod[1] * colorpants[1] * colorscale;
+ b = ent->colormod[2] * colorpants[2] * colorscale;
+ a = texture->currentalpha;
+ if (dolightmap && !dofullbrightpants)
+ {
+ // q3bsp has no lightmap updates, so the lightstylevalue that
+ // would normally be baked into the lightmaptexture must be
+ // applied to the color
+ if (ent->model->brushq3.data_lightmaps)
+ {
+ float scale = d_lightstylevalue[0] * (1.0f / 128.0f);
+ r *= scale;
+ g *= scale;
+ b *= scale;
+ }
+ applycolor = r != 1 || g != 1 || b != 1 || a != 1;
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ RSurf_SetVertexPointer(ent, texture, surface, modelorg);
+ R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
+ RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmodel, true, applycolor, fogallpasses);
+ GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
+ GL_LockArrays(0, 0);
+ }
+ }
+ else
+ {
+ applycolor = r != 1 || g != 1 || b != 1 || a != 1;
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ RSurf_SetVertexPointer(ent, texture, surface, modelorg);
+ R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
+ RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, false, false, applycolor, fogallpasses);
+ GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
+ GL_LockArrays(0, 0);
+ }
+ }
+ }
+ if (doshirt)
+ {
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(texture->skin.shirt);
+ if (waterscrolling)
+ m.texmatrix[0] = r_waterscrollmatrix;
+ m.pointer_color = varray_color4f;
+ colorscale = 1;
+ if (gl_combine.integer)
+ {
+ m.texrgbscale[0] = 2;
+ colorscale *= 0.5f;
+ }
+ // transparent is not affected by r_lightmapintensity
+ if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
+ colorscale *= r_lightmapintensity;
+ R_Mesh_State(&m);
+ r = ent->colormod[0] * colorshirt[0] * colorscale;
+ g = ent->colormod[1] * colorshirt[1] * colorscale;
+ b = ent->colormod[2] * colorshirt[2] * colorscale;
+ a = texture->currentalpha;
+ if (dolightmap && !dofullbrightshirt)
+ {
+ // q3bsp has no lightmap updates, so the lightstylevalue that
+ // would normally be baked into the lightmaptexture must be
+ // applied to the color
+ if (ent->model->brushq3.data_lightmaps)
+ {
+ float scale = d_lightstylevalue[0] * (1.0f / 128.0f);
+ r *= scale;
+ g *= scale;
+ b *= scale;
+ }
+ applycolor = r != 1 || g != 1 || b != 1 || a != 1;
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ RSurf_SetVertexPointer(ent, texture, surface, modelorg);
+ R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
+ RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmodel, true, applycolor, fogallpasses);
+ GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
+ GL_LockArrays(0, 0);
+ }
+ }
+ else
+ {
+ applycolor = r != 1 || g != 1 || b != 1 || a != 1;
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ RSurf_SetVertexPointer(ent, texture, surface, modelorg);
+ R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
+ RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, false, false, applycolor, fogallpasses);
+ GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
+ GL_LockArrays(0, 0);
+ }
+ }
+ }
+ if (doambient)
+ {
+ doambient = false;
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+ GL_DepthMask(false);
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(texture->skin.base);
+ if (waterscrolling)
+ m.texmatrix[0] = r_waterscrollmatrix;
+ m.pointer_color = varray_color4f;
+ colorscale = 1;
+ if (gl_combine.integer)
+ {
+ m.texrgbscale[0] = 2;
+ colorscale *= 0.5f;
+ }
+ R_Mesh_State(&m);
+ colorscale *= r_ambient.value * (1.0f / 64.0f);
+ r = ent->colormod[0] * colorscale;
+ g = ent->colormod[1] * colorscale;
+ b = ent->colormod[2] * colorscale;
+ a = texture->currentalpha;
+ applycolor = r != 1 || g != 1 || b != 1 || a != 1;
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ RSurf_SetVertexPointer(ent, texture, surface, modelorg);
+ R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
+ RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, false, false, applycolor, fogallpasses);
+ GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
+ GL_LockArrays(0, 0);
+ }
+ }
+ if (dodetail)
+ {
+ GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
+ GL_DepthMask(false);
+ GL_Color(1, 1, 1, 1);
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(texture->skin.detail);
+ R_Mesh_State(&m);
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ RSurf_SetVertexPointer(ent, texture, surface, modelorg);
+ R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoorddetail2f);
+ GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
+ GL_LockArrays(0, 0);
+ }
+ }
+ if (doglow)
+ {
+ // if glow was not already done using multitexture, do it now.
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+ GL_DepthMask(false);
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(texture->skin.glow);
+ if (waterscrolling)
+ m.texmatrix[0] = r_waterscrollmatrix;
+ m.pointer_color = varray_color4f;
+ R_Mesh_State(&m);
+ colorscale = 1;
+ r = ent->colormod[0] * colorscale;
+ g = ent->colormod[1] * colorscale;
+ b = ent->colormod[2] * colorscale;
+ a = texture->currentalpha;
+ applycolor = r != 1 || g != 1 || b != 1 || a != 1;
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ RSurf_SetVertexPointer(ent, texture, surface, modelorg);
+ R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
+ RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, false, false, applycolor, fogallpasses);
+ GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
+ GL_LockArrays(0, 0);
+ }
+ }
+ if (dofogpass)
+ {
+ // if this is opaque use alpha blend which will darken the earlier
+ // passes cheaply.
+ //
+ // if this is an alpha blended material, all the earlier passes
+ // were darkened by fog already, so we only need to add the fog
+ // color ontop through the fog mask texture
+ //
+ // if this is an additive blended material, all the earlier passes
+ // were darkened by fog already, and we should not add fog color
+ // (because the background was not darkened, there is no fog color
+ // that was lost behind it).
+ if (fogallpasses)
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+ else
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ GL_DepthMask(false);
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(texture->skin.fog);
+ if (waterscrolling)
+ m.texmatrix[0] = r_waterscrollmatrix;
+ R_Mesh_State(&m);
+ r = fogcolor[0];
+ g = fogcolor[1];
+ b = fogcolor[2];
+ a = texture->currentalpha;
+ applycolor = r != 1 || g != 1 || b != 1 || a != 1;
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ RSurf_SetVertexPointer(ent, texture, surface, modelorg);
+ R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
+ R_Mesh_ColorPointer(varray_color4f);
+ //RSurf_FogPassColors_Vertex3f_Color4f((surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex), varray_color4f, fogcolor[0], fogcolor[1], fogcolor[2], texture->currentalpha, 1, surface->num_vertices, modelorg);
+ if (!surface->lightmaptexture && surface->groupmesh->data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
+ {
+ for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
+ {
+ VectorSubtract(v, modelorg, diff);
+ f = exp(fogdensity/DotProduct(diff, diff));
+ c[0] = r;
+ c[1] = g;
+ c[2] = b;
+ c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * f * a;
+ }
+ }
+ else
+ {
+ for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
+ {
+ VectorSubtract(v, modelorg, diff);
+ f = exp(fogdensity/DotProduct(diff, diff));
+ c[0] = r;
+ c[1] = g;
+ c[2] = b;
+ c[3] = f * a;
+ }
+ }
+ GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
+ GL_LockArrays(0, 0);
+ }
+ }
+ }
+ if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
+ qglEnable(GL_CULL_FACE);