reorganized view rendering setup code a bit to reduce potential for state bugs (more...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sun, 21 Jan 2007 14:21:53 +0000 (14:21 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sun, 21 Jan 2007 14:21:53 +0000 (14:21 +0000)
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
glquake.h
r_shadow.c
r_shadow.h
vid_shared.c

index 76ab227..af26ca6 100644 (file)
@@ -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
-               }
        }
 }
index 32b76f2..ce930c4 100644 (file)
--- 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
index 69ffabf..3327166 100644 (file)
@@ -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();
 }
 
index a3d3bc3..92e2fdb 100644 (file)
@@ -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);
index 6599d71..40730d2 100644 (file)
@@ -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);