X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=r_shadow.c;h=523457a00cd92508c2a057bbb5fc15761103e262;hb=d191d2aae518b7fe21132a6c159554a350966978;hp=613d447d9dcc04120a629bd736fa0d26ebfdfa0d;hpb=ee573a5631ec70bc3c32d6cfbb90aeefcf7e28d4;p=xonotic%2Fdarkplaces.git diff --git a/r_shadow.c b/r_shadow.c index 613d447d..523457a0 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -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;