- if (dodiffusebase)
- {
- GL_Color(1,1,1,1);
- colorscale = r_shadow_rtlight->diffusescale;
- // colorscale accounts for how much we multiply the brightness
- // during combine.
- //
- // mult is how many times the final pass of the lighting will be
- // performed to get more brightness than otherwise possible.
- //
- // Limit mult to 64 for sanity sake.
- if (r_shadow_texture3d.integer && r_textureunits.integer >= 4)
- {
- // 3/2 3D combine path (Geforce3, Radeon 8500)
- memset(&m, 0, sizeof(m));
- m.pointer_vertex = rsurface_vertex3f;
- m.tex[0] = R_GetTexture(normalmaptexture);
- m.texcombinergb[0] = GL_REPLACE;
- m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
- m.texmatrix[0] = texture->currenttexmatrix;
- m.texcubemap[1] = R_GetTexture(r_texture_normalizationcube);
- m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
- m.pointer_texcoord3f[1] = varray_texcoord3f[1];
- R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, rsurface_svector3f + 3 * surface->num_firstvertex, rsurface_tvector3f + 3 * surface->num_firstvertex, rsurface_normal3f + 3 * surface->num_firstvertex, r_shadow_entitylightorigin);
- m.tex3d[2] = R_GetTexture(r_shadow_attenuation3dtexture);
-#ifdef USETEXMATRIX
- m.pointer_texcoord3f[2] = rsurface_vertex3f;
- m.texmatrix[2] = r_shadow_entitytoattenuationxyz;
-#else
- m.pointer_texcoord3f[2] = varray_texcoord3f[2];
- R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[2] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationxyz);
-#endif
- R_Mesh_State(&m);
- GL_ColorMask(0,0,0,1);
- GL_BlendFunc(GL_ONE, GL_ZERO);
- GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
- R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
- GL_LockArrays(0, 0);
- c_rt_lightmeshes++;
- c_rt_lighttris += surface->num_triangles;
-
- memset(&m, 0, sizeof(m));
- m.pointer_vertex = rsurface_vertex3f;
- m.tex[0] = R_GetTexture(basetexture);
- m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
- m.texmatrix[0] = texture->currenttexmatrix;
- if (r_shadow_lightcubemap != r_texture_whitecube)
- {
- m.texcubemap[1] = R_GetTexture(r_shadow_lightcubemap);
-#ifdef USETEXMATRIX
- m.pointer_texcoord3f[1] = rsurface_vertex3f;
- m.texmatrix[1] = r_shadow_entitytolight;
-#else
- m.pointer_texcoord3f[1] = varray_texcoord3f[1];
- R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytolight);
-#endif
- }
- GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
- }
- else if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && r_shadow_lightcubemap != r_texture_whitecube)
- {
- // 1/2/2 3D combine path (original Radeon)
- memset(&m, 0, sizeof(m));
- m.pointer_vertex = rsurface_vertex3f;
- m.tex3d[0] = R_GetTexture(r_shadow_attenuation3dtexture);
-#ifdef USETEXMATRIX
- m.pointer_texcoord3f[0] = rsurface_vertex3f;
- m.texmatrix[0] = r_shadow_entitytoattenuationxyz;
-#else
- m.pointer_texcoord3f[0] = varray_texcoord3f[0];
- R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[0] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationxyz);
-#endif
- R_Mesh_State(&m);
- GL_ColorMask(0,0,0,1);
- GL_BlendFunc(GL_ONE, GL_ZERO);
- GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
- R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
- GL_LockArrays(0, 0);
- c_rt_lightmeshes++;
- c_rt_lighttris += surface->num_triangles;
-
- memset(&m, 0, sizeof(m));
- m.pointer_vertex = rsurface_vertex3f;
- m.tex[0] = R_GetTexture(normalmaptexture);
- m.texcombinergb[0] = GL_REPLACE;
- m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
- m.texmatrix[0] = texture->currenttexmatrix;
- m.texcubemap[1] = R_GetTexture(r_texture_normalizationcube);
- m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
- m.pointer_texcoord3f[1] = varray_texcoord3f[1];
- R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, rsurface_svector3f + 3 * surface->num_firstvertex, rsurface_tvector3f + 3 * surface->num_firstvertex, rsurface_normal3f + 3 * surface->num_firstvertex, r_shadow_entitylightorigin);
- R_Mesh_State(&m);
- GL_BlendFunc(GL_DST_ALPHA, GL_ZERO);
- GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
- R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
- GL_LockArrays(0, 0);
- c_rt_lightmeshes++;
- c_rt_lighttris += surface->num_triangles;
-
- memset(&m, 0, sizeof(m));
- m.pointer_vertex = rsurface_vertex3f;
- m.tex[0] = R_GetTexture(basetexture);
- m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
- m.texmatrix[0] = texture->currenttexmatrix;
- if (r_shadow_lightcubemap != r_texture_whitecube)
- {
- m.texcubemap[1] = R_GetTexture(r_shadow_lightcubemap);
-#ifdef USETEXMATRIX
- m.pointer_texcoord3f[1] = rsurface_vertex3f;
- m.texmatrix[1] = r_shadow_entitytolight;
-#else
- m.pointer_texcoord3f[1] = varray_texcoord3f[1];
- R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytolight);
-#endif
- }
- GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
- }
- else if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && r_shadow_lightcubemap == r_texture_whitecube)
+ GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
+ }
+ else if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && r_shadow_rtlight->currentcubemap == r_texture_whitecube)
+ {
+ // 2/2 3D combine path (original Radeon)
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(normalmaptexture);
+ m.texcombinergb[0] = GL_REPLACE;
+ m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
+ m.texmatrix[0] = rsurface_texture->currenttexmatrix;
+ m.texcubemap[1] = R_GetTexture(r_texture_normalizationcube);
+ m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
+ m.pointer_texcoord3f[1] = rsurface_array_texcoord3f;
+ R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(rsurface_array_texcoord3f + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, rsurface_svector3f + 3 * surface->num_firstvertex, rsurface_tvector3f + 3 * surface->num_firstvertex, rsurface_normal3f + 3 * surface->num_firstvertex, r_shadow_entitylightorigin);
+ R_Mesh_TextureState(&m);
+ GL_ColorMask(0,0,0,1);
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+ GL_LockArrays(0, 0);
+
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(basetexture);
+ m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
+ m.texmatrix[0] = rsurface_texture->currenttexmatrix;
+ m.tex3d[1] = R_GetTexture(r_shadow_attenuation3dtexture);
+ m.pointer_texcoord3f[1] = rsurface_vertex3f;
+ m.texmatrix[1] = r_shadow_entitytoattenuationxyz;
+ GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
+ }
+ else if (r_textureunits.integer >= 4)
+ {
+ // 4/2 2D combine path (Geforce3, Radeon 8500)
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(normalmaptexture);
+ m.texcombinergb[0] = GL_REPLACE;
+ m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
+ m.texmatrix[0] = rsurface_texture->currenttexmatrix;
+ m.texcubemap[1] = R_GetTexture(r_texture_normalizationcube);
+ m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
+ m.pointer_texcoord3f[1] = rsurface_array_texcoord3f;
+ R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(rsurface_array_texcoord3f + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, rsurface_svector3f + 3 * surface->num_firstvertex, rsurface_tvector3f + 3 * surface->num_firstvertex, rsurface_normal3f + 3 * surface->num_firstvertex, r_shadow_entitylightorigin);
+ m.tex[2] = R_GetTexture(r_shadow_attenuation2dtexture);
+ m.pointer_texcoord3f[2] = rsurface_vertex3f;
+ m.texmatrix[2] = r_shadow_entitytoattenuationxyz;
+ m.tex[3] = R_GetTexture(r_shadow_attenuation2dtexture);
+ m.pointer_texcoord3f[3] = rsurface_vertex3f;
+ m.texmatrix[3] = r_shadow_entitytoattenuationz;
+ R_Mesh_TextureState(&m);
+ GL_ColorMask(0,0,0,1);
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+ GL_LockArrays(0, 0);
+
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(basetexture);
+ m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
+ m.texmatrix[0] = rsurface_texture->currenttexmatrix;
+ if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
+ {
+ m.texcubemap[1] = R_GetTexture(r_shadow_rtlight->currentcubemap);
+ m.pointer_texcoord3f[1] = rsurface_vertex3f;
+ m.texmatrix[1] = r_shadow_entitytolight;
+ }
+ GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
+ }
+ else
+ {
+ // 2/2/2 2D combine path (any dot3 card)
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(r_shadow_attenuation2dtexture);
+ m.pointer_texcoord3f[0] = rsurface_vertex3f;
+ m.texmatrix[0] = r_shadow_entitytoattenuationxyz;
+ m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture);
+ m.pointer_texcoord3f[1] = rsurface_vertex3f;
+ m.texmatrix[1] = r_shadow_entitytoattenuationz;
+ R_Mesh_TextureState(&m);
+ GL_ColorMask(0,0,0,1);
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+ GL_LockArrays(0, 0);
+
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(normalmaptexture);
+ m.texcombinergb[0] = GL_REPLACE;
+ m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
+ m.texmatrix[0] = rsurface_texture->currenttexmatrix;
+ m.texcubemap[1] = R_GetTexture(r_texture_normalizationcube);
+ m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
+ m.pointer_texcoord3f[1] = rsurface_array_texcoord3f;
+ R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(rsurface_array_texcoord3f + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, rsurface_svector3f + 3 * surface->num_firstvertex, rsurface_tvector3f + 3 * surface->num_firstvertex, rsurface_normal3f + 3 * surface->num_firstvertex, r_shadow_entitylightorigin);
+ R_Mesh_TextureState(&m);
+ GL_BlendFunc(GL_DST_ALPHA, GL_ZERO);
+ GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+ GL_LockArrays(0, 0);
+
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(basetexture);
+ m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
+ m.texmatrix[0] = rsurface_texture->currenttexmatrix;
+ if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
+ {
+ m.texcubemap[1] = R_GetTexture(r_shadow_rtlight->currentcubemap);
+ m.pointer_texcoord3f[1] = rsurface_vertex3f;
+ m.texmatrix[1] = r_shadow_entitytolight;
+ }
+ GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
+ }
+ // this final code is shared
+ R_Mesh_TextureState(&m);
+ GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 0);
+ VectorScale(lightcolorbase, colorscale, color2);
+ GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--)
+ {
+ GL_Color(bound(0, color2[0], 1), bound(0, color2[1], 1), bound(0, color2[2], 1), 1);
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+ }
+ GL_LockArrays(0, 0);
+}
+
+static void R_Shadow_RenderSurfacesLighting_Light_Dot3_SpecularPass(const msurface_t *surface, const vec3_t lightcolorbase, rtexture_t *glosstexture, rtexture_t *normalmaptexture, float colorscale)
+{
+ int renders;
+ float color2[3];
+ rmeshstate_t m;
+ const int *elements = rsurface_model->surfmesh.data_element3i + surface->num_firsttriangle * 3;
+ // FIXME: detect blendsquare!
+ //if (!gl_support_blendsquare)
+ // return;
+ GL_Color(1,1,1,1);
+ if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && r_shadow_rtlight->currentcubemap != r_texture_whitecube /* && gl_support_blendsquare*/) // FIXME: detect blendsquare!
+ {
+ // 2/0/0/1/2 3D combine blendsquare path
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(normalmaptexture);
+ m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
+ m.texmatrix[0] = rsurface_texture->currenttexmatrix;
+ m.texcubemap[1] = R_GetTexture(r_texture_normalizationcube);
+ m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
+ m.pointer_texcoord3f[1] = rsurface_array_texcoord3f;
+ R_Shadow_GenTexCoords_Specular_NormalCubeMap(rsurface_array_texcoord3f + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, rsurface_svector3f + 3 * surface->num_firstvertex, rsurface_tvector3f + 3 * surface->num_firstvertex, rsurface_normal3f + 3 * surface->num_firstvertex, r_shadow_entitylightorigin, r_shadow_entityeyeorigin);
+ R_Mesh_TextureState(&m);
+ GL_ColorMask(0,0,0,1);
+ // this squares the result
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ZERO);
+ GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+ GL_LockArrays(0, 0);
+
+ R_Mesh_ResetTextureState();
+ GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ // square alpha in framebuffer a few times to make it shiny
+ GL_BlendFunc(GL_ZERO, GL_DST_ALPHA);
+ // these comments are a test run through this math for intensity 0.5
+ // 0.5 * 0.5 = 0.25 (done by the BlendFunc earlier)
+ // 0.25 * 0.25 = 0.0625 (this is another pass)
+ // 0.0625 * 0.0625 = 0.00390625 (this is another pass)
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+ GL_LockArrays(0, 0);
+
+ memset(&m, 0, sizeof(m));
+ m.tex3d[0] = R_GetTexture(r_shadow_attenuation3dtexture);
+ m.pointer_texcoord3f[0] = rsurface_vertex3f;
+ m.texmatrix[0] = r_shadow_entitytoattenuationxyz;
+ R_Mesh_TextureState(&m);
+ GL_BlendFunc(GL_DST_ALPHA, GL_ZERO);
+ GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+ GL_LockArrays(0, 0);
+
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(glosstexture);
+ m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
+ m.texmatrix[0] = rsurface_texture->currenttexmatrix;
+ if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
+ {
+ m.texcubemap[1] = R_GetTexture(r_shadow_rtlight->currentcubemap);
+ m.pointer_texcoord3f[1] = rsurface_vertex3f;
+ m.texmatrix[1] = r_shadow_entitytolight;
+ }
+ GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
+ }
+ else if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && r_shadow_rtlight->currentcubemap == r_texture_whitecube /* && gl_support_blendsquare*/) // FIXME: detect blendsquare!
+ {
+ // 2/0/0/2 3D combine blendsquare path
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(normalmaptexture);
+ m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
+ m.texmatrix[0] = rsurface_texture->currenttexmatrix;
+ m.texcubemap[1] = R_GetTexture(r_texture_normalizationcube);
+ m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
+ m.pointer_texcoord3f[1] = rsurface_array_texcoord3f;
+ R_Shadow_GenTexCoords_Specular_NormalCubeMap(rsurface_array_texcoord3f + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, rsurface_svector3f + 3 * surface->num_firstvertex, rsurface_tvector3f + 3 * surface->num_firstvertex, rsurface_normal3f + 3 * surface->num_firstvertex, r_shadow_entitylightorigin, r_shadow_entityeyeorigin);
+ R_Mesh_TextureState(&m);
+ GL_ColorMask(0,0,0,1);
+ // this squares the result
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ZERO);
+ GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+ GL_LockArrays(0, 0);
+
+ R_Mesh_ResetTextureState();
+ GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ // square alpha in framebuffer a few times to make it shiny
+ GL_BlendFunc(GL_ZERO, GL_DST_ALPHA);
+ // these comments are a test run through this math for intensity 0.5
+ // 0.5 * 0.5 = 0.25 (done by the BlendFunc earlier)
+ // 0.25 * 0.25 = 0.0625 (this is another pass)
+ // 0.0625 * 0.0625 = 0.00390625 (this is another pass)
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+ GL_LockArrays(0, 0);
+
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(glosstexture);
+ m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
+ m.texmatrix[0] = rsurface_texture->currenttexmatrix;
+ m.tex3d[1] = R_GetTexture(r_shadow_attenuation3dtexture);
+ m.pointer_texcoord3f[1] = rsurface_vertex3f;
+ m.texmatrix[1] = r_shadow_entitytoattenuationxyz;
+ GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
+ }
+ else
+ {
+ // 2/0/0/2/2 2D combine blendsquare path
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(normalmaptexture);
+ m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
+ m.texmatrix[0] = rsurface_texture->currenttexmatrix;
+ m.texcubemap[1] = R_GetTexture(r_texture_normalizationcube);
+ m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
+ m.pointer_texcoord3f[1] = rsurface_array_texcoord3f;
+ R_Shadow_GenTexCoords_Specular_NormalCubeMap(rsurface_array_texcoord3f + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, rsurface_svector3f + 3 * surface->num_firstvertex, rsurface_tvector3f + 3 * surface->num_firstvertex, rsurface_normal3f + 3 * surface->num_firstvertex, r_shadow_entitylightorigin, r_shadow_entityeyeorigin);
+ R_Mesh_TextureState(&m);
+ GL_ColorMask(0,0,0,1);
+ // this squares the result
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ZERO);
+ GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+ GL_LockArrays(0, 0);
+
+ R_Mesh_ResetTextureState();
+ GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ // square alpha in framebuffer a few times to make it shiny
+ GL_BlendFunc(GL_ZERO, GL_DST_ALPHA);
+ // these comments are a test run through this math for intensity 0.5
+ // 0.5 * 0.5 = 0.25 (done by the BlendFunc earlier)
+ // 0.25 * 0.25 = 0.0625 (this is another pass)
+ // 0.0625 * 0.0625 = 0.00390625 (this is another pass)
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+ GL_LockArrays(0, 0);
+
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(r_shadow_attenuation2dtexture);
+ m.pointer_texcoord3f[0] = rsurface_vertex3f;
+ m.texmatrix[0] = r_shadow_entitytoattenuationxyz;
+ m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture);
+ m.pointer_texcoord3f[1] = rsurface_vertex3f;
+ m.texmatrix[1] = r_shadow_entitytoattenuationz;
+ R_Mesh_TextureState(&m);
+ GL_BlendFunc(GL_DST_ALPHA, GL_ZERO);
+ GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+ GL_LockArrays(0, 0);
+
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(glosstexture);
+ m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
+ m.texmatrix[0] = rsurface_texture->currenttexmatrix;
+ if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
+ {
+ m.texcubemap[1] = R_GetTexture(r_shadow_rtlight->currentcubemap);
+ m.pointer_texcoord3f[1] = rsurface_vertex3f;
+ m.texmatrix[1] = r_shadow_entitytolight;
+ }
+ GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
+ }
+ R_Mesh_TextureState(&m);
+ GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 0);
+ VectorScale(lightcolorbase, colorscale, color2);
+ GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--)
+ {
+ GL_Color(bound(0, color2[0], 1), bound(0, color2[1], 1), bound(0, color2[2], 1), 1);
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+ }
+ GL_LockArrays(0, 0);
+}
+
+static void R_Shadow_RenderSurfacesLighting_Light_Dot3(int numsurfaces, msurface_t **surfacelist, const vec3_t lightcolorbase, const vec3_t lightcolorpants, const vec3_t lightcolorshirt, rtexture_t *basetexture, rtexture_t *pantstexture, rtexture_t *shirttexture, rtexture_t *normalmaptexture, rtexture_t *glosstexture, float specularscale, qboolean dopants, qboolean doshirt)
+{
+ // ARB path (any Geforce, any Radeon)
+ int surfacelistindex;
+ qboolean doambient = r_shadow_rtlight->ambientscale > 0;
+ qboolean dodiffuse = r_shadow_rtlight->diffusescale > 0;
+ qboolean dospecular = specularscale > 0;
+ if (!doambient && !dodiffuse && !dospecular)
+ return;
+ RSurf_PrepareVerticesForBatch(true, true, numsurfaces, surfacelist);
+ R_Mesh_ColorPointer(NULL);
+ for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
+ {
+ const msurface_t *surface = surfacelist[surfacelistindex];
+ if (doambient)
+ R_Shadow_RenderSurfacesLighting_Light_Dot3_AmbientPass(surface, lightcolorbase, basetexture, r_shadow_rtlight->ambientscale);
+ if (dodiffuse)
+ R_Shadow_RenderSurfacesLighting_Light_Dot3_DiffusePass(surface, lightcolorbase, basetexture, normalmaptexture, r_shadow_rtlight->diffusescale);
+ if (dopants)
+ {
+ if (doambient)
+ R_Shadow_RenderSurfacesLighting_Light_Dot3_AmbientPass(surface, lightcolorpants, pantstexture, r_shadow_rtlight->ambientscale);
+ if (dodiffuse)
+ R_Shadow_RenderSurfacesLighting_Light_Dot3_DiffusePass(surface, lightcolorpants, pantstexture, normalmaptexture, r_shadow_rtlight->diffusescale);
+ }
+ if (doshirt)
+ {
+ if (doambient)
+ R_Shadow_RenderSurfacesLighting_Light_Dot3_AmbientPass(surface, lightcolorshirt, shirttexture, r_shadow_rtlight->ambientscale);
+ if (dodiffuse)
+ R_Shadow_RenderSurfacesLighting_Light_Dot3_DiffusePass(surface, lightcolorshirt, shirttexture, normalmaptexture, r_shadow_rtlight->diffusescale);
+ }
+ if (dospecular)
+ R_Shadow_RenderSurfacesLighting_Light_Dot3_SpecularPass(surface, lightcolorbase, glosstexture, normalmaptexture, specularscale);
+ }
+}
+
+void R_Shadow_RenderSurfacesLighting_Light_Vertex_Pass(const model_t *model, const msurface_t *surface, vec3_t diffusecolor2, vec3_t ambientcolor2)
+{
+ int renders;
+ const int *elements = rsurface_model->surfmesh.data_element3i + surface->num_firsttriangle * 3;
+ R_Shadow_RenderSurfacesLighting_Light_Vertex_Shading(surface, diffusecolor2, ambientcolor2);
+ for (renders = 0;renders < 64 && (ambientcolor2[0] > renders || ambientcolor2[1] > renders || ambientcolor2[2] > renders || diffusecolor2[0] > renders || diffusecolor2[1] > renders || diffusecolor2[2] > renders);renders++)
+ {
+ int i;
+ float *c;
+#if 1
+ // due to low fillrate on the cards this vertex lighting path is
+ // designed for, we manually cull all triangles that do not
+ // contain a lit vertex
+ int draw;
+ const int *e;
+ int newnumtriangles;
+ int *newe;
+ int newelements[3072];
+ draw = false;
+ newnumtriangles = 0;
+ newe = newelements;
+ for (i = 0, e = elements;i < surface->num_triangles;i++, e += 3)
+ {
+ if (newnumtriangles >= 1024)