+ if (dospecular)
+ {
+ // FIXME: detect blendsquare!
+ //if (gl_support_blendsquare)
+ {
+ colorscale = specularscale;
+ GL_Color(1,1,1,1);
+ if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && r_shadow_lightcubemap != r_texture_whitecube /* && gl_support_blendsquare*/) // FIXME: detect blendsquare!
+ {
+ // 2/0/0/1/2 3D combine blendsquare path
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = rsurface_vertex3f;
+ m.tex[0] = R_GetTexture(normalmaptexture);
+ m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
+ 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_Specular_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_shadow_entityeyeorigin);
+ R_Mesh_State(&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);
+ c_rt_lightmeshes++;
+ c_rt_lighttris += surface->num_triangles;
+
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = rsurface_vertex3f;
+ R_Mesh_State(&m);
+ 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);
+ c_rt_lightmeshes++;
+ c_rt_lighttris += surface->num_triangles;
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+ c_rt_lightmeshes++;
+ c_rt_lighttris += surface->num_triangles;
+ GL_LockArrays(0, 0);
+
+ 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_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(glosstexture);
+ m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
+ 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_support_blendsquare*/) // FIXME: detect blendsquare!
+ {
+ // 2/0/0/2 3D combine blendsquare path
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = rsurface_vertex3f;
+ m.tex[0] = R_GetTexture(normalmaptexture);
+ m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
+ 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_Specular_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_shadow_entityeyeorigin);
+ R_Mesh_State(&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);
+ c_rt_lightmeshes++;
+ c_rt_lighttris += surface->num_triangles;
+
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = rsurface_vertex3f;
+ R_Mesh_State(&m);
+ 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);
+ c_rt_lightmeshes++;
+ c_rt_lighttris += surface->num_triangles;
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+ c_rt_lightmeshes++;
+ c_rt_lighttris += surface->num_triangles;
+ GL_LockArrays(0, 0);
+
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = rsurface_vertex3f;
+ m.tex[0] = R_GetTexture(glosstexture);
+ m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
+ m.tex3d[1] = R_GetTexture(r_shadow_attenuation3dtexture);
+#ifdef USETEXMATRIX
+ m.pointer_texcoord3f[1] = rsurface_vertex3f;
+ m.texmatrix[1] = r_shadow_entitytoattenuationxyz;
+#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_entitytoattenuationxyz);
+#endif
+ GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
+ }
+ else
+ {
+ // 2/0/0/2/2 2D combine blendsquare path
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = rsurface_vertex3f;
+ m.tex[0] = R_GetTexture(normalmaptexture);
+ m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
+ 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_Specular_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_shadow_entityeyeorigin);
+ R_Mesh_State(&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);
+ c_rt_lightmeshes++;
+ c_rt_lighttris += surface->num_triangles;
+
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = rsurface_vertex3f;
+ R_Mesh_State(&m);
+ 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);
+ c_rt_lightmeshes++;
+ c_rt_lighttris += surface->num_triangles;
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, elements);
+ c_rt_lightmeshes++;
+ c_rt_lighttris += surface->num_triangles;
+ GL_LockArrays(0, 0);
+
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = rsurface_vertex3f;
+ m.tex[0] = R_GetTexture(r_shadow_attenuation2dtexture);
+#ifdef USETEXMATRIX
+ m.pointer_texcoord3f[0] = rsurface_vertex3f;
+ m.texmatrix[0] = r_shadow_entitytoattenuationxyz;
+#else
+ m.pointer_texcoord[0] = varray_texcoord2f[0];
+ R_Shadow_Transform_Vertex3f_Texcoord2f(varray_texcoord2f[0] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationxyz);
+#endif
+ m.tex[1] = R_GetTexture(r_shadow_attenuation2dtexture);
+#ifdef USETEXMATRIX
+ m.pointer_texcoord3f[1] = rsurface_vertex3f;
+ m.texmatrix[1] = r_shadow_entitytoattenuationz;
+#else
+ m.pointer_texcoord[1] = varray_texcoord2f[1];
+ R_Shadow_Transform_Vertex3f_Texcoord2f(varray_texcoord2f[1] + 3 * surface->num_firstvertex, surface->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, &r_shadow_entitytoattenuationz);
+#endif
+ 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(glosstexture);
+ m.pointer_texcoord[0] = surface->groupmesh->data_texcoordtexture2f;
+ 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);
+ }
+ R_Mesh_State(&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);
+ c_rt_lightmeshes++;
+ c_rt_lighttris += surface->num_triangles;
+ }
+ GL_LockArrays(0, 0);
+ }
+ }