+ if (r_shadow_glsl.integer && r_shadow_program_light[0])
+ {
+ r_shadowstage = R_SHADOWSTAGE_LIGHT_GLSL;
+ memset(&m, 0, sizeof(m));
+ m.pointer_vertex = varray_vertex3f;
+ m.pointer_texcoord[0] = varray_texcoord2f[0];
+ m.pointer_texcoord3f[1] = varray_svector3f;
+ m.pointer_texcoord3f[2] = varray_tvector3f;
+ m.pointer_texcoord3f[3] = varray_normal3f;
+ m.tex[0] = R_GetTexture(r_texture_blanknormalmap); // normal
+ m.tex[1] = R_GetTexture(r_texture_white); // diffuse
+ m.tex[2] = R_GetTexture(r_texture_white); // gloss
+ m.texcubemap[3] = R_GetTexture(r_shadow_lightcubemap); // light filter
+ // TODO: support fog (after renderer is converted to texture fog)
+ m.tex[4] = R_GetTexture(r_texture_white); // fog
+ //m.texmatrix[3] = r_shadow_entitytolight; // light filter matrix
+ R_Mesh_State(&m);
+ GL_BlendFunc(GL_ONE, GL_ONE);
+ GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 0);
+ CHECKGLERROR
+ r_shadow_lightpermutation = 0;
+ // only add a feature to the permutation if that permutation exists
+ // (otherwise it might end up not using a shader at all, which looks
+ // worse than using less features)
+ if (r_shadow_rtlight->specularscale && r_shadow_program_light[r_shadow_lightpermutation | SHADERPERMUTATION_SPECULAR])
+ r_shadow_lightpermutation |= SHADERPERMUTATION_SPECULAR;
+ //if (fog && r_shadow_program_light[r_shadow_lightpermutation | SHADERPERMUTATION_FOG])
+ // r_shadow_lightpermutation |= SHADERPERMUTATION_FOG;
+ if (r_shadow_lightcubemap != r_texture_whitecube && r_shadow_program_light[r_shadow_lightpermutation | SHADERPERMUTATION_CUBEFILTER])
+ r_shadow_lightpermutation |= SHADERPERMUTATION_CUBEFILTER;
+ if (r_shadow_glsl_offsetmapping.integer && r_shadow_program_light[r_shadow_lightpermutation | SHADERPERMUTATION_OFFSETMAPPING])
+ r_shadow_lightpermutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ r_shadow_lightprog = r_shadow_program_light[r_shadow_lightpermutation];
+ qglUseProgramObjectARB(r_shadow_lightprog);CHECKGLERROR
+ // TODO: support fog (after renderer is converted to texture fog)
+ if (r_shadow_lightpermutation & SHADERPERMUTATION_FOG)
+ {
+ qglUniform1fARB(qglGetUniformLocationARB(r_shadow_lightprog, "FogRangeRecip"), 0);CHECKGLERROR
+ }
+ qglUniform1fARB(qglGetUniformLocationARB(r_shadow_lightprog, "AmbientScale"), r_shadow_rtlight->ambientscale);CHECKGLERROR
+ qglUniform1fARB(qglGetUniformLocationARB(r_shadow_lightprog, "DiffuseScale"), r_shadow_rtlight->diffusescale);CHECKGLERROR
+ if (r_shadow_lightpermutation & SHADERPERMUTATION_SPECULAR)
+ {
+ qglUniform1fARB(qglGetUniformLocationARB(r_shadow_lightprog, "SpecularPower"), 8);CHECKGLERROR
+ qglUniform1fARB(qglGetUniformLocationARB(r_shadow_lightprog, "SpecularScale"), r_shadow_rtlight->specularscale);CHECKGLERROR
+ }
+ //qglUniform3fARB(qglGetUniformLocationARB(r_shadow_lightprog, "LightColor"), lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKGLERROR
+ //qglUniform3fARB(qglGetUniformLocationARB(r_shadow_lightprog, "LightPosition"), relativelightorigin[0], relativelightorigin[1], relativelightorigin[2]);CHECKGLERROR
+ //if (r_shadow_lightpermutation & (SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_FOG | SHADERPERMUTATION_OFFSETMAPPING))
+ //{
+ // qglUniform3fARB(qglGetUniformLocationARB(r_shadow_lightprog, "EyePosition"), relativeeyeorigin[0], relativeeyeorigin[1], relativeeyeorigin[2]);CHECKGLERROR
+ //}
+ if (r_shadow_lightpermutation & SHADERPERMUTATION_OFFSETMAPPING)
+ {
+ qglUniform1fARB(qglGetUniformLocationARB(r_shadow_lightprog, "OffsetMapping_Scale"), r_shadow_glsl_offsetmapping_scale.value);CHECKGLERROR
+ qglUniform1fARB(qglGetUniformLocationARB(r_shadow_lightprog, "OffsetMapping_Bias"), r_shadow_glsl_offsetmapping_bias.value);CHECKGLERROR
+ }
+ }
+ else if (gl_dot3arb && gl_texturecubemap && r_textureunits.integer >= 2 && gl_combine.integer && gl_stencil)
+ r_shadowstage = R_SHADOWSTAGE_LIGHT_DOT3;
+ else
+ r_shadowstage = R_SHADOWSTAGE_LIGHT_VERTEX;
+}
+
+void R_Shadow_Stage_VisibleShadowVolumes(void)
+{
+ R_Shadow_Stage_Reset();
+ GL_BlendFunc(GL_ONE, GL_ONE);
+ GL_DepthMask(false);
+ GL_DepthTest(r_shadow_visiblevolumes.integer < 2);
+ qglPolygonOffset(0, 0);
+ GL_Color(0.0, 0.0125, 0.1, 1);
+ GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
+ qglDepthFunc(GL_GEQUAL);
+ qglCullFace(GL_FRONT); // this culls back
+ qglDisable(GL_CULL_FACE);
+ qglDisable(GL_STENCIL_TEST);
+ r_shadowstage = R_SHADOWSTAGE_VISIBLEVOLUMES;
+}
+
+void R_Shadow_Stage_VisibleLighting(int stenciltest)
+{
+ R_Shadow_Stage_Reset();
+ GL_BlendFunc(GL_ONE, GL_ONE);
+ GL_DepthMask(false);
+ GL_DepthTest(r_shadow_visiblelighting.integer < 2);
+ qglPolygonOffset(0, 0);
+ GL_Color(0.1, 0.0125, 0, 1);
+ GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
+ qglDepthFunc(GL_EQUAL);
+ qglCullFace(GL_FRONT); // this culls back
+ qglEnable(GL_CULL_FACE);
+ if (stenciltest)
+ qglEnable(GL_STENCIL_TEST);
+ else
+ qglDisable(GL_STENCIL_TEST);
+ r_shadowstage = R_SHADOWSTAGE_VISIBLELIGHTING;