diff --git a/base/renderprogs/interactionSM.pixel b/base/renderprogs/interactionSM.pixel index 8d8e5069d5..c8c1d5b755 100644 --- a/base/renderprogs/interactionSM.pixel +++ b/base/renderprogs/interactionSM.pixel @@ -185,13 +185,13 @@ void main( PS_IN fragment, out PS_OUT result ) shadowTexcoord.z = dot4( modelPosition, shadowMatrixZ ); shadowTexcoord.w = dot4( modelPosition, shadowMatrixW ); - //float bias = 0.001 * tan( acos( ldotN ) ); - //bias = clamp( bias, 0, 0.001 ); + //float bias = 0.005 * tan( acos( ldotN ) ); + //bias = clamp( bias, 0, 0.01 ); float bias = 0.001; shadowTexcoord.xyz /= shadowTexcoord.w; - shadowTexcoord.z = shadowTexcoord.z * 0.9991; - //shadowTexcoord.z = shadowTexcoord.z - bias; + //shadowTexcoord.z = shadowTexcoord.z * 0.9991; + shadowTexcoord.z = shadowTexcoord.z - bias; shadowTexcoord.w = float(shadowIndex); #if 0 diff --git a/neo/renderer/Framebuffer.cpp b/neo/renderer/Framebuffer.cpp index d6e699326b..4c1df0d035 100644 --- a/neo/renderer/Framebuffer.cpp +++ b/neo/renderer/Framebuffer.cpp @@ -77,9 +77,14 @@ void Framebuffer::Init() int width, height; width = height = r_shadowMapImageSize.GetInteger(); - globalFramebuffers.shadowFBO = new Framebuffer( "_shadowMap" , width, height ); - globalFramebuffers.shadowFBO->Bind(); - glDrawBuffers( 0, NULL ); + for( int i = 0; i < MAX_SHADOWMAP_RESOLUTIONS; i++ ) + { + width = height = shadowMapResolutions[i]; + + globalFramebuffers.shadowFBO[i] = new Framebuffer( "_shadowMap" , width, height ); + globalFramebuffers.shadowFBO[i]->Bind(); + glDrawBuffers( 0, NULL ); + } // globalFramebuffers.shadowFBO->AddColorBuffer( GL_RGBA8, 0 ); // globalFramebuffers.shadowFBO->AddDepthBuffer( GL_DEPTH_COMPONENT24 ); // globalFramebuffers.shadowFBO->Check(); diff --git a/neo/renderer/Framebuffer.h b/neo/renderer/Framebuffer.h index 337c45988d..e2f9a6810d 100644 --- a/neo/renderer/Framebuffer.h +++ b/neo/renderer/Framebuffer.h @@ -29,6 +29,13 @@ If you have questions concerning this license or the applicable additional terms #ifndef __FRAMEBUFFER_H__ #define __FRAMEBUFFER_H__ +static const int MAX_SHADOWMAP_RESOLUTIONS = 5; +#if 1 +static int shadowMapResolutions[MAX_SHADOWMAP_RESOLUTIONS] = { 2048, 1024, 512, 512, 256 }; +#else +static int shadowMapResolutions[MAX_SHADOWMAP_RESOLUTIONS] = { 1024, 1024, 1024, 1024, 1024 }; +#endif + class Framebuffer { public: @@ -82,7 +89,7 @@ class Framebuffer struct globalFramebuffers_t { - Framebuffer* shadowFBO; + Framebuffer* shadowFBO[MAX_SHADOWMAP_RESOLUTIONS]; }; extern globalFramebuffers_t globalFramebuffers; diff --git a/neo/renderer/Image.h b/neo/renderer/Image.h index 412c99fa5a..6a90561f48 100644 --- a/neo/renderer/Image.h +++ b/neo/renderer/Image.h @@ -337,7 +337,7 @@ class idImageManager idImage* fogImage; // increasing alpha is denser fog idImage* fogEnterImage; // adjust fogImage alpha based on terminator plane // RB begin - idImage* shadowImage; + idImage* shadowImage[5]; idImage* jitterImage1; // shadow jitter idImage* jitterImage4; idImage* jitterImage16; diff --git a/neo/renderer/Image_intrinsic.cpp b/neo/renderer/Image_intrinsic.cpp index ca712f6674..93a49cd911 100644 --- a/neo/renderer/Image_intrinsic.cpp +++ b/neo/renderer/Image_intrinsic.cpp @@ -451,9 +451,33 @@ void R_QuadraticImage( idImage* image ) } // RB begin -static void R_CreateShadowMapImage( idImage* image ) +static void R_CreateShadowMapImage_Res0( idImage* image ) { - int size = r_shadowMapImageSize.GetInteger(); + int size = shadowMapResolutions[0]; + image->GenerateShadowArray( size, size, TF_LINEAR, TR_CLAMP_TO_ZERO_ALPHA, TD_SHADOW_ARRAY ); +} + +static void R_CreateShadowMapImage_Res1( idImage* image ) +{ + int size = shadowMapResolutions[1]; + image->GenerateShadowArray( size, size, TF_LINEAR, TR_CLAMP_TO_ZERO_ALPHA, TD_SHADOW_ARRAY ); +} + +static void R_CreateShadowMapImage_Res2( idImage* image ) +{ + int size = shadowMapResolutions[2]; + image->GenerateShadowArray( size, size, TF_LINEAR, TR_CLAMP_TO_ZERO_ALPHA, TD_SHADOW_ARRAY ); +} + +static void R_CreateShadowMapImage_Res3( idImage* image ) +{ + int size = shadowMapResolutions[3]; + image->GenerateShadowArray( size, size, TF_LINEAR, TR_CLAMP_TO_ZERO_ALPHA, TD_SHADOW_ARRAY ); +} + +static void R_CreateShadowMapImage_Res4( idImage* image ) +{ + int size = shadowMapResolutions[4]; image->GenerateShadowArray( size, size, TF_LINEAR, TR_CLAMP_TO_ZERO_ALPHA, TD_SHADOW_ARRAY ); } @@ -562,7 +586,11 @@ void idImageManager::CreateIntrinsicImages() ImageFromFunction( "_quadratic", R_QuadraticImage ); // RB begin - shadowImage = ImageFromFunction( va( "_shadowMap%i_0", r_shadowMapImageSize.GetInteger() ), R_CreateShadowMapImage ); + shadowImage[0] = ImageFromFunction( va( "_shadowMapArray%i", shadowMapResolutions[0] ), R_CreateShadowMapImage_Res0 ); + shadowImage[1] = ImageFromFunction( va( "_shadowMapArray%i", shadowMapResolutions[1] ), R_CreateShadowMapImage_Res1 ); + shadowImage[2] = ImageFromFunction( va( "_shadowMapArray%i", shadowMapResolutions[2] ), R_CreateShadowMapImage_Res2 ); + shadowImage[3] = ImageFromFunction( va( "_shadowMapArray%i", shadowMapResolutions[3] ), R_CreateShadowMapImage_Res3 ); + shadowImage[4] = ImageFromFunction( va( "_shadowMapArray%i", shadowMapResolutions[4] ), R_CreateShadowMapImage_Res4 ); jitterImage1 = globalImages->ImageFromFunction( "_jitter1", R_CreateJitterImage1 ); jitterImage4 = globalImages->ImageFromFunction( "_jitter4", R_CreateJitterImage4 ); diff --git a/neo/renderer/RenderSystem_init.cpp b/neo/renderer/RenderSystem_init.cpp index b69925d3ba..39e8267e09 100644 --- a/neo/renderer/RenderSystem_init.cpp +++ b/neo/renderer/RenderSystem_init.cpp @@ -222,8 +222,11 @@ idCVar r_shadowMapBiasScale( "r_shadowMapBiasScale", "0.0001", CVAR_RENDERER | C idCVar r_shadowMapSamples( "r_shadowMapSamples", "16", CVAR_RENDERER | CVAR_INTEGER, "0, 1, 4, or 16" ); idCVar r_shadowMapSplits( "r_shadowMapSplits", "3", CVAR_RENDERER | CVAR_INTEGER, "number of splits for cascaded shadow mapping with parallel lights", 0, 4 ); idCVar r_shadowMapSplitWeight( "r_shadowMapSplitWeight", "0.9", CVAR_RENDERER | CVAR_FLOAT, "" ); -idCVar r_shadowMapLodScale( "r_shadowMapLodScale", "0.8", CVAR_RENDERER | CVAR_FLOAT, "" ); +idCVar r_shadowMapLodScale( "r_shadowMapLodScale", "1.4", CVAR_RENDERER | CVAR_FLOAT, "" ); idCVar r_shadowMapLodBias( "r_shadowMapLodBias", "0", CVAR_RENDERER | CVAR_INTEGER, "" ); +idCVar r_shadowMapPolygonFactor( "r_shadowMapPolygonFactor", "2", CVAR_RENDERER | CVAR_FLOAT, "polygonOffset factor for drawing shadow buffer" ); +idCVar r_shadowMapPolygonOffset( "r_shadowMapPolygonOffset", "3000", CVAR_RENDERER | CVAR_FLOAT, "polygonOffset units for drawing shadow buffer" ); +idCVar r_shadowMapOccluderFacing( "r_shadowMapOccluderFacing", "2", CVAR_RENDERER | CVAR_INTEGER, "0 = front faces, 1 = back faces, 2 = twosided" ); // RB end diff --git a/neo/renderer/tr_backend_draw.cpp b/neo/renderer/tr_backend_draw.cpp index 08d1316ea3..06bfa63973 100644 --- a/neo/renderer/tr_backend_draw.cpp +++ b/neo/renderer/tr_backend_draw.cpp @@ -1346,7 +1346,7 @@ static void RB_RenderInteractions( const drawSurf_t* surfList, const viewLight_t { // texture 5 will be the shadow maps array GL_SelectTexture( INTERACTION_TEXUNIT_SHADOWMAPS ); - globalImages->shadowImage->Bind(); + globalImages->shadowImage[vLight->shadowLOD]->Bind(); // texture 6 will be the jitter texture for soft shadowing GL_SelectTexture( INTERACTION_TEXUNIT_JITTER ); @@ -2237,18 +2237,28 @@ static void RB_ShadowMapPass( const drawSurf_t* drawSurfs, const viewLight_t* vL uint64 glState = 0; - //GL_PolygonOffset( r_shadowPolygonFactor.GetFloat(), -r_shadowPolygonOffset.GetFloat() ); - - // the actual stencil func will be set in the draw code, but we need to make sure it isn't // disabled here, and that the value will get reset for the interactions without looking // like a no-change-required - //GL_State( glState | GLS_POLYGON_OFFSET ); - - GL_State( GLS_DEFAULT ); + GL_State( glState | GLS_POLYGON_OFFSET ); - // Two Sided Stencil reduces two draw calls to one for slightly faster shadows - GL_Cull( CT_TWO_SIDED ); + switch( r_shadowMapOccluderFacing.GetInteger() ) + { + case 0: + GL_Cull( CT_FRONT_SIDED ); + GL_PolygonOffset( r_shadowMapPolygonFactor.GetFloat(), r_shadowMapPolygonOffset.GetFloat() ); + break; + + case 1: + GL_Cull( CT_BACK_SIDED ); + GL_PolygonOffset( -r_shadowMapPolygonFactor.GetFloat(), -r_shadowMapPolygonOffset.GetFloat() ); + break; + + default: + GL_Cull( CT_TWO_SIDED ); + GL_PolygonOffset( r_shadowMapPolygonFactor.GetFloat(), r_shadowMapPolygonOffset.GetFloat() ); + break; + } idRenderMatrix lightProjectionRenderMatrix; idRenderMatrix lightViewRenderMatrix; @@ -2546,20 +2556,20 @@ static void RB_ShadowMapPass( const drawSurf_t* drawSurfs, const viewLight_t* vL - globalFramebuffers.shadowFBO->Bind(); + globalFramebuffers.shadowFBO[vLight->shadowLOD]->Bind(); if( side < 0 ) { - globalFramebuffers.shadowFBO->AttachImageDepthLayer( globalImages->shadowImage, 0 ); + globalFramebuffers.shadowFBO[vLight->shadowLOD]->AttachImageDepthLayer( globalImages->shadowImage[vLight->shadowLOD], 0 ); } else { - globalFramebuffers.shadowFBO->AttachImageDepthLayer( globalImages->shadowImage, side ); + globalFramebuffers.shadowFBO[vLight->shadowLOD]->AttachImageDepthLayer( globalImages->shadowImage[vLight->shadowLOD], side ); } - globalFramebuffers.shadowFBO->Check(); + globalFramebuffers.shadowFBO[vLight->shadowLOD]->Check(); - GL_ViewportAndScissor( 0, 0, r_shadowMapImageSize.GetInteger(), r_shadowMapImageSize.GetInteger() ); + GL_ViewportAndScissor( 0, 0, shadowMapResolutions[vLight->shadowLOD], shadowMapResolutions[vLight->shadowLOD] ); glClear( GL_DEPTH_BUFFER_BIT ); diff --git a/neo/renderer/tr_backend_rendertools.cpp b/neo/renderer/tr_backend_rendertools.cpp index af9ca2dc97..1446d9f88d 100644 --- a/neo/renderer/tr_backend_rendertools.cpp +++ b/neo/renderer/tr_backend_rendertools.cpp @@ -1888,20 +1888,11 @@ static void RB_ShowShadowMapLODs() int count = 0; for( viewLight_t* vLight = backEnd.viewDef->viewLights; vLight != NULL; vLight = vLight->next ) { -#if 0 - const idMaterial* lightShader = vLight->lightShader; - - if( lightShader->IsFogLight() ) + if( !vLight->lightDef->LightCastsShadows() ) { continue; } - if( lightShader->IsBlendLight() ) - { - continue; - } -#endif - count++; // depth buffered planes @@ -2925,7 +2916,7 @@ void RB_ShowShadowMaps() if( !r_showShadowMaps.GetBool() ) return; - image = globalImages->shadowImage; + image = globalImages->shadowImage[0]; if( !image ) { return; diff --git a/neo/renderer/tr_frontend_addlights.cpp b/neo/renderer/tr_frontend_addlights.cpp index 70051c2d20..764e2732fe 100644 --- a/neo/renderer/tr_frontend_addlights.cpp +++ b/neo/renderer/tr_frontend_addlights.cpp @@ -266,7 +266,7 @@ static void R_AddSingleLight( viewLight_t* vLight ) vLight->scissorRect.zmax = projected[1][2]; // RB: calculate shadow LOD similar to Q3A .md3 LOD code - vLight->shadowLOD = -1; + vLight->shadowLOD = 0; if( r_useShadowMapping.GetBool() && lightCastsShadows ) { @@ -275,7 +275,7 @@ static void R_AddSingleLight( viewLight_t* vLight ) int lod; int numLods; - numLods = 5; + numLods = MAX_SHADOWMAP_RESOLUTIONS; // compute projected bounding sphere // and use that as a criteria for selecting LOD @@ -323,15 +323,17 @@ static void R_AddSingleLight( viewLight_t* vLight ) if( lod >= numLods ) { // don't draw any shadow - lod = -1; + //lod = -1; - //lod = numLods - 1; + lod = numLods - 1; } // never give ultra quality for point lights if( lod == 0 && light->parms.pointLight ) + { lod = 1; - + } + vLight->shadowLOD = lod; } // RB end diff --git a/neo/renderer/tr_local.h b/neo/renderer/tr_local.h index ce684ee24b..cddf9edf4b 100644 --- a/neo/renderer/tr_local.h +++ b/neo/renderer/tr_local.h @@ -1065,6 +1065,9 @@ extern idCVar r_shadowMapSplits; extern idCVar r_shadowMapSplitWeight; extern idCVar r_shadowMapLodScale; extern idCVar r_shadowMapLodBias; +extern idCVar r_shadowMapPolygonFactor; +extern idCVar r_shadowMapPolygonOffset; +extern idCVar r_shadowMapOccluderFacing; // RB end /*