Skip to content
Permalink
Browse files

Merge pull request #1024 from SomaZ/OpenJK-Stencil-Optimization

Draw stencil shadows in one drawcall when possible
  • Loading branch information...
xycaleth committed Nov 7, 2019
2 parents 4881be7 + d00df39 commit 146189a6285dcb81ccacea59cf964ebe47c4cf56
@@ -243,6 +243,8 @@ typedef struct glconfig_s {

int displayFrequency;

qboolean doStencilShadowsInOneDrawcall;

// synonymous with "does rendering consume the entire screen?", therefore
// a Voodoo or Voodoo2 will have this set to TRUE, as will a Win32 ICD that
// used CDS.
@@ -386,6 +386,8 @@ along with this program; if not, see <http://www.gnu.org/licenses/>.
#define qglVertexPointer glVertexPointer
#define qglViewport glViewport

extern PFNGLSTENCILOPSEPARATEPROC qglStencilOpSeparate;

extern PFNGLACTIVETEXTUREARBPROC qglActiveTextureARB;
extern PFNGLCLIENTACTIVETEXTUREARBPROC qglClientActiveTextureARB;
extern PFNGLMULTITEXCOORD2FARBPROC qglMultiTexCoord2fARB;
@@ -185,6 +185,7 @@ cvar_t *com_buildScript;
cvar_t *r_environmentMapping;
cvar_t *r_screenshotJpegQuality;

PFNGLSTENCILOPSEPARATEPROC qglStencilOpSeparate;

PFNGLACTIVETEXTUREARBPROC qglActiveTextureARB;
PFNGLCLIENTACTIVETEXTUREARBPROC qglClientActiveTextureARB;
@@ -669,6 +670,12 @@ static void GLimp_InitExtensions( void )
g_bDynamicGlowSupported = false;
ri.Cvar_Set( "r_DynamicGlow","0" );
}

qglStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC)ri.GL_GetProcAddress("glStencilOpSeparate");
if (qglStencilOpSeparate)
{
glConfig.doStencilShadowsInOneDrawcall = qtrue;
}
}

/*
@@ -350,15 +350,27 @@ void RB_DoShadowTessEnd( vec3_t lightPos )
qglDepthFunc(GL_LESS);

//now using the Carmack Reverse<tm> -rww
GL_Cull(CT_FRONT_SIDED);
qglStencilOp( GL_KEEP, GL_INCR, GL_KEEP );
if (glConfig.doStencilShadowsInOneDrawcall)
{
GL_Cull(CT_TWO_SIDED);
qglStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INCR_WRAP, GL_KEEP);
qglStencilOpSeparate(GL_BACK, GL_KEEP, GL_DECR_WRAP, GL_KEEP);

R_RenderShadowEdges();
R_RenderShadowEdges();
qglDisable(GL_STENCIL_TEST);
}
else
{
GL_Cull(CT_FRONT_SIDED);
qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);

GL_Cull(CT_BACK_SIDED);
qglStencilOp( GL_KEEP, GL_DECR, GL_KEEP );
R_RenderShadowEdges();

GL_Cull(CT_BACK_SIDED);
qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);

R_RenderShadowEdges();
R_RenderShadowEdges();
}

qglDepthFunc(GL_LEQUAL);
#else
@@ -392,6 +392,8 @@ along with this program; if not, see <http://www.gnu.org/licenses/>.
#define qglVertexPointer glVertexPointer
#define qglViewport glViewport

extern PFNGLSTENCILOPSEPARATEPROC qglStencilOpSeparate;

extern PFNGLACTIVETEXTUREARBPROC qglActiveTextureARB;
extern PFNGLCLIENTACTIVETEXTUREARBPROC qglClientActiveTextureARB;
extern PFNGLMULTITEXCOORD2FARBPROC qglMultiTexCoord2fARB;
@@ -216,6 +216,8 @@ cvar_t *se_language;
cvar_t *r_aviMotionJpegQuality;
cvar_t *r_screenshotJpegQuality;

PFNGLSTENCILOPSEPARATEPROC qglStencilOpSeparate;

PFNGLACTIVETEXTUREARBPROC qglActiveTextureARB;
PFNGLCLIENTACTIVETEXTUREARBPROC qglClientActiveTextureARB;
PFNGLMULTITEXCOORD2FARBPROC qglMultiTexCoord2fARB;
@@ -725,6 +727,12 @@ static void GLimp_InitExtensions( void )
g_bDynamicGlowSupported = false;
ri.Cvar_Set( "r_DynamicGlow","0" );
}

qglStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC)ri.GL_GetProcAddress("glStencilOpSeparate");
if ( qglStencilOpSeparate )
{
glConfigExt.doStencilShadowsInOneDrawcall = qtrue;
}
}

// Truncates the GL extensions string by only allowing up to 'maxExtensions' extensions in the string.
@@ -1063,6 +1063,7 @@ struct glconfigExt_t
glconfig_t *glConfig;

qboolean doGammaCorrectionWithShaders;
qboolean doStencilShadowsInOneDrawcall;
const char *originalExtensionString;
};

@@ -350,15 +350,27 @@ void RB_DoShadowTessEnd( vec3_t lightPos )
qglDepthFunc(GL_LESS);

//now using the Carmack Reverse<tm> -rww
GL_Cull(CT_FRONT_SIDED);
qglStencilOp( GL_KEEP, GL_INCR, GL_KEEP );
if ( glConfigExt.doStencilShadowsInOneDrawcall )
{
GL_Cull(CT_TWO_SIDED);
qglStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INCR_WRAP, GL_KEEP);
qglStencilOpSeparate(GL_BACK, GL_KEEP, GL_DECR_WRAP, GL_KEEP);

R_RenderShadowEdges();
qglDisable(GL_STENCIL_TEST);
}
else
{
GL_Cull(CT_FRONT_SIDED);
qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);

R_RenderShadowEdges();
R_RenderShadowEdges();

GL_Cull(CT_BACK_SIDED);
qglStencilOp( GL_KEEP, GL_DECR, GL_KEEP );
GL_Cull(CT_BACK_SIDED);
qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);

R_RenderShadowEdges();
R_RenderShadowEdges();
}

qglDepthFunc(GL_LEQUAL);
#else
@@ -388,7 +400,7 @@ void RB_DoShadowTessEnd( vec3_t lightPos )

// reenable writing to the color buffer
qglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );

#ifdef _DEBUG_STENCIL_SHADOWS
qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
#endif

1 comment on commit 146189a

@tomkidd

This comment has been minimized.

Copy link

tomkidd commented on 146189a Nov 16, 2019

FYI, built this for the first time from scratch on macOS and I couldn't get it to compile until I added this to code/rd-vanilla/glext.h and codemp/rd-vanilla/glext.h as line 5950:

typedef void (APIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);

Please sign in to comment.
You can’t perform that action at this time.