From b6ee99c1ec92872b535c07cef78cf38a31584021 Mon Sep 17 00:00:00 2001 From: eihrul Date: Thu, 1 Oct 2009 05:43:23 +0000 Subject: [PATCH] automagically select best shadowmapping filter mode depending on hardware git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@9269 d7cf8633-e32d-0410-b094-e92efae38249 --- gl_rmain.c | 29 +++++++------- gl_textures.c | 17 +++++---- glquake.h | 22 ++++++++--- r_shadow.c | 103 +++++++++++++++++++++++++++++++++++++++++--------- vid_shared.c | 18 +++++++++ 5 files changed, 143 insertions(+), 46 deletions(-) diff --git a/gl_rmain.c b/gl_rmain.c index 8375090e..a9e5b783 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -447,6 +447,9 @@ static void R_BuildFogTexture(void) static const char *builtinshaderstring = "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n" "// written by Forest 'LordHavoc' Hale\n" +"\n" +"// enable various extensions depending on permutation:\n" +"\n" "#ifdef USESHADOWMAPRECT\n" "# extension GL_ARB_texture_rectangle : enable\n" "#endif\n" @@ -471,6 +474,10 @@ static const char *builtinshaderstring = "# extension GL_EXT_gpu_shader4 : enable\n" "#endif\n" "\n" +"#ifdef USESHADOWSAMPLER\n" +"# extension GL_ARB_shadow : enable\n" +"#endif\n" +"\n" "// common definitions between vertex shader and fragment shader:\n" "\n" "//#ifdef __GLSL_CG_DATA_TYPES\n" @@ -1995,8 +2002,9 @@ extern qboolean r_shadow_usingshadowmapcube; extern qboolean r_shadow_usingshadowmap2d; extern float r_shadow_shadowmap_texturescale[4]; extern float r_shadow_shadowmap_parameters[4]; -extern int r_shadow_shadowmapvsdct; -extern int r_shadow_shadowmapfilter; +extern qboolean r_shadow_shadowmapvsdct; +extern qboolean r_shadow_shadowmapsampler; +extern int r_shadow_shadowmappcf; void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass) { // select a permutation of the lighting shader appropriate to this @@ -2047,21 +2055,12 @@ void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, f else if(r_shadow_shadowmapvsdct) permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT; - switch (r_shadow_shadowmapfilter) - { - case 1: + if (r_shadow_shadowmapsampler) permutation |= SHADERPERMUTATION_SHADOWSAMPLER; - break; - case 2: - permutation |= SHADERPERMUTATION_SHADOWSAMPLER | SHADERPERMUTATION_SHADOWMAPPCF; - break; - case 3: - permutation |= SHADERPERMUTATION_SHADOWMAPPCF; - break; - case 4: + if (r_shadow_shadowmappcf > 1) permutation |= SHADERPERMUTATION_SHADOWMAPPCF2; - break; - } + else if (r_shadow_shadowmappcf) + permutation |= SHADERPERMUTATION_SHADOWMAPPCF; } } else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) diff --git a/gl_textures.c b/gl_textures.c index 0a3f2cb1..c3cbcf3d 100644 --- a/gl_textures.c +++ b/gl_textures.c @@ -785,15 +785,18 @@ static void GL_SetupTextureParameters(int flags, textype_t textype, int texturet if (textype == TEXTYPE_SHADOWMAP) { - if (flags & TEXF_COMPARE) + if (gl_support_arb_shadow) { - qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);CHECKGLERROR - } - else - { - qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);CHECKGLERROR + if (flags & TEXF_COMPARE) + { + qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);CHECKGLERROR + } + else + { + qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);CHECKGLERROR + } + qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);CHECKGLERROR } - qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);CHECKGLERROR qglTexParameteri(textureenum, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);CHECKGLERROR } diff --git a/glquake.h b/glquake.h index fb7a8335..301b4660 100644 --- a/glquake.h +++ b/glquake.h @@ -135,11 +135,6 @@ typedef ptrdiff_t GLsizeiptrARB; #define GL_LINE 0x1B01 #define GL_FILL 0x1B02 -extern int gl_support_anisotropy; -extern int gl_max_anisotropy; -#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE -#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF - #define GL_ADD 0x0104 #define GL_DECAL 0x2101 #define GL_MODULATE 0x2100 @@ -268,8 +263,16 @@ extern int gl_max_anisotropy; #endif +//GL_EXT_texture_filter_anisotropic +extern int gl_support_anisotropy; +extern int gl_max_anisotropy; +#ifndef GL_TEXTURE_MAX_ANISOTROPY_EXT +#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF +#endif + // GL_ARB_depth_texture -#ifndef GL_DEPTH_COMPOENNT32_ARB +#ifndef GL_DEPTH_COMPONENT32_ARB #define GL_DEPTH_COMPONENT16_ARB 0x81A5 #define GL_DEPTH_COMPONENT24_ARB 0x81A6 #define GL_DEPTH_COMPONENT32_ARB 0x81A7 @@ -278,6 +281,7 @@ extern int gl_max_anisotropy; #endif // GL_ARB_shadow +extern int gl_support_arb_shadow; #ifndef GL_TEXTURE_COMPARE_MODE_ARB #define GL_TEXTURE_COMPARE_MODE_ARB 0x884C #define GL_TEXTURE_COMPARE_FUNC_ARB 0x884D @@ -953,6 +957,12 @@ extern void (GLAPIENTRY *qglGetQueryObjectuivARB)(GLuint qid, GLenum pname, GLui #define GL_LUMINANCE_ALPHA 0x190A #define GL_LUMINANCE16_ALPHA16 0x8048 +//GL_AMD_texture_texture4 +extern int gl_support_amd_texture_texture4; + +//GL_ARB_texture_gather +extern int gl_support_arb_texture_gather; + #define DEBUGGL #ifdef DEBUGGL diff --git a/r_shadow.c b/r_shadow.c index fd8830c2..27eeaa41 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -179,9 +179,12 @@ GLuint r_shadow_fborectangle; GLuint r_shadow_fbocubeside[R_SHADOW_SHADOWMAP_NUMCUBEMAPS][6]; GLuint r_shadow_fbo2d; int r_shadow_shadowmode; -int r_shadow_shadowmapvsdct; +int r_shadow_shadowmapfilterquality; +int r_shadow_shadowmaptexturetype; int r_shadow_shadowmapmaxsize; -int r_shadow_shadowmapfilter; +qboolean r_shadow_shadowmapvsdct; +qboolean r_shadow_shadowmapsampler; +int r_shadow_shadowmappcf; int r_shadow_shadowmapborder; int r_shadow_lightscissor[4]; @@ -263,7 +266,8 @@ cvar_t r_shadow_realtime_world_compilesvbsp = {0, "r_shadow_realtime_world_compi cvar_t r_shadow_realtime_world_compileportalculling = {0, "r_shadow_realtime_world_compileportalculling", "1", "enables portal-based culling optimization during compilation"}; cvar_t r_shadow_scissor = {0, "r_shadow_scissor", "1", "use scissor optimization of light rendering (restricts rendering to the portion of the screen affected by the light)"}; cvar_t r_shadow_shadowmapping = {CVAR_SAVE, "r_shadow_shadowmapping", "0", "enables use of shadowmapping (depth texture sampling) instead of stencil shadow volumes, requires gl_fbo 1"}; -cvar_t r_shadow_shadowmapping_filterquality = {CVAR_SAVE, "r_shadow_shadowmapping_filterquality", "0", "shadowmap filter modes: 0 = no filtering, 1 = bilinear, 2 = bilinear 2x2 blur (fast), 3 = 3x3 blur (moderate), 4 = 4x4 blur (slow)"}; +cvar_t r_shadow_shadowmapping_texturetype = {CVAR_SAVE, "r_shadow_shadowmapping_texturetype", "0", "shadowmap texture types: 0 = auto-select, 1 = 2D, 2 = rectangle, 3 = cubemap"}; +cvar_t r_shadow_shadowmapping_filterquality = {CVAR_SAVE, "r_shadow_shadowmapping_filterquality", "-1", "shadowmap filter modes: -1 = auto-select, 0 = no filtering, 1 = bilinear, 2 = bilinear 2x2 blur (fast), 3 = 3x3 blur (moderate), 4 = 4x4 blur (slow)"}; cvar_t r_shadow_shadowmapping_vsdct = {CVAR_SAVE, "r_shadow_shadowmapping_vsdct", "1", "enables use of virtual shadow depth cube texture"}; cvar_t r_shadow_shadowmapping_minsize = {CVAR_SAVE, "r_shadow_shadowmapping_minsize", "32", "shadowmap size limit"}; cvar_t r_shadow_shadowmapping_maxsize = {CVAR_SAVE, "r_shadow_shadowmapping_maxsize", "512", "shadowmap size limit"}; @@ -338,18 +342,71 @@ cachepic_t *r_editlights_sprcubemaplight; cachepic_t *r_editlights_sprcubemapnoshadowlight; cachepic_t *r_editlights_sprselection; -void R_Shadow_FreeShadowMaps(void) +void R_Shadow_SetShadowMode(void) { - int i; - r_shadow_shadowmapmaxsize = bound(1, r_shadow_shadowmapping_maxsize.integer, 2048); - r_shadow_shadowmode = r_shadow_shadowmapping.integer; - r_shadow_shadowmapvsdct = r_shadow_shadowmapping_vsdct.integer; - r_shadow_shadowmapfilter = r_shadow_shadowmapping_filterquality.integer; + r_shadow_shadowmapvsdct = r_shadow_shadowmapping_vsdct.integer != 0; + r_shadow_shadowmapfilterquality = r_shadow_shadowmapping_filterquality.integer; + r_shadow_shadowmaptexturetype = r_shadow_shadowmapping_texturetype.integer; r_shadow_shadowmapborder = bound(0, r_shadow_shadowmapping_bordersize.integer, 16); r_shadow_shadowmaplod = -1; + r_shadow_shadowmapsampler = false; + r_shadow_shadowmappcf = 0; + r_shadow_shadowmode = 0; + if(r_shadow_shadowmapping.integer) + { + if(r_shadow_shadowmapfilterquality < 0) + { + if(strstr(gl_vendor, "NVIDIA")) + { + r_shadow_shadowmapsampler = gl_support_arb_shadow; + r_shadow_shadowmappcf = 1; + } + else if(gl_support_amd_texture_texture4 || gl_support_arb_texture_gather) + r_shadow_shadowmappcf = 1; + else if(strstr(gl_vendor, "ATI")) + r_shadow_shadowmappcf = 1; + else + r_shadow_shadowmapsampler = gl_support_arb_shadow; + } + else + { + switch (r_shadow_shadowmapfilterquality) + { + case 1: + r_shadow_shadowmapsampler = gl_support_arb_shadow; + break; + case 2: + r_shadow_shadowmapsampler = gl_support_arb_shadow; + r_shadow_shadowmappcf = 1; + break; + case 3: + r_shadow_shadowmappcf = 1; + break; + case 4: + r_shadow_shadowmappcf = 2; + break; + } + } + r_shadow_shadowmode = r_shadow_shadowmaptexturetype; + if(r_shadow_shadowmode <= 0) + { + if(!gl_texturerectangle || gl_support_arb_texture_non_power_of_two) + r_shadow_shadowmode = 1; + else if((gl_support_amd_texture_texture4 || gl_support_arb_texture_gather) && r_shadow_shadowmappcf && !r_shadow_shadowmapsampler) + r_shadow_shadowmode = 1; + else + r_shadow_shadowmode = 2; + } + } +} + +void R_Shadow_FreeShadowMaps(void) +{ + int i; + + R_Shadow_SetShadowMode(); - CHECKGLERROR if (r_shadow_fborectangle) qglDeleteFramebuffersEXT(1, &r_shadow_fborectangle); r_shadow_fborectangle = 0; @@ -401,8 +458,11 @@ void r_shadow_start(void) r_shadow_shadowmapmaxsize = 0; r_shadow_shadowmapsize = 0; r_shadow_shadowmaplod = 0; - r_shadow_shadowmapvsdct = 0; - r_shadow_shadowmapfilter = 0; + r_shadow_shadowmapfilterquality = 0; + r_shadow_shadowmaptexturetype = 0; + r_shadow_shadowmapvsdct = false; + r_shadow_shadowmapsampler = false; + r_shadow_shadowmappcf = 0; r_shadow_fborectangle = 0; r_shadow_fbo2d = 0; memset(r_shadow_fbocubeside, 0, sizeof(r_shadow_fbocubeside)); @@ -575,6 +635,7 @@ void R_Shadow_Init(void) Cvar_RegisterVariable(&r_shadow_scissor); Cvar_RegisterVariable(&r_shadow_shadowmapping); Cvar_RegisterVariable(&r_shadow_shadowmapping_vsdct); + Cvar_RegisterVariable(&r_shadow_shadowmapping_texturetype); Cvar_RegisterVariable(&r_shadow_shadowmapping_filterquality); Cvar_RegisterVariable(&r_shadow_shadowmapping_maxsize); Cvar_RegisterVariable(&r_shadow_shadowmapping_minsize); @@ -1497,7 +1558,8 @@ void R_Shadow_RenderMode_ShadowMap(int side, qboolean clear, int size) if (!r_shadow_shadowmap2dtexture) { #if 1 - r_shadow_shadowmap2dtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "shadowmap", maxsize*2, maxsize*4, r_shadow_shadowmapfilter == 1 || r_shadow_shadowmapfilter == 2); + int w = maxsize*2, h = gl_support_arb_texture_non_power_of_two ? maxsize*3 : maxsize*4; + r_shadow_shadowmap2dtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "shadowmap", w, h, r_shadow_shadowmapsampler); qglGenFramebuffersEXT(1, &r_shadow_fbo2d);CHECKGLERROR qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fbo2d);CHECKGLERROR qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, R_GetTexture(r_shadow_shadowmap2dtexture), 0);CHECKGLERROR @@ -1527,8 +1589,8 @@ void R_Shadow_RenderMode_ShadowMap(int side, qboolean clear, int size) R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapping_bordersize.integer, nearclip, farclip, NULL); r_shadow_shadowmap_texturescale[0] = 1.0f / R_TextureWidth(r_shadow_shadowmap2dtexture); r_shadow_shadowmap_texturescale[1] = 1.0f / R_TextureHeight(r_shadow_shadowmap2dtexture); - r_shadow_shadowmap_parameters[0] = r_shadow_shadowmapvsdct ? size / (float)maxsize : 0.5f * (size - r_shadow_shadowmapborder); - r_shadow_shadowmap_parameters[1] = r_shadow_shadowmapvsdct ? 0.75f * size / (float)maxsize : size; + r_shadow_shadowmap_parameters[0] = r_shadow_shadowmapvsdct ? 2*size * r_shadow_shadowmap_texturescale[0] : 0.5f * (size - r_shadow_shadowmapborder); + r_shadow_shadowmap_parameters[1] = r_shadow_shadowmapvsdct ? 3*size * r_shadow_shadowmap_texturescale[1] : size; r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAP2D; } else if (r_shadow_shadowmode == 2) @@ -1539,7 +1601,7 @@ void R_Shadow_RenderMode_ShadowMap(int side, qboolean clear, int size) if (!r_shadow_shadowmaprectangletexture) { #if 1 - r_shadow_shadowmaprectangletexture = R_LoadTextureShadowMapRectangle(r_shadow_texturepool, "shadowmap", maxsize*2, maxsize*3, r_shadow_shadowmapfilter == 1 || r_shadow_shadowmapfilter == 2); + r_shadow_shadowmaprectangletexture = R_LoadTextureShadowMapRectangle(r_shadow_texturepool, "shadowmap", maxsize*2, maxsize*3, r_shadow_shadowmapsampler); qglGenFramebuffersEXT(1, &r_shadow_fborectangle);CHECKGLERROR qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fborectangle);CHECKGLERROR qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, R_GetTexture(r_shadow_shadowmaprectangletexture), 0);CHECKGLERROR @@ -1579,7 +1641,7 @@ void R_Shadow_RenderMode_ShadowMap(int side, qboolean clear, int size) if (!r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]) { #if 1 - r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod] = R_LoadTextureShadowMapCube(r_shadow_texturepool, "shadowmapcube", bound(1, maxsize >> r_shadow_shadowmaplod, 2048), r_shadow_shadowmapfilter == 1 || r_shadow_shadowmapfilter == 2); + r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod] = R_LoadTextureShadowMapCube(r_shadow_texturepool, "shadowmapcube", bound(1, maxsize >> r_shadow_shadowmaplod, 2048), r_shadow_shadowmapsampler); qglGenFramebuffersEXT(6, r_shadow_fbocubeside[r_shadow_shadowmaplod]);CHECKGLERROR for (i = 0;i < 6;i++) { @@ -3821,7 +3883,12 @@ void R_ShadowVolumeLighting(qboolean visible) dlight_t *light; size_t range; - if (r_shadow_shadowmapmaxsize != bound(1, r_shadow_shadowmapping_maxsize.integer, 2048) || r_shadow_shadowmode != r_shadow_shadowmapping.integer || r_shadow_shadowmapvsdct != r_shadow_shadowmapping_vsdct.integer || r_shadow_shadowmapfilter != r_shadow_shadowmapping_filterquality.integer || r_shadow_shadowmapborder != bound(0, r_shadow_shadowmapping_bordersize.integer, 16)) + if (r_shadow_shadowmapmaxsize != bound(1, r_shadow_shadowmapping_maxsize.integer, 2048) || + (r_shadow_shadowmode != 0) != (r_shadow_shadowmapping.integer != 0) || + r_shadow_shadowmapvsdct != (r_shadow_shadowmapping_vsdct.integer != 0) || + r_shadow_shadowmaptexturetype != r_shadow_shadowmapping_texturetype.integer || + r_shadow_shadowmapfilterquality != r_shadow_shadowmapping_filterquality.integer || + r_shadow_shadowmapborder != bound(0, r_shadow_shadowmapping_bordersize.integer, 16)) R_Shadow_FreeShadowMaps(); if (r_editlights.integer) diff --git a/vid_shared.c b/vid_shared.c index 68428f3e..978a6d3d 100644 --- a/vid_shared.c +++ b/vid_shared.c @@ -43,6 +43,8 @@ int gl_support_arb_texture_non_power_of_two = false; int gl_dot3arb = false; // GL_ARB_depth_texture int gl_depthtexture = false; +// GL_ARB_shadow +int gl_support_arb_shadow = false; // GL_SGIS_texture_edge_clamp int gl_support_clamptoedge = false; // GL_EXT_texture_filter_anisotropic @@ -72,6 +74,10 @@ int gl_support_ext_framebuffer_object = false; int gl_support_texture_compression = false; //GL_ARB_occlusion_query int gl_support_arb_occlusion_query = false; +//GL_AMD_texture_texture4 +int gl_support_amd_texture_texture4 = false; +//GL_ARB_texture_gather +int gl_support_arb_texture_gather = false; // LordHavoc: if window is hidden, don't update screen qboolean vid_hidden = true; @@ -832,6 +838,7 @@ void VID_CheckExtensions(void) gl_support_arb_texture_non_power_of_two = false; gl_dot3arb = false; gl_depthtexture = false; + gl_support_arb_shadow = false; gl_support_clamptoedge = false; gl_support_anisotropy = false; gl_max_anisotropy = 1; @@ -847,6 +854,8 @@ void VID_CheckExtensions(void) gl_support_ext_framebuffer_object = false; gl_support_texture_compression = false; gl_support_arb_occlusion_query = false; + gl_support_amd_texture_texture4 = false; + gl_support_arb_texture_gather = false; if (!GL_CheckExtension("1.1", opengl110funcs, NULL, false)) Sys_Error("OpenGL 1.1.0 functions not found"); @@ -887,7 +896,11 @@ void VID_CheckExtensions(void) // COMMANDLINEOPTION: GL: -norectangle disables GL_ARB_texture_rectangle (required for bumpmapping) if ((gl_texturerectangle = GL_CheckExtension("GL_ARB_texture_rectangle", NULL, "-norectangle", false))) qglGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &gl_max_rectangle_texture_size); +// COMMANDLINEOPTION: GL: -nodepthtexture disables use of GL_ARB_depth_texture (required for shadowmapping) gl_depthtexture = GL_CheckExtension("GL_ARB_depth_texture", NULL, "-nodepthtexture", false); +// COMMANDLINEOPTION: GL: -noshadow disables use of GL_ARB_shadow (required for hardware shadowmap filtering) + gl_support_arb_shadow = GL_CheckExtension("GL_ARB_shadow", NULL, "-noshadow", false); + // COMMANDLINEOPTION: GL: -notexturecompression disables GL_ARB_texture_compression (which saves video memory if it is supported, but can also degrade image quality, see gl_texturecompression cvar documentation for more information) gl_support_texture_compression = GL_CheckExtension("GL_ARB_texture_compression", texturecompressionfuncs, "-notexturecompression", false); // COMMANDLINEOPTION: GL: -nocva disables GL_EXT_compiled_vertex_array (renders faster) @@ -942,6 +955,11 @@ void VID_CheckExtensions(void) // COMMANDLINEOPTION: GL: -noocclusionquery disables GL_ARB_occlusion_query (which allows coronas to fade according to visibility, and potentially used for rendering optimizations) gl_support_arb_occlusion_query = GL_CheckExtension("GL_ARB_occlusion_query", occlusionqueryfuncs, "-noocclusionquery", false); + +// COMMANDLINEOPTION: GL: -notexture4 disables GL_AMD_texture_texture4 (which provides fetch4 sampling) + gl_support_amd_texture_texture4 = GL_CheckExtension("GL_AMD_texture_texture4", NULL, "-notexture4", false); +// COMMANDLINEOPTION: GL: -notexturegather disables GL_ARB_texture_gather (which provides fetch4 sampling) + gl_support_arb_texture_gather = GL_CheckExtension("GL_ARB_texture_gather", NULL, "-notexturegather", false); } void Force_CenterView_f (void) -- 2.39.2