]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - r_shadow.c
rewrote PRVM_AllocString and PRVM_FreeString to deal with string offsets directly...
[xonotic/darkplaces.git] / r_shadow.c
index 613d447d9dcc04120a629bd736fa0d26ebfdfa0d..523457a00cd92508c2a057bbb5fc15761103e262 100644 (file)
@@ -7,26 +7,25 @@ as far as the light's radius, if the light has a radius at all), capped at
 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).
 
 
 
@@ -452,8 +451,8 @@ void r_shadow_start(void)
                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;
@@ -674,7 +673,7 @@ void R_Shadow_Init(void)
        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},
@@ -684,7 +683,7 @@ static matrix4x4_t matrix_attenuationxyz =
        }
 };
 
-static matrix4x4_t matrix_attenuationz =
+matrix4x4_t matrix_attenuationz =
 {
        {
                {0.0, 0.0, 0.5, 0.5},
@@ -947,15 +946,15 @@ void R_Shadow_RenderVolume(int numvertices, int numtriangles, const float *verte
        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++;
@@ -1113,7 +1112,7 @@ void R_Shadow_Stage_StencilShadowVolumes(void)
        //}
        //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);
@@ -1124,10 +1123,10 @@ void R_Shadow_Stage_StencilShadowVolumes(void)
                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
        {
@@ -1222,7 +1221,7 @@ void R_Shadow_Stage_Lighting(int stenciltest)
                        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;
@@ -1369,7 +1368,7 @@ qboolean R_Shadow_ScissorForBBox(const float *mins, const float *maxs)
                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++;
@@ -1573,7 +1572,7 @@ void R_Shadow_RenderLighting(int firstvertex, int numvertices, int numtriangles,
        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)
@@ -1601,7 +1600,7 @@ void R_Shadow_RenderLighting(int firstvertex, int numvertices, int numtriangles,
                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)
@@ -2633,7 +2632,7 @@ void R_RTLight_Compile(rtlight_t *rtlight)
        {
                // 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);
@@ -2743,15 +2742,15 @@ void R_Shadow_DrawEntityShadow(entity_render_t *ent, rtlight_t *rtlight, int num
                                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++;
@@ -2873,7 +2872,7 @@ void R_DrawRTLight(rtlight_t *rtlight, qboolean visible)
        {
                // 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;
@@ -3253,7 +3252,7 @@ void R_Shadow_LoadWorldLights(void)
        }
        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;
@@ -3396,7 +3395,7 @@ void R_Shadow_LoadLightsFile(void)
        }
        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;
@@ -3452,7 +3451,7 @@ void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void)
        // 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;