+ int renders;
+ float color[3], color2[3], colorscale;
+ rmeshstate_t m;
+ if (!bumptexture)
+ bumptexture = r_shadow_blankbumptexture;
+ if (!glosstexture)
+ glosstexture = r_shadow_blankglosstexture;
+ GL_DepthMask(false);
+ GL_DepthTest(true);
+ if (gl_dot3arb && gl_texturecubemap && gl_combine.integer && gl_stencil)
+ {
+ if (lighting & LIGHTING_DIFFUSE)
+ {
+ GL_Color(1,1,1,1);
+ colorscale = r_shadow_lightintensityscale.value;
+ // 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 = vertex3f;
+ m.tex[0] = R_GetTexture(bumptexture);
+ m.texcombinergb[0] = GL_REPLACE;
+ m.pointer_texcoord[0] = texcoord2f;
+ m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture);
+ m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
+ m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+ R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin);
+ m.tex3d[2] = R_GetTexture(r_shadow_attenuation3dtexture);
+#if USETEXMATRIX
+ m.pointer_texcoord3f[2] = vertex3f;
+ m.texmatrix[2] = *matrix_modeltoattenuationxyz;
+#else
+ m.pointer_texcoord3f[2] = varray_texcoord3f[2];
+ R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[2], numverts, vertex3f, matrix_modeltoattenuationxyz);
+#endif
+ R_Mesh_State(&m);
+ GL_ColorMask(0,0,0,1);
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ GL_LockArrays(0, numverts);
+ R_Mesh_Draw(numverts, numtriangles, elements);
+ GL_LockArrays(0, 0);
+ c_rt_lightmeshes++;
+ c_rt_lighttris += numtriangles;
+
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = vertex3f;
+ m.tex[0] = R_GetTexture(basetexture);
+ m.pointer_texcoord[0] = texcoord2f;
+ if (lightcubemap)
+ {
+ m.texcubemap[1] = R_GetTexture(lightcubemap);
+#if USETEXMATRIX
+ m.pointer_texcoord3f[1] = vertex3f;
+ m.texmatrix[1] = *matrix_modeltolight;
+#else
+ m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+ R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltolight);
+#endif
+ }
+ }
+ else if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && lightcubemap)
+ {
+ // 1/2/2 3D combine path (original Radeon)
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = vertex3f;
+ m.tex3d[0] = R_GetTexture(r_shadow_attenuation3dtexture);
+#if USETEXMATRIX
+ m.pointer_texcoord3f[0] = vertex3f;
+ m.texmatrix[0] = *matrix_modeltoattenuationxyz;
+#else
+ m.pointer_texcoord3f[0] = varray_texcoord3f[0];
+ R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[0], numverts, vertex3f, matrix_modeltoattenuationxyz);
+#endif
+ R_Mesh_State(&m);
+ GL_ColorMask(0,0,0,1);
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ GL_LockArrays(0, numverts);
+ R_Mesh_Draw(numverts, numtriangles, elements);
+ GL_LockArrays(0, 0);
+ c_rt_lightmeshes++;
+ c_rt_lighttris += numtriangles;
+
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = vertex3f;
+ m.tex[0] = R_GetTexture(bumptexture);
+ m.texcombinergb[0] = GL_REPLACE;
+ m.pointer_texcoord[0] = texcoord2f;
+ m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture);
+ m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
+ m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+ R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin);
+ R_Mesh_State(&m);
+ GL_BlendFunc(GL_DST_ALPHA, GL_ZERO);
+ GL_LockArrays(0, numverts);
+ R_Mesh_Draw(numverts, numtriangles, elements);
+ GL_LockArrays(0, 0);
+ c_rt_lightmeshes++;
+ c_rt_lighttris += numtriangles;
+
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = vertex3f;
+ m.tex[0] = R_GetTexture(basetexture);
+ m.pointer_texcoord[0] = texcoord2f;
+ if (lightcubemap)
+ {
+ m.texcubemap[1] = R_GetTexture(lightcubemap);
+#if USETEXMATRIX
+ m.pointer_texcoord3f[1] = vertex3f;
+ m.texmatrix[1] = *matrix_modeltolight;
+#else
+ m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+ R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltolight);
+#endif
+ }
+ }
+ else if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && !lightcubemap)
+ {
+ // 2/2 3D combine path (original Radeon)
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = vertex3f;
+ m.tex[0] = R_GetTexture(bumptexture);
+ m.texcombinergb[0] = GL_REPLACE;
+ m.pointer_texcoord[0] = texcoord2f;
+ m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture);
+ m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
+ m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+ R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin);
+ R_Mesh_State(&m);
+ GL_ColorMask(0,0,0,1);
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ GL_LockArrays(0, numverts);
+ R_Mesh_Draw(numverts, numtriangles, elements);
+ GL_LockArrays(0, 0);
+ c_rt_lightmeshes++;
+ c_rt_lighttris += numtriangles;
+
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = vertex3f;
+ m.tex[0] = R_GetTexture(basetexture);
+ m.pointer_texcoord[0] = texcoord2f;
+ m.tex3d[1] = R_GetTexture(r_shadow_attenuation3dtexture);
+#if USETEXMATRIX
+ m.pointer_texcoord3f[1] = vertex3f;
+ m.texmatrix[1] = *matrix_modeltoattenuationxyz;
+#else
+ m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+ R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltoattenuationxyz);
+#endif
+ }
+ else if (r_textureunits.integer >= 4)
+ {
+ // 4/2 2D combine path (Geforce3, Radeon 8500)
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = vertex3f;
+ m.tex[0] = R_GetTexture(bumptexture);
+ m.texcombinergb[0] = GL_REPLACE;
+ m.pointer_texcoord[0] = texcoord2f;
+ m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture);
+ m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
+ m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+ R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin);
+ m.tex[2] = R_GetTexture(r_shadow_attenuation2dtexture);
+#if USETEXMATRIX
+ m.pointer_texcoord3f[2] = vertex3f;
+ m.texmatrix[2] = *matrix_modeltoattenuationxyz;
+#else
+ m.pointer_texcoord[2] = varray_texcoord2f[2];
+ R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[2], numverts, vertex3f, matrix_modeltoattenuationxyz);
+#endif
+ m.tex[3] = R_GetTexture(r_shadow_attenuation2dtexture);
+#if USETEXMATRIX
+ m.pointer_texcoord3f[3] = vertex3f;
+ m.texmatrix[3] = *matrix_modeltoattenuationz;
+#else
+ m.pointer_texcoord[3] = varray_texcoord2f[3];
+ R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[3], numverts, vertex3f, matrix_modeltoattenuationz);
+#endif
+ R_Mesh_State(&m);
+ GL_ColorMask(0,0,0,1);
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ GL_LockArrays(0, numverts);
+ R_Mesh_Draw(numverts, numtriangles, elements);
+ GL_LockArrays(0, 0);
+ c_rt_lightmeshes++;
+ c_rt_lighttris += numtriangles;
+
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = vertex3f;
+ m.tex[0] = R_GetTexture(basetexture);
+ m.pointer_texcoord[0] = texcoord2f;
+ if (lightcubemap)
+ {
+ m.texcubemap[1] = R_GetTexture(lightcubemap);
+#if USETEXMATRIX
+ m.pointer_texcoord3f[1] = vertex3f;
+ m.texmatrix[1] = *matrix_modeltolight;
+#else
+ m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+ R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltolight);
+#endif
+ }
+ }
+ else
+ {
+ // 2/2/2 2D combine path (any dot3 card)
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = vertex3f;
+ m.tex[0] = R_GetTexture(r_shadow_attenuation2dtexture);
+#if USETEXMATRIX
+ m.pointer_texcoord3f[0] = vertex3f;
+ m.texmatrix[0] = *matrix_modeltoattenuationxyz;
+#else
+ m.pointer_texcoord[0] = varray_texcoord2f[0];
+ R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[0], numverts, vertex3f, matrix_modeltoattenuationxyz);
+#endif
+ m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture);
+#if USETEXMATRIX
+ m.pointer_texcoord3f[1] = vertex3f;
+ m.texmatrix[1] = *matrix_modeltoattenuationz;
+#else
+ m.pointer_texcoord[1] = varray_texcoord2f[1];
+ R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[1], numverts, vertex3f, matrix_modeltoattenuationz);
+#endif
+ R_Mesh_State(&m);
+ GL_ColorMask(0,0,0,1);
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ GL_LockArrays(0, numverts);
+ R_Mesh_Draw(numverts, numtriangles, elements);
+ GL_LockArrays(0, 0);
+ c_rt_lightmeshes++;
+ c_rt_lighttris += numtriangles;
+
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = vertex3f;
+ m.tex[0] = R_GetTexture(bumptexture);
+ m.texcombinergb[0] = GL_REPLACE;
+ m.pointer_texcoord[0] = texcoord2f;
+ m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture);
+ m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
+ m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+ R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin);
+ R_Mesh_State(&m);
+ GL_BlendFunc(GL_DST_ALPHA, GL_ZERO);
+ GL_LockArrays(0, numverts);
+ R_Mesh_Draw(numverts, numtriangles, elements);
+ GL_LockArrays(0, 0);
+ c_rt_lightmeshes++;
+ c_rt_lighttris += numtriangles;
+
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = vertex3f;
+ m.tex[0] = R_GetTexture(basetexture);
+ m.pointer_texcoord[0] = texcoord2f;
+ if (lightcubemap)
+ {
+ m.texcubemap[1] = R_GetTexture(lightcubemap);
+#if USETEXMATRIX
+ m.pointer_texcoord3f[1] = vertex3f;
+ m.texmatrix[1] = *matrix_modeltolight;
+#else
+ m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+ R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltolight);
+#endif
+ }
+ }
+ // this final code is shared
+ R_Mesh_State(&m);
+ GL_ColorMask(1,1,1,0);
+ GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
+ VectorScale(lightcolor, colorscale, color2);
+ 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);
+ GL_LockArrays(0, numverts);
+ R_Mesh_Draw(numverts, numtriangles, elements);
+ GL_LockArrays(0, 0);
+ c_rt_lightmeshes++;
+ c_rt_lighttris += numtriangles;
+ }
+ }
+ if ((lighting & LIGHTING_SPECULAR) && (r_shadow_gloss.integer >= 2 || (r_shadow_gloss.integer >= 1 && glosstexture != r_shadow_blankglosstexture)))
+ {
+ // FIXME: detect blendsquare!
+ //if (gl_support_blendsquare)
+ {
+ colorscale = r_shadow_lightintensityscale.value * r_shadow_glossintensity.value;
+ if (glosstexture == r_shadow_blankglosstexture)
+ colorscale *= r_shadow_gloss2intensity.value;
+ GL_Color(1,1,1,1);
+ if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && lightcubemap /*&& gl_support_blendsquare*/) // FIXME: detect blendsquare!
+ {
+ // 2/0/0/1/2 3D combine blendsquare path
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = vertex3f;
+ m.tex[0] = R_GetTexture(bumptexture);
+ m.pointer_texcoord[0] = texcoord2f;
+ m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture);
+ m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
+ m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+ R_Shadow_GenTexCoords_Specular_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin, relativeeyeorigin);
+ R_Mesh_State(&m);
+ GL_ColorMask(0,0,0,1);
+ // this squares the result
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ZERO);
+ GL_LockArrays(0, numverts);
+ R_Mesh_Draw(numverts, numtriangles, elements);
+ GL_LockArrays(0, 0);
+ c_rt_lightmeshes++;
+ c_rt_lighttris += numtriangles;
+
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = vertex3f;
+ R_Mesh_State(&m);
+ GL_LockArrays(0, numverts);
+ // 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(numverts, numtriangles, elements);
+ c_rt_lightmeshes++;
+ c_rt_lighttris += numtriangles;
+ R_Mesh_Draw(numverts, numtriangles, elements);
+ c_rt_lightmeshes++;
+ c_rt_lighttris += numtriangles;
+ GL_LockArrays(0, 0);
+
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = vertex3f;
+ m.tex3d[0] = R_GetTexture(r_shadow_attenuation3dtexture);
+#if USETEXMATRIX
+ m.pointer_texcoord3f[0] = vertex3f;
+ m.texmatrix[0] = *matrix_modeltoattenuationxyz;
+#else
+ m.pointer_texcoord3f[0] = varray_texcoord3f[0];
+ R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[0], numverts, vertex3f, matrix_modeltoattenuationxyz);
+#endif
+ R_Mesh_State(&m);
+ GL_BlendFunc(GL_DST_ALPHA, GL_ZERO);
+ GL_LockArrays(0, numverts);
+ R_Mesh_Draw(numverts, numtriangles, elements);
+ GL_LockArrays(0, 0);
+ c_rt_lightmeshes++;
+ c_rt_lighttris += numtriangles;
+
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = vertex3f;
+ m.tex[0] = R_GetTexture(glosstexture);
+ m.pointer_texcoord[0] = texcoord2f;
+ if (lightcubemap)
+ {
+ m.texcubemap[1] = R_GetTexture(lightcubemap);
+#if USETEXMATRIX
+ m.pointer_texcoord3f[1] = vertex3f;
+ m.texmatrix[1] = *matrix_modeltolight;
+#else
+ m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+ R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltolight);
+#endif
+ }
+ }
+ else if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && !lightcubemap /*&& gl_support_blendsquare*/) // FIXME: detect blendsquare!
+ {
+ // 2/0/0/2 3D combine blendsquare path
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = vertex3f;
+ m.tex[0] = R_GetTexture(bumptexture);
+ m.pointer_texcoord[0] = texcoord2f;
+ m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture);
+ m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
+ m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+ R_Shadow_GenTexCoords_Specular_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin, relativeeyeorigin);
+ R_Mesh_State(&m);
+ GL_ColorMask(0,0,0,1);
+ // this squares the result
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ZERO);
+ GL_LockArrays(0, numverts);
+ R_Mesh_Draw(numverts, numtriangles, elements);
+ GL_LockArrays(0, 0);
+ c_rt_lightmeshes++;
+ c_rt_lighttris += numtriangles;
+
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = vertex3f;
+ R_Mesh_State(&m);
+ GL_LockArrays(0, numverts);
+ // 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(numverts, numtriangles, elements);
+ c_rt_lightmeshes++;
+ c_rt_lighttris += numtriangles;
+ R_Mesh_Draw(numverts, numtriangles, elements);
+ c_rt_lightmeshes++;
+ c_rt_lighttris += numtriangles;
+ GL_LockArrays(0, 0);
+
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = vertex3f;
+ m.tex[0] = R_GetTexture(glosstexture);
+ m.pointer_texcoord[0] = texcoord2f;
+ m.tex3d[1] = R_GetTexture(r_shadow_attenuation3dtexture);
+#if USETEXMATRIX
+ m.pointer_texcoord3f[1] = vertex3f;
+ m.texmatrix[1] = *matrix_modeltoattenuationxyz;
+#else
+ m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+ R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltoattenuationxyz);
+#endif
+ }
+ else
+ {
+ // 2/0/0/2/2 2D combine blendsquare path
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = vertex3f;
+ m.tex[0] = R_GetTexture(bumptexture);
+ m.pointer_texcoord[0] = texcoord2f;
+ m.texcubemap[1] = R_GetTexture(r_shadow_normalcubetexture);
+ m.texcombinergb[1] = GL_DOT3_RGBA_ARB;
+ m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+ R_Shadow_GenTexCoords_Specular_NormalCubeMap(varray_texcoord3f[1], numverts, vertex3f, svector3f, tvector3f, normal3f, relativelightorigin, relativeeyeorigin);
+ R_Mesh_State(&m);
+ GL_ColorMask(0,0,0,1);
+ // this squares the result
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ZERO);
+ GL_LockArrays(0, numverts);
+ R_Mesh_Draw(numverts, numtriangles, elements);
+ GL_LockArrays(0, 0);
+ c_rt_lightmeshes++;
+ c_rt_lighttris += numtriangles;
+
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = vertex3f;
+ R_Mesh_State(&m);
+ GL_LockArrays(0, numverts);
+ // 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(numverts, numtriangles, elements);
+ c_rt_lightmeshes++;
+ c_rt_lighttris += numtriangles;
+ R_Mesh_Draw(numverts, numtriangles, elements);
+ c_rt_lightmeshes++;
+ c_rt_lighttris += numtriangles;
+ GL_LockArrays(0, 0);
+
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = vertex3f;
+ m.tex[0] = R_GetTexture(r_shadow_attenuation2dtexture);
+#if USETEXMATRIX
+ m.pointer_texcoord3f[0] = vertex3f;
+ m.texmatrix[0] = *matrix_modeltoattenuationxyz;
+#else
+ m.pointer_texcoord[0] = varray_texcoord2f[0];
+ R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[0], numverts, vertex3f, matrix_modeltoattenuationxyz);
+#endif
+ m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture);
+#if USETEXMATRIX
+ m.pointer_texcoord3f[1] = vertex3f;
+ m.texmatrix[1] = *matrix_modeltoattenuationz;
+#else
+ m.pointer_texcoord[1] = varray_texcoord2f[1];
+ R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[1], numverts, vertex3f, matrix_modeltoattenuationz);
+#endif
+ R_Mesh_State(&m);
+ GL_BlendFunc(GL_DST_ALPHA, GL_ZERO);
+ GL_LockArrays(0, numverts);
+ R_Mesh_Draw(numverts, numtriangles, elements);
+ GL_LockArrays(0, 0);
+ c_rt_lightmeshes++;
+ c_rt_lighttris += numtriangles;
+
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = vertex3f;
+ m.tex[0] = R_GetTexture(glosstexture);
+ m.pointer_texcoord[0] = texcoord2f;
+ if (lightcubemap)
+ {
+ m.texcubemap[1] = R_GetTexture(lightcubemap);
+#if USETEXMATRIX
+ m.pointer_texcoord3f[1] = vertex3f;
+ m.texmatrix[1] = *matrix_modeltolight;
+#else
+ m.pointer_texcoord3f[1] = varray_texcoord3f[1];
+ R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltolight);
+#endif
+ }
+ }
+ }
+ R_Mesh_State(&m);
+ GL_ColorMask(1,1,1,0);
+ GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
+ VectorScale(lightcolor, colorscale, color2);
+ GL_LockArrays(0, numverts);
+ 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(numverts, numtriangles, elements);
+ c_rt_lightmeshes++;
+ c_rt_lighttris += numtriangles;
+ }
+ GL_LockArrays(0, 0);
+ }
+ }
+ else
+ {
+ if (lighting & LIGHTING_DIFFUSE)
+ {
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+ VectorScale(lightcolor, r_shadow_lightintensityscale.value, color2);
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = vertex3f;
+ m.pointer_color = varray_color4f;
+ m.tex[0] = R_GetTexture(basetexture);
+ m.pointer_texcoord[0] = texcoord2f;
+ if (r_textureunits.integer >= 2)
+ {
+ // voodoo2
+ m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture);
+#if USETEXMATRIX
+ m.pointer_texcoord3f[1] = vertex3f;
+ m.texmatrix[1] = *matrix_modeltoattenuationxyz;
+#else
+ m.pointer_texcoord[1] = varray_texcoord2f[1];
+ R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[1], numverts, vertex3f, matrix_modeltoattenuationxyz);
+#endif
+ if (r_textureunits.integer >= 3)
+ {
+ // Geforce3/Radeon class but not using dot3
+ m.tex[2] = R_GetTexture(r_shadow_attenuation2dtexture);
+#if USETEXMATRIX
+ m.pointer_texcoord3f[2] = vertex3f;
+ m.texmatrix[2] = *matrix_modeltoattenuationz;
+#else
+ m.pointer_texcoord[2] = varray_texcoord2f[2];
+ R_Shadow_Transform_Vertex3f_TexCoord2f(varray_texcoord2f[2], numverts, vertex3f, matrix_modeltoattenuationz);
+#endif
+ }
+ }
+ R_Mesh_State(&m);
+ for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--)
+ {
+ color[0] = bound(0, color2[0], 1);
+ color[1] = bound(0, color2[1], 1);
+ color[2] = bound(0, color2[2], 1);
+ if (r_textureunits.integer >= 3)
+ R_Shadow_VertexShading(numverts, vertex3f, normal3f, color, matrix_modeltolight);
+ else if (r_textureunits.integer >= 2)
+ R_Shadow_VertexShadingWithZAttenuation(numverts, vertex3f, normal3f, color, matrix_modeltolight);
+ else
+ R_Shadow_VertexShadingWithXYZAttenuation(numverts, vertex3f, normal3f, color, matrix_modeltolight);
+ GL_LockArrays(0, numverts);
+ R_Mesh_Draw(numverts, numtriangles, elements);
+ GL_LockArrays(0, 0);
+ c_rt_lightmeshes++;
+ c_rt_lighttris += numtriangles;
+ }
+ }
+ }