+ surface = texturesurfacelist[texturesurfaceindex];
+ m.pointer_vertex = surface->mesh.data_vertex3f;
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
+ }
+ }
+ else if ((texture->currentmaterialflags & MATERIALFLAG_WATER) && r_watershader.value && gl_textureshader && !texture->skin.glow && !fogenabled && ent->colormod[0] == 1 && ent->colormod[1] == 1 && ent->colormod[2] == 1)
+ {
+ // NVIDIA Geforce3 distortion texture shader on water
+ float args[4] = {0.05f,0,0,0.04f};
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(mod_shared_distorttexture[(int)(r_refdef.time * 16)&63]);
+ m.tex[1] = R_GetTexture(texture->skin.base);
+ m.texcombinergb[0] = GL_REPLACE;
+ m.texcombinergb[1] = GL_REPLACE;
+ Matrix4x4_CreateFromQuakeEntity(&m.texmatrix[0], 0, 0, 0, 0, 0, 0, r_watershader.value);
+ m.texmatrix[1] = r_surf_waterscrollmatrix;
+
+ GL_ActiveTexture(0);
+ qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
+ GL_ActiveTexture(1);
+ qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_OFFSET_TEXTURE_2D_NV);
+ qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB);
+ qglTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, &args[0]);
+ qglEnable(GL_TEXTURE_SHADER_NV);
+
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ m.pointer_vertex = RSurf_GetVertexPointer(ent, surface);
+ m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
+ m.pointer_texcoord[1] = surface->mesh.data_texcoordtexture2f;
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+
+ 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)
+ dobase = true;
+ dolightmap = !(texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT);
+ doambient = r_ambient.value >= (1/64.0f);
+ dodetail = 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 (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
+ {
+ if (dobase && dolightmap && gl_combine.integer)
+ {
+ dobase = false;
+ memset(&m, 0, sizeof(m));
+ m.tex[1] = R_GetTexture(texture->skin.base);
+ if (waterscrolling)
+ m.texmatrix[1] = r_surf_waterscrollmatrix;
+ m.texrgbscale[1] = 2;
+ m.pointer_color = varray_color4f;
+ colorscale = 1;
+ r = ent->colormod[0] * colorscale;
+ g = ent->colormod[1] * colorscale;
+ b = ent->colormod[2] * colorscale;
+ a = texture->currentalpha;
+ base = r_ambient.value * (1.0f / 64.0f);
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ m.pointer_vertex = RSurf_GetVertexPointer(ent, surface);
+ m.pointer_texcoord[0] = surface->mesh.data_texcoordlightmap2f;
+ m.pointer_texcoord[1] = surface->mesh.data_texcoordtexture2f;
+ if (surface->lightmaptexture)
+ {
+ m.tex[0] = R_GetTexture(surface->lightmaptexture);
+ if (fogallpasses)
+ {
+ m.pointer_color = varray_color4f;
+ for (i = 0, v = m.pointer_vertex, c = varray_color4f;i < surface->mesh.num_vertices;i++, v += 3, c += 4)
+ {
+ VectorSubtract(v, modelorg, diff);
+ f = 1 - exp(fogdensity/DotProduct(diff, diff));
+ c[0] = f * r;
+ c[1] = f * g;
+ c[2] = f * b;
+ c[3] = a;
+ }
+ }
+ else
+ {
+ m.pointer_color = NULL;
+ GL_Color(r, g, b, a);
+ }
+ }
+ else
+ {
+ m.tex[0] = R_GetTexture(r_texture_white);
+ m.pointer_color = varray_color4f;
+#ifdef LHREMOVESOON
+ if (surface->styles[0] != 255 || surface->dlightframe == r_framecount)
+#else
+ if (surface->styles[0] != 255)
+#endif
+ {
+ for (i = 0, v = m.pointer_vertex, c = varray_color4f;i < surface->mesh.num_vertices;i++, v += 3, c += 4)
+ {
+ c[0] = 0;
+ c[1] = 0;
+ c[2] = 0;
+ if (surface->styles[0] != 255)
+ {
+ if (surface->mesh.data_lightmapcolor4f)
+ {
+ float scale = d_lightstylevalue[surface->styles[0]] * (1.0f / 128.0f);
+ VectorMA(c, scale, surface->mesh.data_lightmapcolor4f + i*4, c);
+ }
+ else if (surface->mesh.data_lightmapoffsets)
+ {
+ const qbyte *lm = surface->samples + surface->mesh.data_lightmapoffsets[i];
+ float scale = d_lightstylevalue[surface->styles[0]] * (1.0f / 32768.0f);
+ VectorMA(c, scale, lm, c);
+ if (surface->styles[1] != 255)
+ {
+ int size3 = ((surface->extents[0]>>4)+1)*((surface->extents[1]>>4)+1)*3;
+ lm += size3;
+ scale = d_lightstylevalue[surface->styles[1]] * (1.0f / 32768.0f);
+ VectorMA(c, scale, lm, c);
+ if (surface->styles[2] != 255)
+ {
+ lm += size3;
+ scale = d_lightstylevalue[surface->styles[2]] * (1.0f / 32768.0f);
+ VectorMA(c, scale, lm, c);
+ if (surface->styles[3] != 255)
+ {
+ lm += size3;
+ scale = d_lightstylevalue[surface->styles[3]] * (1.0f / 32768.0f);
+ VectorMA(c, scale, lm, c);
+ }
+ }
+ }
+ }
+ }
+#ifdef LHREMOVESOON
+ if (surface->dlightframe == r_framecount)
+ {
+ int l;
+ float worldvertex[3];
+ // TODO: make this work with autosprite which uses identitymatrix
+ Matrix4x4_Transform(&ent->matrix, v, worldvertex);
+ for (l = 0;l < r_numdlights;l++)
+ {
+ if (surface->dlightbits[l >> 5] & (1 << (l & 31)))
+ {
+ float f2;
+ dlight_t *light = &r_dlight[l];
+ f2 = VectorDistance2(worldvertex, light->origin) + LIGHTOFFSET;
+ if (f2 < light->rtlight.lightmap_cullradius2)
+ {
+ f2 = (1.0f / f2) - light->rtlight.lightmap_subtract;
+ VectorMA(c, f2, light->rtlight.lightmap_light, c);
+ }
+ }
+ }
+ }
+#endif
+ c[0] *= r;
+ c[1] *= g;
+ c[2] *= b;
+ if (fogallpasses)
+ {
+ VectorSubtract(v, modelorg, diff);
+ f = 1 - exp(fogdensity/DotProduct(diff, diff));
+ VectorScale(c, f, c);
+ }
+ if (surface->mesh.data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
+ c[3] = surface->mesh.data_lightmapcolor4f[i*4+3] * a;
+ else
+ c[3] = a;
+ }
+ }
+ else
+ {
+ if (surface->mesh.data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
+ {
+ for (i = 0, v = m.pointer_vertex, c = varray_color4f;i < surface->mesh.num_vertices;i++, v += 3, c += 4)
+ {
+ c[0] = 0;
+ c[1] = 0;
+ c[2] = 0;
+ c[3] = surface->mesh.data_lightmapcolor4f[i*4+3] * a;
+ }
+ }
+ else
+ {
+ m.pointer_color = NULL;
+ GL_Color(0, 0, 0, a);
+ }
+ }
+ }
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ }
+ if (dobase)
+ {
+ dobase = false;
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(texture->skin.base);
+ if (waterscrolling)
+ m.texmatrix[0] = r_surf_waterscrollmatrix;
+ m.texmatrix[0] = r_surf_waterscrollmatrix;
+ m.pointer_color = varray_color4f;
+ colorscale = 1;
+ if (gl_combine.integer)
+ {
+ m.texrgbscale[0] = 4;
+ colorscale *= 0.25f;
+ }
+ r = ent->colormod[0] * colorscale;
+ g = ent->colormod[1] * colorscale;
+ b = ent->colormod[2] * colorscale;
+ a = texture->currentalpha;
+ if (dolightmap)
+ {
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ m.pointer_vertex = RSurf_GetVertexPointer(ent, surface);
+ m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
+ for (i = 0, v = m.pointer_vertex, c = varray_color4f;i < surface->mesh.num_vertices;i++, v += 3, c += 4)
+ {
+ c[0] = 0;
+ c[1] = 0;
+ c[2] = 0;
+ if (surface->styles[0] != 255)
+ {
+ if (surface->mesh.data_lightmapcolor4f)
+ {
+ float scale = d_lightstylevalue[surface->styles[0]] * (1.0f / 128.0f);
+ VectorMA(c, scale, surface->mesh.data_lightmapcolor4f + i*4, c);
+ }
+ else if (surface->mesh.data_lightmapoffsets)
+ {
+ const qbyte *lm = surface->samples + surface->mesh.data_lightmapoffsets[i];
+ float scale = d_lightstylevalue[surface->styles[0]] * (1.0f / 32768.0f);
+ VectorMA(c, scale, lm, c);
+ if (surface->styles[1] != 255)
+ {
+ int size3 = ((surface->extents[0]>>4)+1)*((surface->extents[1]>>4)+1)*3;
+ lm += size3;
+ scale = d_lightstylevalue[surface->styles[1]] * (1.0f / 32768.0f);
+ VectorMA(c, scale, lm, c);
+ if (surface->styles[2] != 255)
+ {
+ lm += size3;
+ scale = d_lightstylevalue[surface->styles[2]] * (1.0f / 32768.0f);
+ VectorMA(c, scale, lm, c);
+ if (surface->styles[3] != 255)
+ {
+ lm += size3;
+ scale = d_lightstylevalue[surface->styles[3]] * (1.0f / 32768.0f);
+ VectorMA(c, scale, lm, c);
+ }
+ }
+ }
+ }
+ }
+#ifdef LHREMOVESOON
+ if (surface->dlightframe == r_framecount)
+ {
+ // TODO: make this work with autosprite which uses identitymatrix
+ Matrix4x4_Transform(&ent->matrix, v, worldvertex);
+ for (l = 0;l < r_numdlights;l++)
+ {
+ if (surface->dlightbits[l >> 5] & (1 << (l & 31)))
+ {
+ float f2;
+ dlight_t *light = &r_dlight[l];
+ f2 = VectorDistance2(worldvertex, light->origin) + LIGHTOFFSET;
+ if (f2 < light->rtlight.lightmap_cullradius2)
+ {
+ f2 = (1.0f / f2) - light->rtlight.lightmap_subtract;
+ VectorMA(c, f2, light->rtlight.lightmap_light, c);
+ }
+ }
+ }
+ }
+#endif
+ c[0] *= r;
+ c[1] *= g;
+ c[2] *= b;
+ if (fogallpasses)
+ {
+ VectorSubtract(v, modelorg, diff);
+ f = 1 - exp(fogdensity/DotProduct(diff, diff));
+ VectorScale(c, f, c);
+ }
+ if (surface->mesh.data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
+ c[3] = surface->mesh.data_lightmapcolor4f[i*4+3] * a;
+ else
+ c[3] = a;
+ }
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ }
+ else
+ {
+ if (fogallpasses)
+ {
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ m.pointer_vertex = RSurf_GetVertexPointer(ent, surface);
+ m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
+ if (m.tex[1])
+ m.pointer_texcoord[1] = surface->mesh.data_texcoordtexture2f;
+ if (surface->mesh.data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
+ {
+ m.pointer_color = varray_color4f;
+ for (i = 0, v = m.pointer_vertex, c = varray_color4f;i < surface->mesh.num_vertices;i++, v += 3, c += 4)
+ {
+ VectorSubtract(v, modelorg, diff);
+ f = 1 - exp(fogdensity/DotProduct(diff, diff));
+ c[0] = r * f;
+ c[1] = g * f;
+ c[2] = b * f;
+ c[3] = surface->mesh.data_lightmapcolor4f[i*4+3] * a;
+ }
+ }
+ else
+ {
+ m.pointer_color = varray_color4f;
+ for (i = 0, v = m.pointer_vertex, c = varray_color4f;i < surface->mesh.num_vertices;i++, v += 3, c += 4)
+ {
+ VectorSubtract(v, modelorg, diff);
+ f = 1 - exp(fogdensity/DotProduct(diff, diff));
+ c[0] = r * f;
+ c[1] = g * f;
+ c[2] = b * f;
+ c[3] = a;
+ }
+ }
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ }
+ else
+ {
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ m.pointer_vertex = RSurf_GetVertexPointer(ent, surface);
+ m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
+ if (m.tex[1])
+ m.pointer_texcoord[1] = surface->mesh.data_texcoordtexture2f;
+ if (surface->mesh.data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
+ {
+ m.pointer_color = varray_color4f;
+ for (i = 0, v = m.pointer_vertex, c = varray_color4f;i < surface->mesh.num_vertices;i++, v += 3, c += 4)
+ {
+ c[0] = r;
+ c[1] = g;
+ c[2] = b;
+ c[3] = surface->mesh.data_lightmapcolor4f[i*4+3] * a;
+ }
+ }
+ else
+ {
+ m.pointer_color = NULL;
+ GL_Color(r, g, b, a);
+ }
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (!dolightmap && dobase)
+ {
+ dolightmap = false;
+ dobase = false;
+ GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], 1);
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(texture->skin.base);
+ if (waterscrolling)
+ m.texmatrix[0] = r_surf_waterscrollmatrix;
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ m.pointer_vertex = RSurf_GetVertexPointer(ent, surface);
+ m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ }
+ if (r_lightmapintensity <= 0 && dolightmap && dobase)
+ {
+ dolightmap = false;
+ dobase = false;
+ GL_Color(0, 0, 0, 1);
+ memset(&m, 0, sizeof(m));
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ m.pointer_vertex = RSurf_GetVertexPointer(ent, surface);
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ }
+ if (r_textureunits.integer >= 2 && gl_combine.integer && dolightmap && dobase)
+ {
+ // dualtexture combine
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ GL_DepthMask(true);
+ dolightmap = false;
+ dobase = false;
+ memset(&m, 0, sizeof(m));
+ m.tex[1] = R_GetTexture(texture->skin.base);
+ if (waterscrolling)
+ m.texmatrix[1] = r_surf_waterscrollmatrix;
+ m.texrgbscale[1] = 2;
+ r = ent->colormod[0] * r_lightmapintensity;
+ g = ent->colormod[1] * r_lightmapintensity;
+ b = ent->colormod[2] * r_lightmapintensity;
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ memset(&m, 0, sizeof(m));
+ m.tex[1] = R_GetTexture(texture->skin.base);
+ if (waterscrolling)
+ m.texmatrix[1] = r_surf_waterscrollmatrix;
+ m.texrgbscale[1] = 2;
+ m.pointer_vertex = RSurf_GetVertexPointer(ent, surface);
+ m.pointer_texcoord[0] = surface->mesh.data_texcoordlightmap2f;
+ m.pointer_texcoord[1] = surface->mesh.data_texcoordtexture2f;
+ if (surface->lightmaptexture)
+ {
+ m.tex[0] = R_GetTexture(surface->lightmaptexture);
+ m.pointer_color = NULL;
+ GL_Color(r, g, b, 1);
+ }
+ else if (r == 1 && g == 1 && b == 1)
+ {
+ m.tex[0] = R_GetTexture(r_texture_white);
+ m.pointer_color = surface->mesh.data_lightmapcolor4f;
+ }
+ else
+ {
+ m.tex[0] = R_GetTexture(r_texture_white);
+ m.pointer_color = varray_color4f;
+ for (i = 0;i < surface->mesh.num_vertices;i++)
+ {
+ varray_color4f[i*4+0] = surface->mesh.data_lightmapcolor4f[i*4+0] * r;
+ varray_color4f[i*4+1] = surface->mesh.data_lightmapcolor4f[i*4+1] * g;
+ varray_color4f[i*4+2] = surface->mesh.data_lightmapcolor4f[i*4+2] * b;
+ varray_color4f[i*4+3] = surface->mesh.data_lightmapcolor4f[i*4+3];
+ }
+ }
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ }
+ // single texture
+ if (dolightmap)
+ {
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ GL_DepthMask(true);
+ GL_Color(1, 1, 1, 1);
+ memset(&m, 0, sizeof(m));
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ m.pointer_vertex = RSurf_GetVertexPointer(ent, surface);
+ m.tex[0] = R_GetTexture(surface->lightmaptexture);
+ m.pointer_texcoord[0] = surface->mesh.data_texcoordlightmap2f;
+ if (surface->lightmaptexture)
+ m.pointer_color = NULL;
+ else
+ m.pointer_color = surface->mesh.data_lightmapcolor4f;
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ }
+ if (dobase)
+ {
+ 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(texture->skin.base);
+ if (waterscrolling)
+ m.texmatrix[0] = r_surf_waterscrollmatrix;
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ m.pointer_vertex = RSurf_GetVertexPointer(ent, surface);
+ m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ 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_surf_waterscrollmatrix;
+ m.pointer_color = varray_color4f;
+ colorscale = 1;
+ if (gl_combine.integer)
+ {
+ m.texrgbscale[0] = 4;
+ colorscale *= 0.25f;
+ }
+ base = r_ambient.value * (1.0f / 64.0f);
+ r = ent->colormod[0] * colorscale * base;
+ g = ent->colormod[1] * colorscale * base;
+ b = ent->colormod[2] * colorscale * base;
+ a = texture->currentalpha;
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ m.pointer_vertex = RSurf_GetVertexPointer(ent, surface);
+ m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
+ for (i = 0, v = m.pointer_vertex, c = varray_color4f;i < surface->mesh.num_vertices;i++, v += 3, c += 4)
+ {
+ c[0] = r;
+ c[1] = g;
+ c[2] = b;
+ if (fogallpasses)
+ {
+ VectorSubtract(v, modelorg, diff);
+ f = 1 - exp(fogdensity/DotProduct(diff, diff));
+ VectorScale(c, f, c);
+ }
+ if (surface->mesh.data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
+ c[3] = surface->mesh.data_lightmapcolor4f[i*4+3] * a;
+ else
+ c[3] = a;
+ }
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ }
+ // marklights based vertex dlight rendering... evil and broken
+#if 0
+ GL_BlendFunc(GL_ONE, GL_ONE);
+ GL_DepthMask(false);
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(texture->skin.base);
+ if (waterscrolling)
+ m.texmatrix[0] = r_surf_waterscrollmatrix;
+ m.pointer_color = varray_color4f;
+ r = ent->colormod[0] * r_lightmapintensity;
+ g = ent->colormod[1] * r_lightmapintensity;
+ b = ent->colormod[2] * r_lightmapintensity;
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ qboolean lit;
+ surface = texturesurfacelist[texturesurfaceindex];
+ if (surface->dlightframe != r_framecount)
+ continue;
+ m.pointer_vertex = RSurf_GetVertexPointer(ent, surface);
+ m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
+ lit = false;
+ for (i = 0, v = m.pointer_vertex, c = varray_color4f;i < surface->mesh.num_vertices;i++, v += 3, c += 4)
+ {
+ c[0] = 0;
+ c[1] = 0;
+ c[2] = 0;
+ c[3] = 1;
+ // TODO: make this work with autosprite which uses identitymatrix or change autosprite
+ Matrix4x4_Transform(&ent->matrix, v, worldvertex);
+ for (l = 0;l < r_numdlights;l++)
+ {
+ if (surface->dlightbits[l >> 5] & (1 << (l & 31)))
+ {
+ float f2;
+ dlight_t *light = &r_dlight[l];
+ f2 = VectorDistance2(worldvertex, light->origin) + LIGHTOFFSET;
+ if (f2 < light->rtlight.lightmap_cullradius2)
+ {
+ f2 = (1.0f / f2) - light->rtlight.lightmap_subtract;
+ VectorMA(c, f2, light->rtlight.lightmap_light, c);
+ lit = true;
+ }
+ }
+ }
+ c[0] *= r;
+ c[1] *= g;
+ c[2] *= b;
+ if (fogallpasses)
+ {
+ VectorSubtract(v, modelorg, diff);
+ f = 1 - exp(fogdensity/DotProduct(diff, diff));
+ VectorScale(c, f, c);
+ }
+ if (surface->mesh.data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
+ c[3] = surface->mesh.data_lightmapcolor4f[i*4+3] * a;
+ else
+ c[3] = a;
+ }
+ if (!lit)
+ continue;
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+#endif
+ 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);
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ m.pointer_vertex = RSurf_GetVertexPointer(ent, surface);
+ m.pointer_texcoord[0] = surface->mesh.data_texcoorddetail2f;
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ 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_surf_waterscrollmatrix;
+ m.pointer_color = varray_color4f;
+ colorscale = 1;
+ r = ent->colormod[0] * colorscale;
+ g = ent->colormod[1] * colorscale;
+ b = ent->colormod[2] * colorscale;
+ a = texture->currentalpha;
+ if (fogallpasses)
+ {
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ m.pointer_vertex = RSurf_GetVertexPointer(ent, surface);
+ m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
+ if (surface->mesh.data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
+ {
+ m.pointer_color = varray_color4f;
+ for (i = 0, v = m.pointer_vertex, c = varray_color4f;i < surface->mesh.num_vertices;i++, v += 3, c += 4)
+ {
+ VectorSubtract(v, modelorg, diff);
+ f = 1 - exp(fogdensity/DotProduct(diff, diff));
+ c[0] = f * r;
+ c[1] = f * g;
+ c[2] = f * b;
+ c[3] = surface->mesh.data_lightmapcolor4f[i*4+3] * a;
+ }
+ }
+ else
+ {
+ m.pointer_color = varray_color4f;
+ for (i = 0, v = m.pointer_vertex, c = varray_color4f;i < surface->mesh.num_vertices;i++, v += 3, c += 4)
+ {
+ VectorSubtract(v, modelorg, diff);
+ f = 1 - exp(fogdensity/DotProduct(diff, diff));
+ c[0] = f * r;
+ c[1] = f * g;
+ c[2] = f * b;
+ c[3] = a;
+ }
+ }
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ }
+ else
+ {
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ m.pointer_vertex = RSurf_GetVertexPointer(ent, surface);
+ m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
+ if (surface->mesh.data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
+ {
+ m.pointer_color = varray_color4f;
+ for (i = 0, v = m.pointer_vertex, c = varray_color4f;i < surface->mesh.num_vertices;i++, v += 3, c += 4)
+ {
+ c[0] = r;
+ c[1] = g;
+ c[2] = b;
+ c[3] = surface->mesh.data_lightmapcolor4f[i*4+3] * a;
+ }
+ }
+ else
+ {
+ m.pointer_color = NULL;
+ GL_Color(r, g, b, a);
+ }
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ 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_surf_waterscrollmatrix;
+ r = fogcolor[0];
+ g = fogcolor[1];
+ b = fogcolor[2];
+ a = texture->currentalpha;
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ m.pointer_vertex = RSurf_GetVertexPointer(ent, surface);
+ m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
+ m.pointer_color = varray_color4f;
+ //RSurf_FogPassColors_Vertex3f_Color4f(surface->mesh.data_vertex3f, varray_color4f, fogcolor[0], fogcolor[1], fogcolor[2], texture->currentalpha, 1, surface->mesh.num_vertices, modelorg);
+ if (surface->mesh.data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
+ {
+ m.pointer_color = varray_color4f;
+ for (i = 0, v = m.pointer_vertex, c = varray_color4f;i < surface->mesh.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->mesh.data_lightmapcolor4f[i*4+3] * f * a;
+ }
+ }
+ else
+ {
+ m.pointer_color = varray_color4f;
+ for (i = 0, v = m.pointer_vertex, c = varray_color4f;i < surface->mesh.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;
+ }
+ }
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ }
+ }
+ if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
+ qglEnable(GL_CULL_FACE);
+}
+
+static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata2)
+{
+ const entity_render_t *ent = calldata1;
+ const msurface_t *surface = ent->model->brush.data_surfaces + calldata2;
+ vec3_t modelorg;
+ texture_t *texture;
+#ifdef LHREMOVESOON
+ rmeshstate_t m;
+ float base, colorscale;
+ float args[4] = {0.05f,0,0,0.04f};
+ matrix4x4_t scrollmatrix;
+#endif
+
+ texture = surface->texture;
+ if (texture->basematerialflags & MATERIALFLAG_SKY)
+ return; // transparent sky is too difficult
+ R_UpdateTextureInfo(ent, texture);
+
+ R_Mesh_Matrix(&ent->matrix);
+ Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
+ R_DrawSurfaceList(ent, texture, 1, &surface, modelorg);
+#ifdef LHREMOVESOON
+ GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
+ GL_DepthMask(!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT));
+ if (texture->currentmaterialflags & MATERIALFLAG_ADD)
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+ else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ else
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+
+ // water scrolling in texture matrix
+ if ((texture->currentmaterialflags & MATERIALFLAG_WATER) && r_waterscroll.value != 0)
+ Matrix4x4_CreateTranslate(&scrollmatrix, sin(r_refdef.time) * 0.025 * r_waterscroll.value, sin(r_refdef.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
+ else
+ scrollmatrix = r_identitymatrix;
+
+ if (surface->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
+ qglDisable(GL_CULL_FACE);
+ if ((texture->currentmaterialflags & MATERIALFLAG_WATER) && r_watershader.value && gl_textureshader && !texture->skin.glow && !fogenabled && ent->colormod[0] == 1 && ent->colormod[1] == 1 && ent->colormod[2] == 1)
+ {
+ // NVIDIA Geforce3 distortion texture shader on water
+ GL_Color(1, 1, 1, texture->currentalpha);
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = RSurf_GetVertexPointer(ent, surface);
+ m.tex[0] = R_GetTexture(mod_shared_distorttexture[(int)(r_refdef.time * 16)&63]);
+ m.tex[1] = R_GetTexture(texture->skin.base);
+ m.texcombinergb[0] = GL_REPLACE;
+ m.texcombinergb[1] = GL_REPLACE;
+ m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
+ m.pointer_texcoord[1] = surface->mesh.data_texcoordtexture2f;
+ Matrix4x4_CreateFromQuakeEntity(&m.texmatrix[0], 0, 0, 0, 0, 0, 0, r_watershader.value);
+ m.texmatrix[1] = scrollmatrix;
+ R_Mesh_State(&m);
+
+ GL_ActiveTexture(0);
+ qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
+ GL_ActiveTexture(1);
+ qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_OFFSET_TEXTURE_2D_NV);
+ qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB);
+ qglTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, &args[0]);
+ qglEnable(GL_TEXTURE_SHADER_NV);
+
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+
+ qglDisable(GL_TEXTURE_SHADER_NV);
+ qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
+ GL_ActiveTexture(0);
+ }
+ else
+ {
+ int i;
+ float r, g, b, a, f, *c, diff[3];
+ const float *v;
+ qboolean dolightmaptexture;
+ qboolean dodetail;
+ qboolean doglow;
+ dolightmaptexture = surface->lightmaptexture && gl_combine.integer && !(texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT);
+ dodetail = texture->skin.detail != NULL && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT);
+ doglow = texture->skin.glow != NULL;
+ // TODO: ideally transparent surface rendering should call
+ // R_RenderLighting instead of using vertex dlights
+ // (it would need scrolling support added though!)
+ if (dolightmaptexture)
+ {
+ {
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = RSurf_GetVertexPointer(ent, surface);
+ m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
+ m.tex[0] = R_GetTexture(texture->skin.base);
+ m.texmatrix[0] = scrollmatrix;
+ m.pointer_texcoord[1] = surface->mesh.data_texcoordlightmap2f;
+ m.tex[1] = R_GetTexture(surface->lightmaptexture);
+ m.texrgbscale[1] = 2;
+ m.pointer_color = varray_color4f;
+ if (r_textureunits.integer >= 3 && dodetail)
+ {
+ dodetail = false;
+ m.pointer_texcoord[2] = surface->mesh.data_texcoorddetail2f;
+ m.tex[2] = R_GetTexture(texture->skin.detail);
+ m.texmatrix[2] = scrollmatrix;
+ if (r_textureunits.integer >= 4 && doglow)
+ {
+ doglow = false;
+ m.pointer_texcoord[3] = surface->mesh.data_texcoordtexture2f;
+ m.tex[3] = R_GetTexture(texture->skin.glow);
+ m.texmatrix[3] = scrollmatrix;
+ }
+ }
+ else if (r_textureunits.integer >= 3 && doglow && !dodetail)
+ {
+ doglow = false;
+ m.pointer_texcoord[2] = surface->mesh.data_texcoordtexture2f;
+ m.tex[2] = R_GetTexture(texture->skin.glow);
+ m.texmatrix[2] = scrollmatrix;
+ }
+ colorscale = 1;
+ r = ent->colormod[0] * colorscale;
+ g = ent->colormod[1] * colorscale;
+ b = ent->colormod[2] * colorscale;
+ a = texture->currentalpha;
+ for (i = 0, v = m.pointer_vertex, c = varray_color4f;i < surface->mesh.num_vertices;i++, v += 3, c += 4)
+ {
+ c[0] = r;
+ c[1] = g;
+ c[2] = b;
+ if (fogenabled)
+ {
+ VectorSubtract(v, modelorg, diff);
+ f = 1 - exp(fogdensity/DotProduct(diff, diff));
+ VectorScale(c, f, c);
+ }
+ if (surface->mesh.data_lightmapcolor4f)
+ c[3] = surface->mesh.data_lightmapcolor4f[i*4+3] * a;
+ else
+ c[3] = a;
+ }
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ if ((r_ambient.value > 0 || surface->dlightframe == r_framecount) && !(texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
+ {
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+ GL_DepthMask(false);
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = RSurf_GetVertexPointer(ent, surface);
+ m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
+ m.tex[0] = R_GetTexture(texture->skin.base);
+ m.texmatrix[0] = scrollmatrix;
+ m.pointer_color = varray_color4f;
+ colorscale = 1;
+ if (gl_combine.integer)
+ {
+ m.texrgbscale[0] = 4;
+ colorscale *= 0.25f;
+ }
+ r = ent->colormod[0] * colorscale;
+ g = ent->colormod[1] * colorscale;
+ b = ent->colormod[2] * colorscale;
+ a = texture->currentalpha;
+ base = r_ambient.value * (1.0f / 64.0f);
+ for (i = 0, v = m.pointer_vertex, c = varray_color4f;i < surface->mesh.num_vertices;i++, v += 3, c += 4)
+ {
+ c[0] = base;
+ c[1] = base;
+ c[2] = base;
+ if (surface->dlightframe == r_framecount)
+ {
+ // TODO: make this work with autosprite which uses identitymatrix
+ Matrix4x4_Transform(&ent->matrix, v, worldvertex);
+ for (l = 0;l < r_numdlights;l++)
+ {
+ if (surface->dlightbits[l >> 5] & (1 << (l & 31)))
+ {
+ float f2;
+ dlight_t *light = &r_dlight[l];
+ f2 = VectorDistance2(worldvertex, light->origin) + LIGHTOFFSET;
+ if (f2 < light->rtlight.lightmap_cullradius2)
+ {
+ f2 = (1.0f / f2) - light->rtlight.lightmap_subtract;
+ VectorMA(c, f2, light->rtlight.lightmap_light, c);
+ }
+ }
+ }
+ }
+ c[0] *= r;
+ c[1] *= g;
+ c[2] *= b;
+ if (fogenabled)
+ {
+ VectorSubtract(v, modelorg, diff);
+ f = 1 - exp(fogdensity/DotProduct(diff, diff));
+ VectorScale(c, f, c);
+ }
+ if (surface->mesh.data_lightmapcolor4f)
+ c[3] = surface->mesh.data_lightmapcolor4f[i*4+3] * a;
+ else
+ c[3] = a;
+ }
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ }
+ else
+ {
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = RSurf_GetVertexPointer(ent, surface);
+ m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
+ m.tex[0] = R_GetTexture(texture->skin.base);
+ m.texmatrix[0] = scrollmatrix;
+ m.pointer_color = varray_color4f;
+ colorscale = 1;
+ if (gl_combine.integer)
+ {
+ m.texrgbscale[0] = 4;
+ colorscale *= 0.25f;
+ }
+ if (doglow)
+ {
+ doglow = false;
+ m.pointer_texcoord[1] = surface->mesh.data_texcoordtexture2f;
+ m.tex[1] = R_GetTexture(texture->skin.glow);
+ m.texmatrix[1] = scrollmatrix;
+ }
+ r = ent->colormod[0] * colorscale;
+ g = ent->colormod[1] * colorscale;
+ b = ent->colormod[2] * colorscale;
+ a = texture->currentalpha;
+ base = r_ambient.value * (1.0f / 64.0f);
+ if ((ent->flags & RENDER_LIGHT) && !(texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
+ {
+ for (i = 0, v = m.pointer_vertex, c = varray_color4f;i < surface->mesh.num_vertices;i++, v += 3, c += 4)
+ {
+ c[0] = base;
+ c[1] = base;
+ c[2] = base;
+ if (surface->styles[0] != 255)
+ {
+ if (surface->mesh.data_lightmapcolor4f)
+ {
+ float scale = d_lightstylevalue[surface->styles[0]] * (1.0f / 128.0f);
+ VectorMA(c, scale, surface->mesh.data_lightmapcolor4f + i*4, c);
+ }
+ else if (surface->mesh.data_lightmapoffsets)
+ {
+ const qbyte *lm = surface->samples + surface->mesh.data_lightmapoffsets[i];
+ float scale = d_lightstylevalue[surface->styles[0]] * (1.0f / 32768.0f);
+ VectorMA(c, scale, lm, c);
+ if (surface->styles[1] != 255)
+ {
+ int size3 = ((surface->extents[0]>>4)+1)*((surface->extents[1]>>4)+1)*3;
+ lm += size3;
+ scale = d_lightstylevalue[surface->styles[1]] * (1.0f / 32768.0f);
+ VectorMA(c, scale, lm, c);
+ if (surface->styles[2] != 255)
+ {
+ lm += size3;
+ scale = d_lightstylevalue[surface->styles[2]] * (1.0f / 32768.0f);
+ VectorMA(c, scale, lm, c);
+ if (surface->styles[3] != 255)
+ {
+ lm += size3;
+ scale = d_lightstylevalue[surface->styles[3]] * (1.0f / 32768.0f);
+ VectorMA(c, scale, lm, c);
+ }
+ }
+ }
+ }
+ }
+ if (surface->dlightframe == r_framecount)
+ {
+ // TODO: make this work with autosprite which uses identitymatrix
+ Matrix4x4_Transform(&ent->matrix, v, worldvertex);
+ for (l = 0;l < r_numdlights;l++)
+ {
+ if (surface->dlightbits[l >> 5] & (1 << (l & 31)))
+ {
+ float f2;
+ dlight_t *light = &r_dlight[l];
+ f2 = VectorDistance2(worldvertex, light->origin) + LIGHTOFFSET;
+ if (f2 < light->rtlight.lightmap_cullradius2)
+ {
+ f2 = (1.0f / f2) - light->rtlight.lightmap_subtract;
+ VectorMA(c, f2, light->rtlight.lightmap_light, c);
+ }
+ }
+ }
+ }
+ c[0] *= r;
+ c[1] *= g;
+ c[2] *= b;
+ if (fogenabled)
+ {
+ VectorSubtract(v, modelorg, diff);
+ f = 1 - exp(fogdensity/DotProduct(diff, diff));
+ VectorScale(c, f, c);
+ }
+ if (surface->mesh.data_lightmapcolor4f)
+ c[3] = surface->mesh.data_lightmapcolor4f[i*4+3] * a;
+ else
+ c[3] = a;
+ }
+ }
+ else
+ {
+ if (fogenabled)
+ {
+ if (surface->mesh.data_lightmapcolor4f)
+ {
+ for (i = 0, v = m.pointer_vertex, c = varray_color4f;i < surface->mesh.num_vertices;i++, v += 3, c += 4)
+ {
+ VectorSubtract(v, modelorg, diff);
+ f = 1 - exp(fogdensity/DotProduct(diff, diff));
+ c[0] = r * f;
+ c[1] = g * f;
+ c[2] = b * f;
+ c[3] = surface->mesh.data_lightmapcolor4f[i*4+3] * a;
+ }
+ }
+ else
+ {
+ for (i = 0, v = m.pointer_vertex, c = varray_color4f;i < surface->mesh.num_vertices;i++, v += 3, c += 4)
+ {
+ VectorSubtract(v, modelorg, diff);
+ f = 1 - exp(fogdensity/DotProduct(diff, diff));
+ c[0] = r * f;
+ c[1] = g * f;
+ c[2] = b * f;
+ c[3] = a;
+ }
+ }
+ }
+ else
+ {
+ if (surface->mesh.data_lightmapcolor4f)
+ {
+ for (i = 0, v = m.pointer_vertex, c = varray_color4f;i < surface->mesh.num_vertices;i++, v += 3, c += 4)
+ {
+ c[0] = r;
+ c[1] = g;
+ c[2] = b;
+ c[3] = surface->mesh.data_lightmapcolor4f[i*4+3] * a;
+ }
+ }
+ else
+ {
+ m.pointer_color = NULL;
+ GL_Color(r, g, b, a);
+ }
+ }
+ }
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ // note: dodetail is never set if transparent
+ if (dodetail)
+ {
+ GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
+ GL_DepthMask(false);
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = RSurf_GetVertexPointer(ent, surface);
+ m.pointer_texcoord[0] = surface->mesh.data_texcoorddetail2f;
+ m.tex[0] = R_GetTexture(texture->skin.detail);
+ m.pointer_color = varray_color4f;
+ RSurf_FoggedColors_Vertex3f_Color4f(surface->mesh.data_vertex3f, varray_color4f, ent->colormod[0], ent->colormod[1], ent->colormod[2], texture->currentalpha, 1, surface->mesh.num_vertices, modelorg);
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ if (doglow)
+ {
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+ GL_DepthMask(false);
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = RSurf_GetVertexPointer(ent, surface);
+ m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
+ m.tex[0] = R_GetTexture(texture->skin.glow);
+ m.texmatrix[0] = scrollmatrix;
+ m.pointer_color = varray_color4f;
+ RSurf_FoggedColors_Vertex3f_Color4f(surface->mesh.data_vertex3f, varray_color4f, ent->colormod[0], ent->colormod[1], ent->colormod[2], texture->currentalpha, 1, surface->mesh.num_vertices, modelorg);
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ if (fogenabled && !(texture->currentmaterialflags & MATERIALFLAG_ADD))
+ {
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+ GL_DepthMask(false);
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = RSurf_GetVertexPointer(ent, surface);
+ m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
+ m.tex[0] = R_GetTexture(texture->skin.fog);
+ m.texmatrix[0] = scrollmatrix;
+ m.pointer_color = varray_color4f;
+ RSurf_FogPassColors_Vertex3f_Color4f(surface->mesh.data_vertex3f, varray_color4f, fogcolor[0], fogcolor[1], fogcolor[2], texture->currentalpha, 1, surface->mesh.num_vertices, modelorg);
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ }
+ if (surface->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
+ qglEnable(GL_CULL_FACE);
+#endif
+}
+
+#ifdef LHREMOVESOON
+void R_DrawSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, msurface_t **texturesurfacelist)
+{
+ int texturesurfaceindex;
+ vec3_t tempcenter, center, modelorg;
+ msurface_t *surface;
+ qboolean dolightmap;
+ qboolean dobase;
+ qboolean doambient;
+ qboolean dodetail;
+ qboolean doglow;
+ qboolean dofog;
+ rmeshstate_t m;
+ Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
+ c_faces += texturenumsurfaces;
+ // gl_lightmaps debugging mode skips normal texturing
+ if (gl_lightmaps.integer)
+ {
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ GL_DepthMask(true);
+ GL_DepthTest(true);
+ qglDisable(GL_CULL_FACE);
+ GL_Color(1, 1, 1, 1);
+ memset(&m, 0, sizeof(m));
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ m.tex[0] = R_GetTexture(surface->lightmaptexture);
+ m.pointer_texcoord[0] = surface->mesh.data_texcoordlightmap2f;
+ if (surface->lightmaptexture)
+ {
+ GL_Color(1, 1, 1, 1);
+ m.pointer_color = NULL;
+ }
+ else
+ m.pointer_color = surface->mesh.data_lightmapcolor4f;
+ m.pointer_vertex = surface->mesh.data_vertex3f;
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ qglEnable(GL_CULL_FACE);
+ return;
+ }
+ if (texture->currentmaterialflags & MATERIALFLAG_WALL)
+ {
+ dolightmap = (ent->flags & RENDER_LIGHT);
+ dobase = true;
+ doambient = r_ambient.value > 0;
+ dodetail = texture->skin.detail != NULL && r_detailtextures.integer != 0;
+ doglow = texture->skin.glow != NULL;
+ dofog = fogenabled;
+ // multitexture cases
+ if (r_textureunits.integer >= 2 && gl_combine.integer && dobase && dolightmap)
+ {
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ GL_DepthMask(true);
+ GL_DepthTest(true);
+ GL_Color(1, 1, 1, 1);
+ 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(texture->skin.base);
+ dobase = false;
+ m.texrgbscale[1] = 2;
+ dolightmap = false;
+ if (r_textureunits.integer >= 4 && !doambient && dodetail && doglow)
+ {
+ m.tex[2] = R_GetTexture(texture->skin.detail);
+ m.texrgbscale[2] = 2;
+ dodetail = false;
+ m.tex[3] = R_GetTexture(texture->skin.glow);
+ m.texcombinergb[3] = GL_ADD;
+ doglow = false;