cvar_t r_shadow_bumpscale_bumpmap = {0, "r_shadow_bumpscale_bumpmap", "4", "what magnitude to interpret _bump.tga textures as, higher values increase depth, requires r_restart to take effect"};
cvar_t r_shadow_debuglight = {0, "r_shadow_debuglight", "-1", "renders only one light, for level design purposes or debugging"};
cvar_t r_shadow_gloss = {CVAR_SAVE, "r_shadow_gloss", "1", "0 disables gloss (specularity) rendering, 1 uses gloss if textures are found, 2 forces a flat metallic specular effect on everything without textures (similar to tenebrae)"};
-cvar_t r_shadow_gloss2intensity = {0, "r_shadow_gloss2intensity", "0.25", "how bright the forced flat gloss should look if r_shadow_gloss is 2"};
-cvar_t r_shadow_glossintensity = {0, "r_shadow_glossintensity", "1", "how bright textured glossmaps should look if r_shadow_gloss is 1 or 2"};
+cvar_t r_shadow_gloss2intensity = {0, "r_shadow_gloss2intensity", "0.5", "how bright the forced flat gloss should look if r_shadow_gloss is 2"};
+cvar_t r_shadow_glossintensity = {0, "r_shadow_glossintensity", "2", "how bright textured glossmaps should look if r_shadow_gloss is 1 or 2"};
+cvar_t r_shadow_glossexponent = {0, "r_shadow_glossexponent", "32", "how 'sharp' the gloss should appear (specular power)"};
cvar_t r_shadow_lightattenuationpower = {0, "r_shadow_lightattenuationpower", "0.5", "changes attenuation texture generation (does not affect r_glsl lighting)"};
cvar_t r_shadow_lightattenuationscale = {0, "r_shadow_lightattenuationscale", "1", "changes attenuation texture generation (does not affect r_glsl lighting)"};
cvar_t r_shadow_lightintensityscale = {0, "r_shadow_lightintensityscale", "1", "renders all world lights brighter or darker"};
Cvar_RegisterVariable(&r_shadow_gloss);
Cvar_RegisterVariable(&r_shadow_gloss2intensity);
Cvar_RegisterVariable(&r_shadow_glossintensity);
+ Cvar_RegisterVariable(&r_shadow_glossexponent);
Cvar_RegisterVariable(&r_shadow_lightattenuationpower);
Cvar_RegisterVariable(&r_shadow_lightattenuationscale);
Cvar_RegisterVariable(&r_shadow_lightintensityscale);
numshadowmark = 0;
}
-int R_Shadow_ConstructShadowVolume(int innumvertices, int innumtris, const int *inelement3i, const int *inneighbor3i, const float *invertex3f, int *outnumvertices, int *outelement3i, float *outvertex3f, const float *projectorigin, float projectdistance, int numshadowmarktris, const int *shadowmarktris)
+int R_Shadow_ConstructShadowVolume(int innumvertices, int innumtris, const int *inelement3i, const int *inneighbor3i, const float *invertex3f, int *outnumvertices, int *outelement3i, float *outvertex3f, const float *projectorigin, const float *projectdirection, float projectdistance, int numshadowmarktris, const int *shadowmarktris)
{
int i, j;
int outtriangles = 0, outvertices = 0;
const int *element;
const float *vertex;
+ float ratio, direction[3], projectvector[3];
+
+ if (projectdirection)
+ VectorScale(projectdirection, projectdistance, projectvector);
+ else
+ VectorClear(projectvector);
if (maxvertexupdate < innumvertices)
{
for (i = 0;i < numshadowmarktris;i++)
shadowmark[shadowmarktris[i]] = shadowmarkcount;
- for (i = 0;i < numshadowmarktris;i++)
+ // create the vertices
+ if (projectdirection)
{
- element = inelement3i + shadowmarktris[i] * 3;
- // make sure the vertices are created
- for (j = 0;j < 3;j++)
+ for (i = 0;i < numshadowmarktris;i++)
{
- if (vertexupdate[element[j]] != vertexupdatenum)
+ element = inelement3i + shadowmarktris[i] * 3;
+ for (j = 0;j < 3;j++)
{
- float ratio, direction[3];
- vertexupdate[element[j]] = vertexupdatenum;
- vertexremap[element[j]] = outvertices;
- vertex = invertex3f + element[j] * 3;
- // project one copy of the vertex to the sphere radius of the light
- // (FIXME: would projecting it to the light box be better?)
- VectorSubtract(vertex, projectorigin, direction);
- ratio = projectdistance / VectorLength(direction);
- VectorCopy(vertex, outvertex3f);
- VectorMA(projectorigin, ratio, direction, (outvertex3f + 3));
- outvertex3f += 6;
- outvertices += 2;
+ if (vertexupdate[element[j]] != vertexupdatenum)
+ {
+ vertexupdate[element[j]] = vertexupdatenum;
+ vertexremap[element[j]] = outvertices;
+ vertex = invertex3f + element[j] * 3;
+ // project one copy of the vertex according to projectvector
+ VectorCopy(vertex, outvertex3f);
+ VectorAdd(vertex, projectvector, (outvertex3f + 3));
+ outvertex3f += 6;
+ outvertices += 2;
+ }
+ }
+ }
+ }
+ else
+ {
+ for (i = 0;i < numshadowmarktris;i++)
+ {
+ element = inelement3i + shadowmarktris[i] * 3;
+ for (j = 0;j < 3;j++)
+ {
+ if (vertexupdate[element[j]] != vertexupdatenum)
+ {
+ vertexupdate[element[j]] = vertexupdatenum;
+ vertexremap[element[j]] = outvertices;
+ vertex = invertex3f + element[j] * 3;
+ // project one copy of the vertex to the sphere radius of the light
+ // (FIXME: would projecting it to the light box be better?)
+ VectorSubtract(vertex, projectorigin, direction);
+ ratio = projectdistance / VectorLength(direction);
+ VectorCopy(vertex, outvertex3f);
+ VectorMA(projectorigin, ratio, direction, (outvertex3f + 3));
+ outvertex3f += 6;
+ outvertices += 2;
+ }
}
}
}
return outtriangles;
}
-void R_Shadow_VolumeFromList(int numverts, int numtris, const float *invertex3f, const int *elements, const int *neighbors, const vec3_t projectorigin, float projectdistance, int nummarktris, const int *marktris)
+void R_Shadow_VolumeFromList(int numverts, int numtris, const float *invertex3f, const int *elements, const int *neighbors, const vec3_t projectorigin, const vec3_t projectdirection, float projectdistance, int nummarktris, const int *marktris)
{
int tris, outverts;
if (projectdistance < 0.1)
{
- Con_Printf("R_Shadow_Volume: projectdistance %f\n");
+ Con_Printf("R_Shadow_Volume: projectdistance %f\n", projectdistance);
return;
}
if (!numverts || !nummarktris)
// make sure shadowelements is big enough for this volume
if (maxshadowtriangles < nummarktris || maxshadowvertices < numverts)
R_Shadow_ResizeShadowArrays((numverts + 255) & ~255, (nummarktris + 255) & ~255);
- tris = R_Shadow_ConstructShadowVolume(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdistance, nummarktris, marktris);
+ tris = R_Shadow_ConstructShadowVolume(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
r_refdef.stats.lights_dynamicshadowtriangles += tris;
R_Shadow_RenderVolume(outverts, tris, shadowvertex3f, shadowelements);
}
-void R_Shadow_MarkVolumeFromBox(int firsttriangle, int numtris, const float *invertex3f, const int *elements, const vec3_t projectorigin, const vec3_t lightmins, const vec3_t lightmaxs, const vec3_t surfacemins, const vec3_t surfacemaxs)
+void R_Shadow_MarkVolumeFromBox(int firsttriangle, int numtris, const float *invertex3f, const int *elements, const vec3_t projectorigin, const vec3_t projectdirection, const vec3_t lightmins, const vec3_t lightmaxs, const vec3_t surfacemins, const vec3_t surfacemaxs)
{
int t, tend;
const int *e;
const float *v[3];
+ float normal[3];
if (!BoxesOverlap(lightmins, lightmaxs, surfacemins, surfacemaxs))
return;
tend = firsttriangle + numtris;
&& surfacemins[2] >= lightmins[2] && surfacemaxs[2] <= lightmaxs[2])
{
// surface box entirely inside light box, no box cull
- for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
- if (PointInfrontOfTriangle(projectorigin, invertex3f + e[0] * 3, invertex3f + e[1] * 3, invertex3f + e[2] * 3))
- shadowmarklist[numshadowmark++] = t;
+ if (projectdirection)
+ {
+ for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
+ {
+ TriangleNormal(invertex3f + e[0] * 3, invertex3f + e[1] * 3, invertex3f + e[2] * 3, normal);
+ if (DotProduct(normal, projectdirection) < 0)
+ shadowmarklist[numshadowmark++] = t;
+ }
+ }
+ else
+ {
+ for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
+ if (PointInfrontOfTriangle(projectorigin, invertex3f + e[0] * 3, invertex3f + e[1] * 3, invertex3f + e[2] * 3))
+ shadowmarklist[numshadowmark++] = t;
+ }
}
else
{
// surface box not entirely inside light box, cull each triangle
- for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
+ if (projectdirection)
+ {
+ for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
+ {
+ v[0] = invertex3f + e[0] * 3;
+ v[1] = invertex3f + e[1] * 3;
+ v[2] = invertex3f + e[2] * 3;
+ TriangleNormal(v[0], v[1], v[2], normal);
+ if (DotProduct(normal, projectdirection) < 0
+ && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0]))
+ && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0]))
+ && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1]))
+ && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1]))
+ && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2]))
+ && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2])))
+ shadowmarklist[numshadowmark++] = t;
+ }
+ }
+ else
{
- v[0] = invertex3f + e[0] * 3;
- v[1] = invertex3f + e[1] * 3;
- v[2] = invertex3f + e[2] * 3;
- if (PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2])
- && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0]))
- && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0]))
- && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1]))
- && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1]))
- && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2]))
- && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2])))
- shadowmarklist[numshadowmark++] = t;
+ for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
+ {
+ v[0] = invertex3f + e[0] * 3;
+ v[1] = invertex3f + e[1] * 3;
+ v[2] = invertex3f + e[2] * 3;
+ if (PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2])
+ && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0]))
+ && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0]))
+ && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1]))
+ && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1]))
+ && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2]))
+ && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2])))
+ shadowmarklist[numshadowmark++] = t;
+ }
}
}
}
if (r_shadow_rendermode == R_SHADOW_RENDERMODE_STENCIL)
{
// decrement stencil if backface is behind depthbuffer
- qglCullFace(GL_BACK);CHECKGLERROR // quake is backwards, this culls front faces
+ GL_CullFace(GL_BACK); // quake is backwards, this culls front faces
qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);CHECKGLERROR
R_Mesh_Draw(0, numvertices, numtriangles, element3i);
// increment stencil if frontface is behind depthbuffer
- qglCullFace(GL_FRONT);CHECKGLERROR // quake is backwards, this culls back faces
+ GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);CHECKGLERROR
}
R_Mesh_Draw(0, numvertices, numtriangles, element3i);
}
}
r_shadow_attenuation2dtexture = R_LoadTexture2D(r_shadow_texturepool, "attenuation2d", ATTEN2DSIZE, ATTEN2DSIZE, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_ALPHA, NULL);
- if (r_shadow_texture3d.integer)
+ if (r_shadow_texture3d.integer && gl_texture3d)
{
for (z = 0;z < ATTEN3DSIZE;z++)
{
R_Mesh_ResetTextureState();
GL_BlendFunc(GL_ONE, GL_ZERO);
GL_DepthMask(false);
- GL_DepthTest(true);
GL_Color(0, 0, 0, 1);
- qglCullFace(GL_FRONT);CHECKGLERROR // quake is backwards, this culls back faces
- qglEnable(GL_CULL_FACE);CHECKGLERROR
GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
GL_ColorMask(0, 0, 0, 0);
GL_BlendFunc(GL_ONE, GL_ZERO);
GL_DepthMask(false);
- GL_DepthTest(true);
qglPolygonOffset(r_refdef.shadowpolygonfactor, r_refdef.shadowpolygonoffset);CHECKGLERROR
qglDepthFunc(GL_LESS);CHECKGLERROR
- qglCullFace(GL_FRONT);CHECKGLERROR // quake is backwards, this culls back faces
qglEnable(GL_STENCIL_TEST);CHECKGLERROR
qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
r_shadow_rendermode = r_shadow_shadowingrendermode;
if (r_shadow_rendermode == R_SHADOW_RENDERMODE_STENCILTWOSIDE)
{
- qglDisable(GL_CULL_FACE);CHECKGLERROR
+ GL_CullFace(GL_NONE);
qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
qglActiveStencilFaceEXT(GL_BACK);CHECKGLERROR // quake is backwards, this is front faces
qglStencilMask(~0);CHECKGLERROR
}
else
{
- qglEnable(GL_CULL_FACE);CHECKGLERROR
+ GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
qglStencilMask(~0);CHECKGLERROR
// this is changed by every shadow render so its value here is unimportant
qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
R_Shadow_RenderMode_Reset();
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
GL_DepthMask(false);
- GL_DepthTest(true);
qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
//qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
GL_Color(1, 1, 1, 1);
{
qglDepthFunc(GL_EQUAL);CHECKGLERROR
}
- qglCullFace(GL_FRONT);CHECKGLERROR // quake is backwards, this culls back faces
- qglEnable(GL_CULL_FACE);CHECKGLERROR
if (stenciltest)
{
qglEnable(GL_STENCIL_TEST);CHECKGLERROR
R_Shadow_RenderMode_Reset();
GL_BlendFunc(GL_ONE, GL_ONE);
GL_DepthMask(false);
- GL_DepthTest(!r_showdisabledepthtest.integer);
qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
- GL_Color(0.0, 0.0125, 0.1, 1);
+ GL_Color(0.0, 0.0125 * r_view.colorscale, 0.1 * r_view.colorscale, 1);
GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
- qglDepthFunc(GL_GEQUAL);CHECKGLERROR
- qglCullFace(GL_FRONT);CHECKGLERROR // this culls back
- qglDisable(GL_CULL_FACE);CHECKGLERROR
+ if (r_showshadowvolumes.integer >= 2)
+ {
+ qglDepthFunc(GL_ALWAYS);CHECKGLERROR
+ }
+ else
+ {
+ qglDepthFunc(GL_GEQUAL);CHECKGLERROR
+ }
qglDisable(GL_STENCIL_TEST);CHECKGLERROR
r_shadow_rendermode = R_SHADOW_RENDERMODE_VISIBLEVOLUMES;
}
R_Shadow_RenderMode_Reset();
GL_BlendFunc(GL_ONE, GL_ONE);
GL_DepthMask(false);
- GL_DepthTest(!r_showdisabledepthtest.integer);
qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
- GL_Color(0.1, 0.0125, 0, 1);
+ GL_Color(0.1 * r_view.colorscale, 0.0125 * r_view.colorscale, 0, 1);
GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
- if (transparent)
+ if (r_showshadowvolumes.integer >= 2)
+ {
+ qglDepthFunc(GL_ALWAYS);CHECKGLERROR
+ }
+ else if (transparent)
{
qglDepthFunc(GL_LEQUAL);CHECKGLERROR
}
{
qglDepthFunc(GL_EQUAL);CHECKGLERROR
}
- qglCullFace(GL_FRONT);CHECKGLERROR // this culls back
- qglEnable(GL_CULL_FACE);CHECKGLERROR
if (stenciltest)
{
qglEnable(GL_STENCIL_TEST);CHECKGLERROR
R_Shadow_RenderMode_ActiveLight(NULL);
GL_BlendFunc(GL_ONE, GL_ZERO);
GL_DepthMask(true);
- GL_DepthTest(true);
qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
//qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
GL_Color(1, 1, 1, 1);
GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
qglDepthFunc(GL_LEQUAL);CHECKGLERROR
- qglCullFace(GL_FRONT);CHECKGLERROR // quake is backwards, this culls back faces
- qglEnable(GL_CULL_FACE);CHECKGLERROR
- qglDisable(GL_STENCIL_TEST);CHECKGLERROR
- qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
if (gl_support_stenciltwoside)
{
qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
}
+ qglDisable(GL_STENCIL_TEST);CHECKGLERROR
qglStencilMask(~0);CHECKGLERROR
qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
+ qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
+ GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
}
// if that mesh is not empty, check what area of the screen it covers
x1 = y1 = x2 = y2 = 0;
v[3] = 1.0f;
+ //Con_Printf("%i vertices to transform...\n", mesh.numvertices);
for (i = 0;i < mesh.numvertices;i++)
{
VectorCopy(mesh.vertex3f + i * 3, v);
return true;
// the light area is visible, set up the scissor rectangle
- GL_Scissor(ix1, vid.height - iy2, ix2 - ix1, iy2 - iy1);
+ GL_Scissor(ix1, iy1, ix2 - ix1, iy2 - iy1);
//qglScissor(ix1, iy1, ix2 - ix1, iy2 - iy1);CHECKGLERROR
//qglEnable(GL_SCISSOR_TEST);CHECKGLERROR
r_refdef.stats.lights_scissored++;
static void R_Shadow_RenderSurfacesLighting_VisibleLighting(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)
{
// used to display how many times a surface is lit for level design purposes
- GL_Color(0.1, 0.025, 0, 1);
+ GL_Color(0.1 * r_view.colorscale, 0.025 * r_view.colorscale, 0, 1);
R_Mesh_ColorPointer(NULL);
R_Mesh_ResetTextureState();
RSurf_PrepareVerticesForBatch(false, false, numsurfaces, surfacelist);
static void R_Shadow_RenderSurfacesLighting_Light_Dot3_SpecularPass(int numsurfaces, msurface_t **surfacelist, const vec3_t lightcolorbase, rtexture_t *glosstexture, rtexture_t *normalmaptexture, float colorscale)
{
+ float glossexponent;
rmeshstate_t m;
// FIXME: detect blendsquare!
//if (!gl_support_blendsquare)
R_Mesh_ResetTextureState();
// 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)
- RSurf_DrawBatch_Simple(numsurfaces, surfacelist);
- RSurf_DrawBatch_Simple(numsurfaces, surfacelist);
+ for (glossexponent = 2;glossexponent * 2 <= r_shadow_glossexponent.value;glossexponent *= 2)
+ RSurf_DrawBatch_Simple(numsurfaces, surfacelist);
GL_LockArrays(0, 0);
// fourth pass
R_Mesh_ResetTextureState();
// 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)
- RSurf_DrawBatch_Simple(numsurfaces, surfacelist);
- RSurf_DrawBatch_Simple(numsurfaces, surfacelist);
+ for (glossexponent = 2;glossexponent * 2 <= r_shadow_glossexponent.value;glossexponent *= 2)
+ RSurf_DrawBatch_Simple(numsurfaces, surfacelist);
GL_LockArrays(0, 0);
// fourth pass
R_Mesh_ResetTextureState();
// 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)
- RSurf_DrawBatch_Simple(numsurfaces, surfacelist);
- RSurf_DrawBatch_Simple(numsurfaces, surfacelist);
+ for (glossexponent = 2;glossexponent * 2 <= r_shadow_glossexponent.value;glossexponent *= 2)
+ RSurf_DrawBatch_Simple(numsurfaces, surfacelist);
GL_LockArrays(0, 0);
// fourth pass
RSurf_PrepareVerticesForBatch(true, true, numsurfaces, surfacelist);
R_Mesh_ColorPointer(NULL);
if (doambient)
- R_Shadow_RenderSurfacesLighting_Light_Dot3_AmbientPass(numsurfaces, surfacelist, lightcolorbase, basetexture, r_shadow_rtlight->ambientscale);
+ R_Shadow_RenderSurfacesLighting_Light_Dot3_AmbientPass(numsurfaces, surfacelist, lightcolorbase, basetexture, r_shadow_rtlight->ambientscale * r_view.colorscale);
if (dodiffuse)
- R_Shadow_RenderSurfacesLighting_Light_Dot3_DiffusePass(numsurfaces, surfacelist, lightcolorbase, basetexture, normalmaptexture, r_shadow_rtlight->diffusescale);
+ R_Shadow_RenderSurfacesLighting_Light_Dot3_DiffusePass(numsurfaces, surfacelist, lightcolorbase, basetexture, normalmaptexture, r_shadow_rtlight->diffusescale * r_view.colorscale);
if (dopants)
{
if (doambient)
- R_Shadow_RenderSurfacesLighting_Light_Dot3_AmbientPass(numsurfaces, surfacelist, lightcolorpants, pantstexture, r_shadow_rtlight->ambientscale);
+ R_Shadow_RenderSurfacesLighting_Light_Dot3_AmbientPass(numsurfaces, surfacelist, lightcolorpants, pantstexture, r_shadow_rtlight->ambientscale * r_view.colorscale);
if (dodiffuse)
- R_Shadow_RenderSurfacesLighting_Light_Dot3_DiffusePass(numsurfaces, surfacelist, lightcolorpants, pantstexture, normalmaptexture, r_shadow_rtlight->diffusescale);
+ R_Shadow_RenderSurfacesLighting_Light_Dot3_DiffusePass(numsurfaces, surfacelist, lightcolorpants, pantstexture, normalmaptexture, r_shadow_rtlight->diffusescale * r_view.colorscale);
}
if (doshirt)
{
if (doambient)
- R_Shadow_RenderSurfacesLighting_Light_Dot3_AmbientPass(numsurfaces, surfacelist, lightcolorshirt, shirttexture, r_shadow_rtlight->ambientscale);
+ R_Shadow_RenderSurfacesLighting_Light_Dot3_AmbientPass(numsurfaces, surfacelist, lightcolorshirt, shirttexture, r_shadow_rtlight->ambientscale * r_view.colorscale);
if (dodiffuse)
- R_Shadow_RenderSurfacesLighting_Light_Dot3_DiffusePass(numsurfaces, surfacelist, lightcolorshirt, shirttexture, normalmaptexture, r_shadow_rtlight->diffusescale);
+ R_Shadow_RenderSurfacesLighting_Light_Dot3_DiffusePass(numsurfaces, surfacelist, lightcolorshirt, shirttexture, normalmaptexture, r_shadow_rtlight->diffusescale * r_view.colorscale);
}
if (dospecular)
- R_Shadow_RenderSurfacesLighting_Light_Dot3_SpecularPass(numsurfaces, surfacelist, lightcolorbase, glosstexture, normalmaptexture, specularscale);
+ R_Shadow_RenderSurfacesLighting_Light_Dot3_SpecularPass(numsurfaces, surfacelist, lightcolorbase, glosstexture, normalmaptexture, specularscale * r_view.colorscale);
}
void R_Shadow_RenderSurfacesLighting_Light_Vertex_Pass(const model_t *model, int numsurfaces, msurface_t **surfacelist, vec3_t diffusecolor2, vec3_t ambientcolor2)
float ambientcolorpants[3], diffusecolorpants[3];
float ambientcolorshirt[3], diffusecolorshirt[3];
rmeshstate_t m;
- VectorScale(lightcolorbase, r_shadow_rtlight->ambientscale * 2, ambientcolorbase);
- VectorScale(lightcolorbase, r_shadow_rtlight->diffusescale * 2, diffusecolorbase);
- VectorScale(lightcolorpants, r_shadow_rtlight->ambientscale * 2, ambientcolorpants);
- VectorScale(lightcolorpants, r_shadow_rtlight->diffusescale * 2, diffusecolorpants);
- VectorScale(lightcolorshirt, r_shadow_rtlight->ambientscale * 2, ambientcolorshirt);
- VectorScale(lightcolorshirt, r_shadow_rtlight->diffusescale * 2, diffusecolorshirt);
+ VectorScale(lightcolorbase, r_shadow_rtlight->ambientscale * 2 * r_view.colorscale, ambientcolorbase);
+ VectorScale(lightcolorbase, r_shadow_rtlight->diffusescale * 2 * r_view.colorscale, diffusecolorbase);
+ VectorScale(lightcolorpants, r_shadow_rtlight->ambientscale * 2 * r_view.colorscale, ambientcolorpants);
+ VectorScale(lightcolorpants, r_shadow_rtlight->diffusescale * 2 * r_view.colorscale, diffusecolorpants);
+ VectorScale(lightcolorshirt, r_shadow_rtlight->ambientscale * 2 * r_view.colorscale, ambientcolorshirt);
+ VectorScale(lightcolorshirt, r_shadow_rtlight->diffusescale * 2 * r_view.colorscale, diffusecolorshirt);
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
R_Mesh_ColorPointer(rsurface_array_color4f);
memset(&m, 0, sizeof(m));
lightcolorbase[2] = r_shadow_rtlight->currentcolor[2] * rsurface_entity->colormod[2] * rsurface_texture->currentalpha;
if ((r_shadow_rtlight->ambientscale + r_shadow_rtlight->diffusescale) * VectorLength2(lightcolorbase) + (r_shadow_rtlight->specularscale * rsurface_texture->specularscale) * VectorLength2(lightcolorbase) < (1.0f / 1048576.0f))
return;
- if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
- {
- qglDisable(GL_CULL_FACE);CHECKGLERROR
- }
- else
- {
- qglEnable(GL_CULL_FACE);CHECKGLERROR
- }
+ GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
+ GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
if (rsurface_texture->colormapping)
{
- qboolean dopants = rsurface_texture->skin.pants != NULL && VectorLength2(rsurface_entity->colormap_pantscolor) >= (1.0f / 1048576.0f);
- qboolean doshirt = rsurface_texture->skin.shirt != NULL && VectorLength2(rsurface_entity->colormap_shirtcolor) >= (1.0f / 1048576.0f);
+ qboolean dopants = rsurface_texture->currentskinframe->pants != NULL && VectorLength2(rsurface_entity->colormap_pantscolor) >= (1.0f / 1048576.0f);
+ qboolean doshirt = rsurface_texture->currentskinframe->shirt != NULL && VectorLength2(rsurface_entity->colormap_shirtcolor) >= (1.0f / 1048576.0f);
if (dopants)
{
lightcolorpants[0] = lightcolorbase[0] * rsurface_entity->colormap_pantscolor[0];
switch (r_shadow_rendermode)
{
case R_SHADOW_RENDERMODE_VISIBLELIGHTING:
- R_Shadow_RenderSurfacesLighting_VisibleLighting(numsurfaces, surfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, rsurface_texture->basetexture, rsurface_texture->skin.pants, rsurface_texture->skin.shirt, rsurface_texture->skin.nmap, rsurface_texture->glosstexture, r_shadow_rtlight->specularscale * rsurface_texture->specularscale, dopants, doshirt);
+ GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) && !r_showdisabledepthtest.integer);
+ R_Shadow_RenderSurfacesLighting_VisibleLighting(numsurfaces, surfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, rsurface_texture->basetexture, rsurface_texture->currentskinframe->pants, rsurface_texture->currentskinframe->shirt, rsurface_texture->currentskinframe->nmap, rsurface_texture->glosstexture, r_shadow_rtlight->specularscale * rsurface_texture->specularscale, dopants, doshirt);
break;
case R_SHADOW_RENDERMODE_LIGHT_GLSL:
- R_Shadow_RenderSurfacesLighting_Light_GLSL(numsurfaces, surfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, rsurface_texture->basetexture, rsurface_texture->skin.pants, rsurface_texture->skin.shirt, rsurface_texture->skin.nmap, rsurface_texture->glosstexture, r_shadow_rtlight->specularscale * rsurface_texture->specularscale, dopants, doshirt);
+ R_Shadow_RenderSurfacesLighting_Light_GLSL(numsurfaces, surfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, rsurface_texture->basetexture, rsurface_texture->currentskinframe->pants, rsurface_texture->currentskinframe->shirt, rsurface_texture->currentskinframe->nmap, rsurface_texture->glosstexture, r_shadow_rtlight->specularscale * rsurface_texture->specularscale, dopants, doshirt);
break;
case R_SHADOW_RENDERMODE_LIGHT_DOT3:
- R_Shadow_RenderSurfacesLighting_Light_Dot3(numsurfaces, surfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, rsurface_texture->basetexture, rsurface_texture->skin.pants, rsurface_texture->skin.shirt, rsurface_texture->skin.nmap, rsurface_texture->glosstexture, r_shadow_rtlight->specularscale * rsurface_texture->specularscale, dopants, doshirt);
+ R_Shadow_RenderSurfacesLighting_Light_Dot3(numsurfaces, surfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, rsurface_texture->basetexture, rsurface_texture->currentskinframe->pants, rsurface_texture->currentskinframe->shirt, rsurface_texture->currentskinframe->nmap, rsurface_texture->glosstexture, r_shadow_rtlight->specularscale * rsurface_texture->specularscale, dopants, doshirt);
break;
case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
- R_Shadow_RenderSurfacesLighting_Light_Vertex(numsurfaces, surfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, rsurface_texture->basetexture, rsurface_texture->skin.pants, rsurface_texture->skin.shirt, rsurface_texture->skin.nmap, rsurface_texture->glosstexture, r_shadow_rtlight->specularscale * rsurface_texture->specularscale, dopants, doshirt);
+ R_Shadow_RenderSurfacesLighting_Light_Vertex(numsurfaces, surfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, rsurface_texture->basetexture, rsurface_texture->currentskinframe->pants, rsurface_texture->currentskinframe->shirt, rsurface_texture->currentskinframe->nmap, rsurface_texture->glosstexture, r_shadow_rtlight->specularscale * rsurface_texture->specularscale, dopants, doshirt);
break;
default:
Con_Printf("R_Shadow_RenderSurfacesLighting: unknown r_shadow_rendermode %i\n", r_shadow_rendermode);
switch (r_shadow_rendermode)
{
case R_SHADOW_RENDERMODE_VISIBLELIGHTING:
- R_Shadow_RenderSurfacesLighting_VisibleLighting(numsurfaces, surfacelist, lightcolorbase, vec3_origin, vec3_origin, rsurface_texture->basetexture, r_texture_black, r_texture_black, rsurface_texture->skin.nmap, rsurface_texture->glosstexture, r_shadow_rtlight->specularscale * rsurface_texture->specularscale, false, false);
+ GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) && !r_showdisabledepthtest.integer);
+ R_Shadow_RenderSurfacesLighting_VisibleLighting(numsurfaces, surfacelist, lightcolorbase, vec3_origin, vec3_origin, rsurface_texture->basetexture, r_texture_black, r_texture_black, rsurface_texture->currentskinframe->nmap, rsurface_texture->glosstexture, r_shadow_rtlight->specularscale * rsurface_texture->specularscale, false, false);
break;
case R_SHADOW_RENDERMODE_LIGHT_GLSL:
- R_Shadow_RenderSurfacesLighting_Light_GLSL(numsurfaces, surfacelist, lightcolorbase, vec3_origin, vec3_origin, rsurface_texture->basetexture, r_texture_black, r_texture_black, rsurface_texture->skin.nmap, rsurface_texture->glosstexture, r_shadow_rtlight->specularscale * rsurface_texture->specularscale, false, false);
+ R_Shadow_RenderSurfacesLighting_Light_GLSL(numsurfaces, surfacelist, lightcolorbase, vec3_origin, vec3_origin, rsurface_texture->basetexture, r_texture_black, r_texture_black, rsurface_texture->currentskinframe->nmap, rsurface_texture->glosstexture, r_shadow_rtlight->specularscale * rsurface_texture->specularscale, false, false);
break;
case R_SHADOW_RENDERMODE_LIGHT_DOT3:
- R_Shadow_RenderSurfacesLighting_Light_Dot3(numsurfaces, surfacelist, lightcolorbase, vec3_origin, vec3_origin, rsurface_texture->basetexture, r_texture_black, r_texture_black, rsurface_texture->skin.nmap, rsurface_texture->glosstexture, r_shadow_rtlight->specularscale * rsurface_texture->specularscale, false, false);
+ R_Shadow_RenderSurfacesLighting_Light_Dot3(numsurfaces, surfacelist, lightcolorbase, vec3_origin, vec3_origin, rsurface_texture->basetexture, r_texture_black, r_texture_black, rsurface_texture->currentskinframe->nmap, rsurface_texture->glosstexture, r_shadow_rtlight->specularscale * rsurface_texture->specularscale, false, false);
break;
case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
- R_Shadow_RenderSurfacesLighting_Light_Vertex(numsurfaces, surfacelist, lightcolorbase, vec3_origin, vec3_origin, rsurface_texture->basetexture, r_texture_black, r_texture_black, rsurface_texture->skin.nmap, rsurface_texture->glosstexture, r_shadow_rtlight->specularscale * rsurface_texture->specularscale, false, false);
+ R_Shadow_RenderSurfacesLighting_Light_Vertex(numsurfaces, surfacelist, lightcolorbase, vec3_origin, vec3_origin, rsurface_texture->basetexture, r_texture_black, r_texture_black, rsurface_texture->currentskinframe->nmap, rsurface_texture->glosstexture, r_shadow_rtlight->specularscale * rsurface_texture->specularscale, false, false);
break;
default:
Con_Printf("R_Shadow_RenderSurfacesLighting: unknown r_shadow_rendermode %i\n", r_shadow_rendermode);
void R_RTLight_Update(dlight_t *light, int isstatic)
{
- int j, k;
- float scale;
+ double scale;
rtlight_t *rtlight = &light->rtlight;
R_RTLight_Uncompile(rtlight);
memset(rtlight, 0, sizeof(*rtlight));
rtlight->cullmaxs[2] = rtlight->shadoworigin[2] + rtlight->radius;
rtlight->cubemapname[0] = 0;
if (light->cubemapname[0])
- strcpy(rtlight->cubemapname, light->cubemapname);
+ strlcpy(rtlight->cubemapname, light->cubemapname, sizeof(rtlight->cubemapname));
else if (light->cubemapnum > 0)
sprintf(rtlight->cubemapname, "cubemaps/%i", light->cubemapnum);
rtlight->shadow = light->shadow;
rtlight->specularscale = light->specularscale;
rtlight->flags = light->flags;
Matrix4x4_Invert_Simple(&rtlight->matrix_worldtolight, &light->matrix);
- // ConcatScale won't work here because this needs to scale rotate and
- // translate, not just rotate
- scale = 1.0f / rtlight->radius;
- for (k = 0;k < 3;k++)
- for (j = 0;j < 4;j++)
- rtlight->matrix_worldtolight.m[k][j] *= scale;
+ // this has to scale both rotate and translate because this is an already
+ // inverted matrix (it transforms from world to light space, not the other
+ // way around)
+ scale = 1.0 / rtlight->radius;
+ Matrix4x4_Scale(&rtlight->matrix_worldtolight, scale, scale);
}
// compiles rtlight geometry
if (numsurfaces)
memcpy(rtlight->static_surfacelist, r_shadow_buffer_surfacelist, rtlight->static_numsurfaces * sizeof(*rtlight->static_surfacelist));
if (model->CompileShadowVolume && rtlight->shadow)
- model->CompileShadowVolume(ent, rtlight->shadoworigin, rtlight->radius, numsurfaces, r_shadow_buffer_surfacelist);
+ model->CompileShadowVolume(ent, rtlight->shadoworigin, NULL, rtlight->radius, numsurfaces, r_shadow_buffer_surfacelist);
// now we're done compiling the rtlight
r_shadow_compilingrtlight = NULL;
}
if (r_shadow_rendermode == R_SHADOW_RENDERMODE_STENCIL)
{
// decrement stencil if backface is behind depthbuffer
- qglCullFace(GL_BACK);CHECKGLERROR // quake is backwards, this culls front faces
+ GL_CullFace(GL_BACK); // quake is backwards, this culls front faces
qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);CHECKGLERROR
R_Mesh_Draw(0, mesh->numverts, mesh->numtriangles, mesh->element3i);
// increment stencil if frontface is behind depthbuffer
- qglCullFace(GL_FRONT);CHECKGLERROR // quake is backwards, this culls back faces
+ GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);CHECKGLERROR
}
R_Mesh_Draw(0, mesh->numverts, mesh->numtriangles, mesh->element3i);
else if (numsurfaces)
{
R_Mesh_Matrix(&ent->matrix);
- model->DrawShadowVolume(ent, r_shadow_rtlight->shadoworigin, r_shadow_rtlight->radius, numsurfaces, surfacelist, r_shadow_rtlight->cullmins, r_shadow_rtlight->cullmaxs);
+ model->DrawShadowVolume(ent, r_shadow_rtlight->shadoworigin, NULL, r_shadow_rtlight->radius, numsurfaces, surfacelist, r_shadow_rtlight->cullmins, r_shadow_rtlight->cullmaxs);
}
}
else
relativeshadowmaxs[1] = relativeshadoworigin[1] + relativeshadowradius;
relativeshadowmaxs[2] = relativeshadoworigin[2] + relativeshadowradius;
R_Mesh_Matrix(&ent->matrix);
- model->DrawShadowVolume(ent, relativeshadoworigin, relativeshadowradius, model->nummodelsurfaces, model->surfacelist, relativeshadowmins, relativeshadowmaxs);
+ model->DrawShadowVolume(ent, relativeshadoworigin, NULL, relativeshadowradius, model->nummodelsurfaces, model->surfacelist, relativeshadowmins, relativeshadowmaxs);
}
}
&& (r_refdef.worldmodel == NULL || r_refdef.worldmodel->brush.BoxTouchingLeafPVS == NULL || r_refdef.worldmodel->brush.BoxTouchingLeafPVS(r_refdef.worldmodel, leafpvs, ent->mins, ent->maxs)))
{
// about the VectorDistance2 - light emitting entities should not cast their own shadow
- if ((ent->flags & RENDER_SHADOW) && model->DrawShadowVolume && VectorDistance2(ent->origin, rtlight->shadoworigin) > 0.1)
+ vec3_t org;
+ Matrix4x4_OriginFromMatrix(&ent->matrix, org);
+ if ((ent->flags & RENDER_SHADOW) && model->DrawShadowVolume && VectorDistance2(org, rtlight->shadoworigin) > 0.1)
shadowentities[numshadowentities++] = ent;
if (r_viewcache.entityvisible[i] && (ent->flags & RENDER_LIGHT) && model->DrawLight)
lightentities[numlightentities++] = ent;
R_Shadow_RenderMode_End();
}
+extern void R_SetupView(const matrix4x4_t *matrix);
+extern cvar_t r_shadows_throwdistance;
+void R_DrawModelShadows(void)
+{
+ int i;
+ float relativethrowdistance;
+ entity_render_t *ent;
+ vec3_t relativelightorigin;
+ vec3_t relativelightdirection;
+ vec3_t relativeshadowmins, relativeshadowmaxs;
+ float vertex3f[12];
+
+ if (!r_drawentities.integer || !gl_stencil)
+ return;
+
+ CHECKGLERROR
+ GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
+
+ r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
+
+ if (gl_ext_stenciltwoside.integer)
+ r_shadow_shadowingrendermode = R_SHADOW_RENDERMODE_STENCILTWOSIDE;
+ else
+ r_shadow_shadowingrendermode = R_SHADOW_RENDERMODE_STENCIL;
+
+ R_Shadow_RenderMode_StencilShadowVolumes();
+
+ for (i = 0;i < r_refdef.numentities;i++)
+ {
+ ent = r_refdef.entities[i];
+ // cast shadows from anything that is not a submodel of the map
+ if (ent->model && ent->model->DrawShadowVolume != NULL && !ent->model->brush.submodel && (ent->flags & RENDER_SHADOW))
+ {
+ relativethrowdistance = r_shadows_throwdistance.value * Matrix4x4_ScaleFromMatrix(&ent->inversematrix);
+ VectorSet(relativeshadowmins, -relativethrowdistance, -relativethrowdistance, -relativethrowdistance);
+ VectorSet(relativeshadowmaxs, relativethrowdistance, relativethrowdistance, relativethrowdistance);
+ VectorNegate(ent->modellight_lightdir, relativelightdirection);
+ VectorScale(relativelightdirection, -relativethrowdistance, relativelightorigin);
+ R_Mesh_Matrix(&ent->matrix);
+ ent->model->DrawShadowVolume(ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->nummodelsurfaces, ent->model->surfacelist, relativeshadowmins, relativeshadowmaxs);
+ }
+ }
+
+ // not really the right mode, but this will disable any silly stencil features
+ R_Shadow_RenderMode_VisibleLighting(true, true);
+
+ // vertex coordinates for a quad that covers the screen exactly
+ vertex3f[0] = 0;vertex3f[1] = 0;vertex3f[2] = 0;
+ vertex3f[3] = 1;vertex3f[4] = 0;vertex3f[5] = 0;
+ vertex3f[6] = 1;vertex3f[7] = 1;vertex3f[8] = 0;
+ vertex3f[9] = 0;vertex3f[10] = 1;vertex3f[11] = 0;
+
+ // set up ortho view for rendering this pass
+ GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
+ GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
+ GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
+ GL_ScissorTest(true);
+ R_Mesh_Matrix(&identitymatrix);
+ R_Mesh_ResetTextureState();
+ R_Mesh_VertexPointer(vertex3f);
+ R_Mesh_ColorPointer(NULL);
+
+ // set up a 50% darkening blend on shadowed areas
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ GL_DepthTest(false);
+ GL_DepthMask(false);
+ qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
+ GL_Color(0, 0, 0, 0.5);
+ GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
+ qglDepthFunc(GL_ALWAYS);CHECKGLERROR
+ qglEnable(GL_STENCIL_TEST);CHECKGLERROR
+ qglStencilMask(~0);CHECKGLERROR
+ qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
+ qglStencilFunc(GL_NOTEQUAL, 128, ~0);CHECKGLERROR
+
+ // apply the blend to the shadowed areas
+ R_Mesh_Draw(0, 4, 2, polygonelements);
+
+ // restore perspective view
+ R_SetupView(&r_view.matrix);
+
+ // restore other state to normal
+ GL_DepthTest(true);
+ R_Shadow_RenderMode_End();
+}
+
+
//static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
typedef struct suffixinfo_s
{
if (i >= MAX_CUBEMAPS)
return r_texture_whitecube;
numcubemaps++;
- strcpy(cubemaps[i].basename, basename);
+ strlcpy(cubemaps[i].basename, basename, sizeof(cubemaps[i].basename));
cubemaps[i].texture = R_Shadow_LoadCubemap(cubemaps[i].basename);
if (!cubemaps[i].texture)
cubemaps[i].texture = r_texture_whitecube;
// remove quotes on cubemapname
if (cubemapname[0] == '"' && cubemapname[strlen(cubemapname) - 1] == '"')
{
- cubemapname[strlen(cubemapname)-1] = 0;
- strcpy(cubemapname, cubemapname + 1);
+ size_t namelen;
+ namelen = strlen(cubemapname) - 2;
+ memmove(cubemapname, cubemapname + 1, namelen);
+ cubemapname[namelen] = '\0';
}
if (a < 8)
{
data = r_refdef.worldmodel->brush.entities;
if (!data)
return;
- for (entnum = 0;COM_ParseToken(&data, false) && com_token[0] == '{';entnum++)
+ for (entnum = 0;COM_ParseTokenConsole(&data) && com_token[0] == '{';entnum++)
{
type = LIGHTTYPE_MINUSX;
origin[0] = origin[1] = origin[2] = 0;
islight = false;
while (1)
{
- if (!COM_ParseToken(&data, false))
+ if (!COM_ParseTokenConsole(&data))
break; // error
if (com_token[0] == '}')
break; // end of entity
if (com_token[0] == '_')
- strcpy(key, com_token + 1);
+ strlcpy(key, com_token + 1, sizeof(key));
else
- strcpy(key, com_token);
+ strlcpy(key, com_token, sizeof(key));
while (key[strlen(key)-1] == ' ') // remove trailing spaces
key[strlen(key)-1] = 0;
- if (!COM_ParseToken(&data, false))
+ if (!COM_ParseTokenConsole(&data))
break; // error
- strcpy(value, com_token);
+ strlcpy(value, com_token, sizeof(value));
// now that we have the key pair worked out...
if (!strcmp("light", key))
return;
}
if (Cmd_Argc() == 3)
- strcpy(cubemapname, Cmd_Argv(2));
+ strlcpy(cubemapname, Cmd_Argv(2), sizeof(cubemapname));
else
cubemapname[0] = 0;
}
r_shadow_bufferlight.radius = r_shadow_selectedlight->radius;
r_shadow_bufferlight.style = r_shadow_selectedlight->style;
if (r_shadow_selectedlight->cubemapname)
- strcpy(r_shadow_bufferlight.cubemapname, r_shadow_selectedlight->cubemapname);
+ strlcpy(r_shadow_bufferlight.cubemapname, r_shadow_selectedlight->cubemapname, sizeof(r_shadow_bufferlight.cubemapname));
else
r_shadow_bufferlight.cubemapname[0] = 0;
r_shadow_bufferlight.shadow = r_shadow_selectedlight->shadow;