From b7bec17fc069aac4bb8bc7739bb2ea3cb98e4f4b Mon Sep 17 00:00:00 2001 From: havoc Date: Sun, 21 Jan 2007 14:21:53 +0000 Subject: [PATCH] reorganized view rendering setup code a bit to reduce potential for state bugs (more thorough and consistent state resets now) added support for glStencilOpSeparate function in OpenGL 2.0 (or GL_ATI_separate_stencil extension prior to that), so ATI cards should get a speed boost now, this path is now also used on NVIDIA hardware, but support for GL_EXT_stencil_two_side extension has been retained to support several other vendors git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@6714 d7cf8633-e32d-0410-b094-e92efae38249 --- gl_rmain.c | 132 +++++++++++++++++++++++++++++---------------------- glquake.h | 11 +++++ r_shadow.c | 121 ++++++++++++++++------------------------------ r_shadow.h | 1 + vid_shared.c | 22 +++++++++ 5 files changed, 152 insertions(+), 135 deletions(-) diff --git a/gl_rmain.c b/gl_rmain.c index 76ab2271..af26ca6f 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -1408,23 +1408,78 @@ void R_View_Update(void) R_View_UpdateEntityVisible(); } -void R_ResetViewRendering(void) +void R_SetupView(const matrix4x4_t *matrix) +{ + if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows) + GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip); + else + GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip); + + GL_SetupView_Orientation_FromEntity(matrix); +} + +void R_ResetViewRendering2D(void) { if (gl_support_fragment_shader) { qglUseProgramObjectARB(0);CHECKGLERROR } + DrawQ_Finish(); + // GL is weird because it's bottom to top, r_view.y is top to bottom qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR 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_Color(1, 1, 1, 1); GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1); + GL_BlendFunc(GL_ONE, GL_ZERO); + GL_AlphaTest(false); GL_ScissorTest(false); GL_DepthMask(false); GL_DepthTest(false); R_Mesh_Matrix(&identitymatrix); R_Mesh_ResetTextureState(); + qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR + qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR + qglDepthFunc(GL_LEQUAL);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 +} + +void R_ResetViewRendering3D(void) +{ + if (gl_support_fragment_shader) + { + qglUseProgramObjectARB(0);CHECKGLERROR + } + + DrawQ_Finish(); + + // GL is weird because it's bottom to top, r_view.y is top to bottom + qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR + R_SetupView(&r_view.matrix); + GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height); + GL_Color(1, 1, 1, 1); + GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1); + GL_BlendFunc(GL_ONE, GL_ZERO); + GL_AlphaTest(false); + GL_ScissorTest(true); + GL_DepthMask(true); + GL_DepthTest(true); + R_Mesh_Matrix(&identitymatrix); + R_Mesh_ResetTextureState(); + qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR + qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR + qglDepthFunc(GL_LEQUAL);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 } /* @@ -1488,16 +1543,6 @@ void R_ResetViewRendering(void) "#endif // FRAGMENT_SHADER\n" */ -void R_SetupView(const matrix4x4_t *matrix) -{ - if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows) - GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip); - else - GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip); - - GL_SetupView_Orientation_FromEntity(matrix); -} - void R_RenderScene(void); void R_Bloom_StartFrame(void) @@ -1603,7 +1648,7 @@ void R_Bloom_CopyScreenTexture(float colorscale) { r_refdef.stats.bloom++; - R_ResetViewRendering(); + R_ResetViewRendering2D(); R_Mesh_VertexPointer(r_screenvertex3f); R_Mesh_ColorPointer(NULL); R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f); @@ -1649,7 +1694,7 @@ void R_Bloom_MakeTexture(void) r_refdef.stats.bloom++; - R_ResetViewRendering(); + R_ResetViewRendering2D(); R_Mesh_VertexPointer(r_screenvertex3f); R_Mesh_ColorPointer(NULL); @@ -1758,23 +1803,23 @@ void R_HDR_RenderBloomTexture(void) // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance. // TODO: add exposure compensation features + // TODO: add fp16 framebuffer support r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value; R_RenderScene(); - R_ResetViewRendering(); + R_ResetViewRendering2D(); R_Bloom_CopyHDRTexture(); R_Bloom_MakeTexture(); - R_ResetViewRendering(); - GL_ScissorTest(true); - GL_DepthMask(true); - GL_DepthTest(true); + R_ResetViewRendering3D(); + R_ClearScreen(); if (r_timereport_active) R_TimeReport("clear"); + // restore the view settings r_view.width = oldwidth; r_view.height = oldheight; @@ -1787,7 +1832,7 @@ static void R_BlendView(void) // render high dynamic range bloom effect // the bloom texture was made earlier this render, so we just need to // blend it onto the screen... - R_ResetViewRendering(); + R_ResetViewRendering2D(); R_Mesh_VertexPointer(r_screenvertex3f); R_Mesh_ColorPointer(NULL); GL_Color(1, 1, 1, 1); @@ -1806,7 +1851,7 @@ static void R_BlendView(void) R_Bloom_MakeTexture(); // put the original screen image back in place and blend the bloom // texture on it - R_ResetViewRendering(); + R_ResetViewRendering2D(); R_Mesh_VertexPointer(r_screenvertex3f); R_Mesh_ColorPointer(NULL); GL_Color(1, 1, 1, 1); @@ -1835,7 +1880,7 @@ static void R_BlendView(void) if (r_refdef.viewblend[3] >= (1.0f / 256.0f)) { // apply a color tint to the whole view - R_ResetViewRendering(); + R_ResetViewRendering2D(); R_Mesh_VertexPointer(r_screenvertex3f); R_Mesh_ColorPointer(NULL); GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -1926,6 +1971,8 @@ void R_RenderView(void) if (!r_refdef.entities/* || !r_refdef.worldmodel*/) return; //Host_Error ("R_RenderView: NULL worldmodel"); + R_Shadow_UpdateWorldLightSelection(); + CHECKGLERROR if (r_timereport_active) R_TimeReport("setup"); @@ -1934,10 +1981,8 @@ void R_RenderView(void) if (r_timereport_active) R_TimeReport("visibility"); - R_ResetViewRendering(); - GL_ScissorTest(true); - GL_DepthMask(true); - GL_DepthTest(true); + R_ResetViewRendering3D(); + R_ClearScreen(); if (r_timereport_active) R_TimeReport("clear"); @@ -1965,28 +2010,14 @@ extern void VM_AddPolygonsToMeshQueue (void); extern void R_DrawPortals (void); void R_RenderScene(void) { - DrawQ_Finish(); - // don't let sound skip if going slow if (r_refdef.extraupdate) S_ExtraUpdate (); - CHECKGLERROR - if (gl_support_fragment_shader) - { - qglUseProgramObjectARB(0);CHECKGLERROR - } - qglDepthFunc(GL_LEQUAL);CHECKGLERROR - qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR - qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR - - R_ResetViewRendering(); - R_SetupView(&r_view.matrix); + R_ResetViewRendering3D(); R_MeshQueue_BeginScene(); - R_Shadow_UpdateWorldLightSelection(); - R_SkyStartFrame(); Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.time) * 0.025 * r_waterscroll.value, sin(r_refdef.time * 0.8f) * 0.025 * r_waterscroll.value, 0); @@ -2031,6 +2062,8 @@ void R_RenderScene(void) { R_DrawModelShadows(); + R_ResetViewRendering3D(); + // don't let sound skip if going slow if (r_refdef.extraupdate) S_ExtraUpdate (); @@ -2096,13 +2129,7 @@ void R_RenderScene(void) if (r_refdef.extraupdate) S_ExtraUpdate (); - CHECKGLERROR - if (gl_support_fragment_shader) - { - qglUseProgramObjectARB(0);CHECKGLERROR - } - qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR - qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR + R_ResetViewRendering2D(); } /* @@ -2199,6 +2226,7 @@ void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight GL_DepthMask(true); } GL_DepthTest(!(ent->effects & EF_NODEPTHTEST)); + GL_CullFace((ent->flags & RENDER_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces R_Mesh_VertexPointer(nomodelvertex3f); if (r_refdef.fogenabled) { @@ -3678,12 +3706,8 @@ void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces) const int *elements; vec3_t v; CHECKGLERROR - GL_DepthTest(true); + GL_DepthTest(!r_showdisabledepthtest.integer); GL_DepthMask(true); - if (r_showdisabledepthtest.integer) - { - qglDepthFunc(GL_ALWAYS);CHECKGLERROR - } GL_BlendFunc(GL_ONE, GL_ZERO); R_Mesh_ColorPointer(NULL); R_Mesh_ResetTextureState(); @@ -3754,9 +3778,5 @@ void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces) } } rsurface_texture = NULL; - if (r_showdisabledepthtest.integer) - { - qglDepthFunc(GL_LEQUAL);CHECKGLERROR - } } } diff --git a/glquake.h b/glquake.h index 32b76f2d..ce930c4b 100644 --- a/glquake.h +++ b/glquake.h @@ -393,6 +393,17 @@ extern int gl_support_clamptoedge; #define GL_CLAMP_TO_EDGE 0x812F #endif +//GL_ATI_separate_stencil +extern int gl_support_separatestencil; +#ifndef GL_STENCIL_BACK_FUNC +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_FAIL 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#endif +extern void (GLAPIENTRY *qglStencilOpSeparate)(GLenum, GLenum, GLenum, GLenum); +extern void (GLAPIENTRY *qglStencilFuncSeparate)(GLenum, GLenum, GLint, GLuint); + //GL_EXT_stencil_two_side #define GL_STENCIL_TEST_TWO_SIDE_EXT 0x8910 #define GL_ACTIVE_STENCIL_FACE_EXT 0x8911 diff --git a/r_shadow.c b/r_shadow.c index 69ffabf3..33271660 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -146,6 +146,7 @@ typedef enum r_shadow_rendermode_e { R_SHADOW_RENDERMODE_NONE, R_SHADOW_RENDERMODE_STENCIL, + R_SHADOW_RENDERMODE_SEPARATESTENCIL, R_SHADOW_RENDERMODE_STENCILTWOSIDE, R_SHADOW_RENDERMODE_LIGHT_VERTEX, R_SHADOW_RENDERMODE_LIGHT_DOT3, @@ -219,6 +220,7 @@ cvar_t r_shadow_scissor = {0, "r_shadow_scissor", "1", "use scissor optimization cvar_t r_shadow_shadow_polygonfactor = {0, "r_shadow_shadow_polygonfactor", "0", "how much to enlarge shadow volume polygons when rendering (should be 0!)"}; cvar_t r_shadow_shadow_polygonoffset = {0, "r_shadow_shadow_polygonoffset", "1", "how much to push shadow volumes into the distance when rendering, to reduce chances of zfighting artifacts (should not be less than 0)"}; cvar_t r_shadow_texture3d = {0, "r_shadow_texture3d", "1", "use 3D voxel textures for spherical attenuation rather than cylindrical (does not affect r_glsl lighting)"}; +cvar_t gl_ext_separatestencil = {0, "gl_ext_separatetencil", "1", "make use of OpenGL 2.0 glStencilOpSeparate or GL_ATI_separate_stencil extension"}; cvar_t gl_ext_stenciltwoside = {0, "gl_ext_stenciltwoside", "1", "make use of GL_EXT_stenciltwoside extension (NVIDIA only)"}; cvar_t r_editlights = {0, "r_editlights", "0", "enables .rtlights file editing mode"}; cvar_t r_editlights_cursordistance = {0, "r_editlights_cursordistance", "1024", "maximum distance of cursor from eye"}; @@ -405,6 +407,7 @@ void R_Shadow_Init(void) Cvar_RegisterVariable(&r_shadow_shadow_polygonfactor); Cvar_RegisterVariable(&r_shadow_shadow_polygonoffset); Cvar_RegisterVariable(&r_shadow_texture3d); + Cvar_RegisterVariable(&gl_ext_separatestencil); Cvar_RegisterVariable(&gl_ext_stenciltwoside); if (gamemode == GAME_TENEBRAE) { @@ -853,6 +856,8 @@ void R_Shadow_ValidateCvars(void) { if (r_shadow_texture3d.integer && !gl_texture3d) Cvar_SetValueQuick(&r_shadow_texture3d, 0); + if (gl_ext_separatestencil.integer && !gl_support_separatestencil) + Cvar_SetValueQuick(&gl_ext_separatestencil, 0); if (gl_ext_stenciltwoside.integer && !gl_support_stenciltwoside) Cvar_SetValueQuick(&gl_ext_stenciltwoside, 0); } @@ -885,13 +890,16 @@ void R_Shadow_RenderMode_Begin(void) R_Mesh_ColorPointer(NULL); R_Mesh_ResetTextureState(); GL_BlendFunc(GL_ONE, GL_ZERO); + GL_DepthTest(true); GL_DepthMask(false); GL_Color(0, 0, 0, 1); 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) + if (gl_ext_separatestencil.integer) + r_shadow_shadowingrendermode = R_SHADOW_RENDERMODE_SEPARATESTENCIL; + else if (gl_ext_stenciltwoside.integer) r_shadow_shadowingrendermode = R_SHADOW_RENDERMODE_STENCILTWOSIDE; else r_shadow_shadowingrendermode = R_SHADOW_RENDERMODE_STENCIL; @@ -922,22 +930,36 @@ void R_Shadow_RenderMode_Reset(void) } R_Mesh_ColorPointer(NULL); R_Mesh_ResetTextureState(); + GL_DepthTest(true); + GL_DepthMask(false); + qglDepthFunc(GL_LEQUAL);CHECKGLERROR + qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR + qglDisable(GL_STENCIL_TEST);CHECKGLERROR + qglStencilMask(~0);CHECKGLERROR + qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR + qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR + GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces + GL_Color(1, 1, 1, 1); + GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1); + GL_BlendFunc(GL_ONE, GL_ZERO); } void R_Shadow_RenderMode_StencilShadowVolumes(void) { CHECKGLERROR R_Shadow_RenderMode_Reset(); - GL_Color(1, 1, 1, 1); GL_ColorMask(0, 0, 0, 0); - GL_BlendFunc(GL_ONE, GL_ZERO); - GL_DepthMask(false); qglPolygonOffset(r_refdef.shadowpolygonfactor, r_refdef.shadowpolygonoffset);CHECKGLERROR qglDepthFunc(GL_LESS);CHECKGLERROR 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) + if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SEPARATESTENCIL) + { + GL_CullFace(GL_NONE); + qglStencilOpSeparate(GL_BACK, GL_KEEP, GL_INCR, GL_KEEP);CHECKGLERROR // quake is backwards, this is front faces + qglStencilOpSeparate(GL_FRONT, GL_KEEP, GL_DECR, GL_KEEP);CHECKGLERROR // quake is backwards, this is back faces + } + else if (r_shadow_rendermode == R_SHADOW_RENDERMODE_STENCILTWOSIDE) { GL_CullFace(GL_NONE); qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR @@ -948,13 +970,6 @@ void R_Shadow_RenderMode_StencilShadowVolumes(void) qglStencilMask(~0);CHECKGLERROR qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);CHECKGLERROR } - else - { - 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 - } GL_Clear(GL_STENCIL_BUFFER_BIT); r_refdef.stats.lights_clears++; } @@ -964,32 +979,17 @@ void R_Shadow_RenderMode_Lighting(qboolean stenciltest, qboolean transparent) CHECKGLERROR R_Shadow_RenderMode_Reset(); GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); - GL_DepthMask(false); - 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); - if (transparent) - { - qglDepthFunc(GL_LEQUAL);CHECKGLERROR - } - else + if (!transparent) { qglDepthFunc(GL_EQUAL);CHECKGLERROR } if (stenciltest) { qglEnable(GL_STENCIL_TEST);CHECKGLERROR + // only draw light where this geometry was already rendered AND the + // stencil is 128 (values other than this mean shadow) + qglStencilFunc(GL_EQUAL, 128, ~0);CHECKGLERROR } - else - { - qglDisable(GL_STENCIL_TEST);CHECKGLERROR - } - qglStencilMask(~0);CHECKGLERROR - qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR - // only draw light where this geometry was already rendered AND the - // stencil is 128 (values other than this mean shadow) - qglStencilFunc(GL_EQUAL, 128, ~0);CHECKGLERROR r_shadow_rendermode = r_shadow_lightingrendermode; // do global setup needed for the chosen lighting mode if (r_shadow_rendermode == R_SHADOW_RENDERMODE_LIGHT_GLSL) @@ -1016,19 +1016,10 @@ void R_Shadow_RenderMode_VisibleShadowVolumes(void) CHECKGLERROR R_Shadow_RenderMode_Reset(); GL_BlendFunc(GL_ONE, GL_ONE); - GL_DepthMask(false); - qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR + GL_DepthTest(r_showshadowvolumes.integer < 2); 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); - if (r_showshadowvolumes.integer >= 2) - { - qglDepthFunc(GL_ALWAYS);CHECKGLERROR - } - else - { - qglDepthFunc(GL_GEQUAL);CHECKGLERROR - } - qglDisable(GL_STENCIL_TEST);CHECKGLERROR + qglPolygonOffset(r_refdef.shadowpolygonfactor, r_refdef.shadowpolygonoffset);CHECKGLERROR + GL_CullFace(GL_NONE); r_shadow_rendermode = R_SHADOW_RENDERMODE_VISIBLEVOLUMES; } @@ -1037,19 +1028,9 @@ void R_Shadow_RenderMode_VisibleLighting(qboolean stenciltest, qboolean transpar CHECKGLERROR R_Shadow_RenderMode_Reset(); GL_BlendFunc(GL_ONE, GL_ONE); - GL_DepthMask(false); - qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR + GL_DepthTest(r_showlighting.integer < 2); 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 (r_showshadowvolumes.integer >= 2) - { - qglDepthFunc(GL_ALWAYS);CHECKGLERROR - } - else if (transparent) - { - qglDepthFunc(GL_LEQUAL);CHECKGLERROR - } - else + if (!transparent) { qglDepthFunc(GL_EQUAL);CHECKGLERROR } @@ -1057,10 +1038,6 @@ void R_Shadow_RenderMode_VisibleLighting(qboolean stenciltest, qboolean transpar { qglEnable(GL_STENCIL_TEST);CHECKGLERROR } - else - { - qglDisable(GL_STENCIL_TEST);CHECKGLERROR - } r_shadow_rendermode = R_SHADOW_RENDERMODE_VISIBLELIGHTING; } @@ -1069,23 +1046,8 @@ void R_Shadow_RenderMode_End(void) CHECKGLERROR R_Shadow_RenderMode_Reset(); R_Shadow_RenderMode_ActiveLight(NULL); - GL_BlendFunc(GL_ONE, GL_ZERO); GL_DepthMask(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 - 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; } @@ -2535,7 +2497,9 @@ void R_DrawModelShadows(void) r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE; - if (gl_ext_stenciltwoside.integer) + if (gl_ext_separatestencil.integer) + r_shadow_shadowingrendermode = R_SHADOW_RENDERMODE_SEPARATESTENCIL; + else if (gl_ext_stenciltwoside.integer) r_shadow_shadowingrendermode = R_SHADOW_RENDERMODE_STENCILTWOSIDE; else r_shadow_shadowingrendermode = R_SHADOW_RENDERMODE_STENCIL; @@ -2593,11 +2557,10 @@ void R_DrawModelShadows(void) // apply the blend to the shadowed areas R_Mesh_Draw(0, 4, 2, polygonelements); - // restore perspective view - R_SetupView(&r_view.matrix); + // restoring the perspective view is done by R_RenderScene + //R_SetupView(&r_view.matrix); // restore other state to normal - GL_DepthTest(true); R_Shadow_RenderMode_End(); } diff --git a/r_shadow.h b/r_shadow.h index a3d3bc36..92e2fdb4 100644 --- a/r_shadow.h +++ b/r_shadow.h @@ -28,6 +28,7 @@ extern cvar_t r_shadow_shadow_polygonfactor; extern cvar_t r_shadow_shadow_polygonoffset; extern cvar_t r_shadow_singlepassvolumegeneration; extern cvar_t r_shadow_texture3d; +extern cvar_t gl_ext_separatestencil; extern cvar_t gl_ext_stenciltwoside; void R_Shadow_Init(void); diff --git a/vid_shared.c b/vid_shared.c index 6599d711..40730d2a 100644 --- a/vid_shared.c +++ b/vid_shared.c @@ -42,6 +42,8 @@ int gl_support_clamptoedge = false; // GL_EXT_texture_filter_anisotropic int gl_support_anisotropy = false; int gl_max_anisotropy = 1; +// OpenGL2.0 core glStencilOpSeparate, or GL_ATI_separate_stencil +int gl_support_separatestencil = false; // GL_EXT_stencil_two_side int gl_support_stenciltwoside = false; // GL_EXT_blend_minmax @@ -254,6 +256,8 @@ void (GLAPIENTRY *qglPointSize)(GLfloat size); void (GLAPIENTRY *qglBlendEquationEXT)(GLenum); +void (GLAPIENTRY *qglStencilOpSeparate)(GLenum, GLenum, GLenum, GLenum); +void (GLAPIENTRY *qglStencilFuncSeparate)(GLenum, GLenum, GLint, GLuint); void (GLAPIENTRY *qglActiveStencilFaceEXT)(GLenum); void (GLAPIENTRY *qglDeleteObjectARB)(GLhandleARB obj); @@ -519,6 +523,20 @@ static dllfunction_t texture3dextfuncs[] = {NULL, NULL} }; +static dllfunction_t atiseparatestencilfuncs[] = +{ + {"glStencilOpSeparateATI", (void **) &qglStencilOpSeparate}, + {"glStencilFuncSeparateATI", (void **) &qglStencilFuncSeparate}, + {NULL, NULL} +}; + +static dllfunction_t gl2separatestencilfuncs[] = +{ + {"glStencilOpSeparate", (void **) &qglStencilOpSeparate}, + {"glStencilFuncSeparate", (void **) &qglStencilFuncSeparate}, + {NULL, NULL} +}; + static dllfunction_t stenciltwosidefuncs[] = { {"glActiveStencilFaceEXT", (void **) &qglActiveStencilFaceEXT}, @@ -646,6 +664,7 @@ void VID_CheckExtensions(void) gl_support_clamptoedge = false; gl_support_anisotropy = false; gl_max_anisotropy = 1; + gl_support_separatestencil = false; gl_support_stenciltwoside = false; gl_support_ext_blend_minmax = false; gl_support_ext_blend_subtract = false; @@ -709,6 +728,9 @@ void VID_CheckExtensions(void) gl_support_ext_blend_minmax = GL_CheckExtension("GL_EXT_blend_minmax", blendequationfuncs, "-noblendminmax", false); gl_support_ext_blend_subtract = GL_CheckExtension("GL_EXT_blend_subtract", blendequationfuncs, "-noblendsubtract", false); +// COMMANDLINEOPTION: GL: -noseparatestencil disables use of OpenGL2.0 glStencilOpSeparate and GL_ATI_separate_stencil extensions (accelerates shadow rendering) + if (!(gl_support_separatestencil = GL_CheckExtension("glStencilOpSeparate", gl2separatestencilfuncs, "-noseparatestencil", false))) + gl_support_separatestencil = GL_CheckExtension("GL_ATI_separate_stencil", atiseparatestencilfuncs, "-noseparatestencil", false); // COMMANDLINEOPTION: GL: -nostenciltwoside disables GL_EXT_stencil_two_side (accelerates shadow rendering) gl_support_stenciltwoside = GL_CheckExtension("GL_EXT_stencil_two_side", stenciltwosidefuncs, "-nostenciltwoside", false); -- 2.39.2