From: havoc Date: Wed, 10 Mar 2004 07:14:24 +0000 (+0000) Subject: now supports GL_EXT_stencil_two_side extension (found on NV30/R300 class cards),... X-Git-Tag: xonotic-v0.1.0preview~6010 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=93301e7f1c63b5183b3b1c6b242ed2bb566f647b;p=xonotic%2Fdarkplaces.git now supports GL_EXT_stencil_two_side extension (found on NV30/R300 class cards), this halves the polycount thrown at the card for shadow volumes, which got me a 77% speed gain on my GFFX5200 git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@4000 d7cf8633-e32d-0410-b094-e92efae38249 --- diff --git a/glquake.h b/glquake.h index 3dabde6b..96762ea9 100644 --- a/glquake.h +++ b/glquake.h @@ -389,6 +389,11 @@ extern int gl_support_var; #define GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV 0x8533 extern int gl_support_var2; +//GL_EXT_stencil_two_side +#define GL_STENCIL_TEST_TWO_SIDE_EXT 0x8910 +#define GL_ACTIVE_STENCIL_FACE_EXT 0x8911 +extern void (GLAPIENTRY *qglActiveStencilFaceEXT)(GLenum); +extern int gl_support_stenciltwoside; extern void (GLAPIENTRY *qglScissor)(GLint x, GLint y, GLsizei width, GLsizei height); diff --git a/r_shadow.c b/r_shadow.c index 1e0352f1..9a660ed9 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -122,7 +122,7 @@ extern void R_Shadow_EditLights_Init(void); #define SHADOWSTAGE_NONE 0 #define SHADOWSTAGE_STENCIL 1 #define SHADOWSTAGE_LIGHT 2 -#define SHADOWSTAGE_ERASESTENCIL 3 +#define SHADOWSTAGE_STENCILTWOSIDE 3 int r_shadowstage = SHADOWSTAGE_NONE; int r_shadow_reloadlights = false; @@ -179,6 +179,7 @@ cvar_t r_shadow_dlightshadows = {CVAR_SAVE, "r_shadow_dlightshadows", "1"}; cvar_t r_shadow_showtris = {0, "r_shadow_showtris", "0"}; cvar_t r_shadow_staticworldlights = {0, "r_shadow_staticworldlights", "1"}; cvar_t r_shadow_cull = {0, "r_shadow_cull", "1"}; +cvar_t gl_ext_stenciltwoside = {0, "gl_ext_stenciltwoside", "1"}; int c_rt_lights, c_rt_clears, c_rt_scissored; int c_rt_shadowmeshes, c_rt_shadowtris, c_rt_lightmeshes, c_rt_lighttris; @@ -308,6 +309,7 @@ void R_Shadow_Init(void) Cvar_RegisterVariable(&r_shadow_showtris); Cvar_RegisterVariable(&r_shadow_staticworldlights); Cvar_RegisterVariable(&r_shadow_cull); + Cvar_RegisterVariable(&gl_ext_stenciltwoside); if (gamemode == GAME_TENEBRAE) { Cvar_SetValue("r_shadow_gloss", 2); @@ -719,6 +721,8 @@ void R_Shadow_Stage_Begin(void) if (r_shadow_texture3d.integer && !gl_texture3d) Cvar_SetValueQuick(&r_shadow_texture3d, 0); + if (gl_ext_stenciltwoside.integer && !gl_support_stenciltwoside) + Cvar_SetValueQuick(&gl_ext_stenciltwoside, 0); if (!r_shadow_attenuation2dtexture || (!r_shadow_attenuation3dtexture && r_shadow_texture3d.integer) @@ -778,9 +782,24 @@ void R_Shadow_Stage_ShadowVolumes(void) qglDepthFunc(GL_LESS); qglCullFace(GL_FRONT); // quake is backwards, this culls back faces qglEnable(GL_STENCIL_TEST); - qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - qglStencilFunc(GL_ALWAYS, 128, 0xFF); - r_shadowstage = SHADOWSTAGE_STENCIL; + qglStencilFunc(GL_ALWAYS, 128, ~0); + if (gl_ext_stenciltwoside.integer) + { + r_shadowstage = SHADOWSTAGE_STENCILTWOSIDE; + qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT); + qglActiveStencilFaceEXT(GL_FRONT); // quake is backwards, this is back faces + qglStencilMask(~0); + qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP); + qglActiveStencilFaceEXT(GL_BACK); // quake is backwards, this is front faces + qglStencilMask(~0); + qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP); + } + else + { + r_shadowstage = SHADOWSTAGE_STENCIL; + qglStencilMask(~0); + qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + } GL_Clear(GL_STENCIL_BUFFER_BIT); c_rt_clears++; // LordHavoc note: many shadow volumes reside entirely inside the world @@ -807,6 +826,9 @@ void R_Shadow_Stage_LightWithoutShadows(void) qglDepthFunc(GL_EQUAL); qglCullFace(GL_FRONT); // quake is backwards, this culls back faces qglDisable(GL_STENCIL_TEST); + if (gl_support_stenciltwoside) + qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT); + qglStencilMask(~0); qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); qglStencilFunc(GL_EQUAL, 128, 0xFF); r_shadowstage = SHADOWSTAGE_LIGHT; @@ -828,6 +850,9 @@ void R_Shadow_Stage_LightWithShadows(void) qglDepthFunc(GL_EQUAL); qglCullFace(GL_FRONT); // quake is backwards, this culls back faces qglEnable(GL_STENCIL_TEST); + if (gl_support_stenciltwoside) + qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT); + qglStencilMask(~0); qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // only draw light where this geometry was already rendered AND the // stencil is 128 (values other than this mean shadow) @@ -853,6 +878,9 @@ void R_Shadow_Stage_End(void) qglCullFace(GL_FRONT); // quake is backwards, this culls back faces qglDisable(GL_STENCIL_TEST); qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + if (gl_support_stenciltwoside) + qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT); + qglStencilMask(~0); qglStencilFunc(GL_ALWAYS, 128, 0xFF); r_shadowstage = SHADOWSTAGE_NONE; } diff --git a/todo b/todo index e910364f..c7b69246 100644 --- a/todo +++ b/todo @@ -45,7 +45,7 @@ -n darkplaces: write a readme (Antti) -n dpmod: make grapple off-hand (joe hill) -n darkplaces: add DP_SV_ROTATINGBMODEL extension to explain that MOVETYPE_PUSH/SOLID_BSP support rotation in darkplaces and a demonstration of how to use it without qc modifications (Uffe, Supajoe) -0 darkplaces: add Draw2D function to model struct to make it easy to draw models without an entity (Tomaz) +3 darkplaces: add Draw2D function to model struct to make it easy to draw models without an entity (Tomaz) 0 darkplaces: add GL_EXT_stencil_two_side support to shadow rendering (fuh) 0 darkplaces: add Mem_AllocNoClear function, and use it where possible, if developer is on it should clear with random garbage 0 darkplaces: add PF_tokenizeseparator function and DP_QC_TOKENIZESEPARATOR extension (Electro) diff --git a/vid_shared.c b/vid_shared.c index 5b5d40c1..e633c50a 100644 --- a/vid_shared.c +++ b/vid_shared.c @@ -40,6 +40,8 @@ int gl_support_var2 = false; int gl_support_anisotropy = false; // GL_NV_texture_shader int gl_textureshader = false; +// GL_EXT_stencil_two_side +int gl_support_stenciltwoside = false; // LordHavoc: if window is hidden, don't update screen int vid_hidden = true; @@ -231,6 +233,8 @@ void (GLAPIENTRY *qglScissor)(GLint x, GLint y, GLsizei width, GLsizei height); void (GLAPIENTRY *qglPolygonOffset)(GLfloat factor, GLfloat units); +void (GLAPIENTRY *qglActiveStencilFaceEXT)(GLenum); + int GL_CheckExtension(const char *name, const dllfunction_t *funcs, const char *disableparm, int silent) { int failed = false; @@ -415,6 +419,12 @@ static dllfunction_t wglvarfuncs[] = {NULL, NULL} }; +static dllfunction_t stenciltwosidefuncs[] = +{ + {"glActiveStencilFaceEXT", (void **) &qglActiveStencilFaceEXT}, + {NULL, NULL} +}; + void VID_CheckExtensions(void) { @@ -426,6 +436,7 @@ void VID_CheckExtensions(void) gl_support_clamptoedge = false; gl_support_var = false; gl_support_var2 = false; + gl_support_stenciltwoside = false; if (!GL_CheckExtension("OpenGL 1.1.0", opengl110funcs, NULL, false)) Sys_Error("OpenGL 1.1.0 functions not found\n"); @@ -465,6 +476,8 @@ void VID_CheckExtensions(void) gl_textureshader = GL_CheckExtension("GL_NV_texture_shader", NULL, "-notextureshader", false); + gl_support_stenciltwoside = GL_CheckExtension("GL_EXT_stencil_two_side", stenciltwosidefuncs, "-nostenciltwoside", false); + // we don't care if it's an extension or not, they are identical functions, so keep it simple in the rendering code if (qglDrawRangeElements == NULL) qglDrawRangeElements = qglDrawRangeElementsEXT;