both front and back to avoid any problems (extrusion from dark faces also
works but has a different set of problems)
-This is rendered using Carmack's Reverse technique, in which backfaces behind
-zbuffer (zfail) increment the stencil, and frontfaces behind zbuffer (zfail)
-decrement the stencil, the result is a stencil value of zero where shadows
-did not intersect the visible geometry, suitable as a stencil mask for
-rendering lighting everywhere but shadow.
-
-In our case to hopefully avoid the Creative Labs patent on Carmack's Reverse,
-we use a biased stencil clear of 128 (which also negates the need for the
-stencil wrap extension), we draw the frontfaces first and backfaces second
-(decrement, increment), and we redefine the DepthFunc to zpass when behind of
-surfaces and zfail when infront (this means zpass is decr/incr during volume
-rendering, not zfail).
+This is normally rendered using Carmack's Reverse technique, in which
+backfaces behind zbuffer (zfail) increment the stencil, and frontfaces behind
+zbuffer (zfail) decrement the stencil, the result is a stencil value of zero
+where shadows did not intersect the visible geometry, suitable as a stencil
+mask for rendering lighting everywhere but shadow.
+
+In our case to hopefully avoid the Creative Labs patent, we draw the backfaces
+as decrement and the frontfaces as increment, and we redefine the DepthFunc to
+GL_LESS (the patent uses GL_GEQUAL) which causes zfail when behind surfaces
+and zpass when infront (the patent draws where zpass with a GL_GEQUAL test),
+additionally we clear stencil to 128 to avoid the need for the unclamped
+incr/decr extension (not related to patent).
Patent warning:
-This algorithm may be covered by Creative's patent (US Patent #6384822)
-on Carmack's Reverse paper (which I have not read), however that patent
-seems to be about drawing a stencil shadow from a model in an otherwise
-unshadowed scene, where as realtime lighting technology draws light where
-shadows do not lie, additionally the stencil clear, zfail/zpass rules and
-incr/decr order are different in this implementation.
+This algorithm may be covered by Creative's patent (US Patent #6384822),
+however that patent is quite specific about increment on backfaces and
+decrement on frontfaces where zpass with GL_GEQUAL depth test, which is
+opposite this implementation and partially opposite Carmack's Reverse paper
+(which uses GL_LESS, but increments on backfaces and decrements on frontfaces).
int fragstrings_count;
const char *vertstrings_list[SHADERPERMUTATION_COUNT];
const char *fragstrings_list[SHADERPERMUTATION_COUNT];
- vertstring = FS_LoadFile("glsl/light.vert", tempmempool, false);
- fragstring = FS_LoadFile("glsl/light.frag", tempmempool, false);
+ vertstring = (char *)FS_LoadFile("glsl/light.vert", tempmempool, false);
+ fragstring = (char *)FS_LoadFile("glsl/light.frag", tempmempool, false);
for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
{
vertstrings_count = 0;
R_RegisterModule("R_Shadow", r_shadow_start, r_shadow_shutdown, r_shadow_newmap);
}
-static matrix4x4_t matrix_attenuationxyz =
+matrix4x4_t matrix_attenuationxyz =
{
{
{0.5, 0.0, 0.0, 0.5},
}
};
-static matrix4x4_t matrix_attenuationz =
+matrix4x4_t matrix_attenuationz =
{
{
{0.0, 0.0, 0.5, 0.5},
GL_LockArrays(0, numvertices);
if (r_shadowstage == R_SHADOWSTAGE_STENCIL)
{
- // increment stencil if backface is behind depthbuffer
+ // decrement stencil if backface is behind depthbuffer
qglCullFace(GL_BACK); // quake is backwards, this culls front faces
- qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
+ qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
R_Mesh_Draw(0, numvertices, numtriangles, element3i);
c_rt_shadowmeshes++;
c_rt_shadowtris += numtriangles;
- // decrement stencil if frontface is behind depthbuffer
+ // increment stencil if frontface is behind depthbuffer
qglCullFace(GL_FRONT); // quake is backwards, this culls back faces
- qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
+ qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
}
R_Mesh_Draw(0, numvertices, numtriangles, element3i);
c_rt_shadowmeshes++;
//}
//else
// qglDisable(GL_POLYGON_OFFSET_FILL);
- qglDepthFunc(GL_GEQUAL);
+ qglDepthFunc(GL_LESS);
qglCullFace(GL_FRONT); // quake is backwards, this culls back faces
qglEnable(GL_STENCIL_TEST);
qglStencilFunc(GL_ALWAYS, 128, ~0);
qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
qglActiveStencilFaceEXT(GL_BACK); // quake is backwards, this is front faces
qglStencilMask(~0);
- qglStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
+ qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
qglActiveStencilFaceEXT(GL_FRONT); // quake is backwards, this is back faces
qglStencilMask(~0);
- qglStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
+ qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
}
else
{
qglUniform1fARB(qglGetUniformLocationARB(r_shadow_lightprog, "OffsetMapping_Bias"), r_shadow_glsl_offsetmapping_bias.value);CHECKGLERROR
}
}
- else if (gl_dot3arb && gl_texturecubemap && gl_combine.integer && gl_stencil)
+ 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;
return true;
// the light area is visible, set up the scissor rectangle
- GL_Scissor(ix1, vid.realheight - iy2, ix2 - ix1, iy2 - iy1);
+ GL_Scissor(ix1, vid.height - iy2, ix2 - ix1, iy2 - iy1);
//qglScissor(ix1, iy1, ix2 - ix1, iy2 - iy1);
//qglEnable(GL_SCISSOR_TEST);
c_rt_scissored++;
int renders;
float color[3], color2[3], colorscale, specularscale;
rmeshstate_t m;
- // FIXME: support EF_NODEPTHTEST
+ // FIXME: support MATERIALFLAG_NODEPTHTEST
if (!basetexture)
basetexture = r_texture_white;
if (!bumptexture)
int passes = 0;
if (r_shadow_glsl.integer && r_shadow_program_light[0])
passes++; // GLSL shader path (GFFX5200, Radeon 9500)
- else if (gl_dot3arb && gl_texturecubemap && gl_combine.integer && gl_stencil)
+ else if (gl_dot3arb && gl_texturecubemap && r_textureunits.integer >= 2 && gl_combine.integer && gl_stencil)
{
// TODO: add direct pants/shirt rendering
if (pantstexture && (r_shadow_rtlight->ambientscale + r_shadow_rtlight->diffusescale) * VectorLength2(lightcolorpants) > 0.001)
{
// this variable directs the DrawShadowVolume and DrawLight code to capture into the mesh chain instead of rendering
r_shadow_compilingrtlight = rtlight;
- R_Shadow_EnlargeLeafSurfaceBuffer(model->brush.num_leafs, model->brush.num_surfaces);
+ R_Shadow_EnlargeLeafSurfaceBuffer(model->brush.num_leafs, model->num_surfaces);
model->GetLightInfo(ent, rtlight->shadoworigin, rtlight->radius, rtlight->cullmins, rtlight->cullmaxs, r_shadow_buffer_leaflist, r_shadow_buffer_leafpvs, &numleafs, r_shadow_buffer_surfacelist, r_shadow_buffer_surfacepvs, &numsurfaces);
numleafpvsbytes = (model->brush.num_leafs + 7) >> 3;
data = Mem_Alloc(r_shadow_mempool, sizeof(int) * numleafs + numleafpvsbytes + sizeof(int) * numsurfaces);
GL_LockArrays(0, mesh->numverts);
if (r_shadowstage == R_SHADOWSTAGE_STENCIL)
{
- // increment stencil if backface is behind depthbuffer
+ // decrement stencil if backface is behind depthbuffer
qglCullFace(GL_BACK); // quake is backwards, this culls front faces
- qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
+ qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
R_Mesh_Draw(0, mesh->numverts, mesh->numtriangles, mesh->element3i);
c_rtcached_shadowmeshes++;
c_rtcached_shadowtris += mesh->numtriangles;
- // decrement stencil if frontface is behind depthbuffer
+ // increment stencil if frontface is behind depthbuffer
qglCullFace(GL_FRONT); // quake is backwards, this culls back faces
- qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
+ qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
}
R_Mesh_Draw(0, mesh->numverts, mesh->numtriangles, mesh->element3i);
c_rtcached_shadowmeshes++;
{
// dynamic light, world available and can receive realtime lighting
// calculate lit surfaces and leafs
- R_Shadow_EnlargeLeafSurfaceBuffer(r_refdef.worldmodel->brush.num_leafs, r_refdef.worldmodel->brush.num_surfaces);
+ R_Shadow_EnlargeLeafSurfaceBuffer(r_refdef.worldmodel->brush.num_leafs, r_refdef.worldmodel->num_surfaces);
r_refdef.worldmodel->GetLightInfo(r_refdef.worldentity, rtlight->shadoworigin, rtlight->radius, rtlight->cullmins, rtlight->cullmaxs, r_shadow_buffer_leaflist, r_shadow_buffer_leafpvs, &numleafs, r_shadow_buffer_surfacelist, r_shadow_buffer_surfacepvs, &numsurfaces);
leaflist = r_shadow_buffer_leaflist;
leafpvs = r_shadow_buffer_leafpvs;
}
FS_StripExtension (r_refdef.worldmodel->name, name, sizeof (name));
strlcat (name, ".rtlights", sizeof (name));
- lightsstring = FS_LoadFile(name, tempmempool, false);
+ lightsstring = (char *)FS_LoadFile(name, tempmempool, false);
if (lightsstring)
{
s = lightsstring;
}
FS_StripExtension (r_refdef.worldmodel->name, name, sizeof (name));
strlcat (name, ".lights", sizeof (name));
- lightsstring = FS_LoadFile(name, tempmempool, false);
+ lightsstring = (char *)FS_LoadFile(name, tempmempool, false);
if (lightsstring)
{
s = lightsstring;
// try to load a .ent file first
FS_StripExtension (r_refdef.worldmodel->name, key, sizeof (key));
strlcat (key, ".ent", sizeof (key));
- data = entfiledata = FS_LoadFile(key, tempmempool, true);
+ data = entfiledata = (char *)FS_LoadFile(key, tempmempool, true);
// and if that is not found, fall back to the bsp file entity string
if (!data)
data = r_refdef.worldmodel->brush.entities;