From 0d9d13d6f0bd253279db0828da2f45fb8ea2f524 Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Sat, 2 Apr 2022 11:57:33 +0200 Subject: [PATCH] Fixed shadow plopping effects and reeanbled vogel disk sampling --- neo/renderer/Framebuffer.h | 4 ++- neo/renderer/RenderBackend.cpp | 30 ++++++++++++++----- .../builtin/lighting/interactionSM.ps.hlsl | 29 +++++++++++------- 3 files changed, 43 insertions(+), 20 deletions(-) diff --git a/neo/renderer/Framebuffer.h b/neo/renderer/Framebuffer.h index e75372f7..a4ff2e69 100644 --- a/neo/renderer/Framebuffer.h +++ b/neo/renderer/Framebuffer.h @@ -40,9 +40,11 @@ static const int ENVPROBE_CAPTURE_SIZE = 256; static const int RADIANCE_OCTAHEDRON_SIZE = 512; static const int IRRADIANCE_OCTAHEDRON_SIZE = 30 + 2; +// RB: shadow resolutions used in 1.3 //static int shadowMapResolutions[MAX_SHADOWMAP_RESOLUTIONS] = { 2048, 1024, 512, 512, 256 }; + +// if we use higher resolutions than this than the shadow casting lights don't fit into the 16384^2 atlas anymore static int shadowMapResolutions[MAX_SHADOWMAP_RESOLUTIONS] = { 1024, 512, 512, 256, 128 }; -//static int shadowMapResolutions[MAX_SHADOWMAP_RESOLUTIONS] = { 1024, 1024, 1024, 1024, 1024 }; class Framebuffer diff --git a/neo/renderer/RenderBackend.cpp b/neo/renderer/RenderBackend.cpp index e1109df4..ba68371a 100644 --- a/neo/renderer/RenderBackend.cpp +++ b/neo/renderer/RenderBackend.cpp @@ -1510,7 +1510,7 @@ void idRenderBackend::RenderInteractions( const drawSurf_t* surfList, const view float screenCorrectionParm[4]; screenCorrectionParm[0] = 1.0f / ( JITTER_SIZE * shadowMapSamples ) ; screenCorrectionParm[1] = 1.0f / JITTER_SIZE; - screenCorrectionParm[2] = 1.0f / vLight->imageSize.x; // atlas sample scale + screenCorrectionParm[2] = 1.0f / r_shadowMapAtlasSize.GetInteger(); // atlas sample scale screenCorrectionParm[3] = vLight->parallel ? r_shadowMapSunDepthBiasScale.GetFloat() : r_shadowMapRegularDepthBiasScale.GetFloat(); SetFragmentParm( RENDERPARM_SCREENCORRECTIONFACTOR, screenCorrectionParm ); // rpScreenCorrectionFactor @@ -3885,7 +3885,7 @@ void idRenderBackend::ShadowAtlasPass( const viewDef_t* _viewDef ) int shadowIndex = 0; idList inputSizes; - idStrList inputNames; + //idStrList inputNames; for( const viewLight_t* vLight = viewDef->viewLights; vLight != NULL; vLight = vLight->next ) { @@ -3935,16 +3935,17 @@ void idRenderBackend::ShadowAtlasPass( const viewDef_t* _viewDef ) for( ; side < sideStop ; side++ ) { inputSizes.Append( idVec2i( shadowMapResolutions[ vLight->shadowLOD ], shadowMapResolutions[ vLight->shadowLOD ] ) ); - inputNames.Append( lightShader->GetName() ); + //inputNames.Append( lightShader->GetName() ); shadowIndex++; } } idList outputPositions; - idVec2i totalSize; + idList outputSizes; + //idVec2i totalSize; -#if 1 +#if 0 RectAllocatorBinPack2D( inputSizes, inputNames, outputPositions, totalSize, r_shadowMapAtlasSize.GetInteger() ); @@ -3954,6 +3955,7 @@ void idRenderBackend::ShadowAtlasPass( const viewDef_t* _viewDef ) // RB: we don't use RectAllocatorQuadTree here because we don't want to rebuild the quad tree every frame outputPositions.SetNum( inputSizes.Num() ); + outputSizes.SetNum( inputSizes.Num() ); idList sizeRemap; sizeRemap.SetNum( inputSizes.Num() ); @@ -3977,6 +3979,7 @@ void idRenderBackend::ShadowAtlasPass( const viewDef_t* _viewDef ) idVec2i size = inputSizes[ shadowIndex ]; int area = Max( size.x, size.y ); + //int area = 1024; Tile tile; bool result = tileMap.GetTile( area, tile ); @@ -3984,18 +3987,26 @@ void idRenderBackend::ShadowAtlasPass( const viewDef_t* _viewDef ) if( !result ) { outputPositions[ shadowIndex ].Set( -1, -1 ); + outputSizes[ shadowIndex ] = area; } else { + int imageSize = tile.size * r_shadowMapAtlasSize.GetInteger(); + outputSizes[ shadowIndex ] = imageSize; + // convert from [-1..-1] -> [0..1] and flip y idVec2 uvPos; uvPos.x = tile.position.x * 0.5f + 0.5f; - uvPos.y = 1.0f - ( tile.position.y * 0.5f + 0.5f ); + uvPos.y = tile.position.y * 0.5f + 0.5f; idVec2i iPos; iPos.x = uvPos.x * r_shadowMapAtlasSize.GetInteger(); iPos.y = uvPos.y * r_shadowMapAtlasSize.GetInteger(); + // RB: this is really odd but necessary + iPos.x -= imageSize * 0.5f; + iPos.y -= imageSize * 0.5f; + outputPositions[ shadowIndex ].x = iPos.x; outputPositions[ shadowIndex ].y = iPos.y; } @@ -4060,8 +4071,11 @@ void idRenderBackend::ShadowAtlasPass( const viewDef_t* _viewDef ) sideStop = 0; } - vLight->imageSize.x = shadowMapResolutions[ vLight->shadowLOD ]; - vLight->imageSize.y = shadowMapResolutions[ vLight->shadowLOD ]; + //vLight->imageSize.x = shadowMapResolutions[ vLight->shadowLOD ]; + //vLight->imageSize.y = shadowMapResolutions[ vLight->shadowLOD ]; + + vLight->imageSize.x = outputSizes[ shadowIndex ]; + vLight->imageSize.y = outputSizes[ shadowIndex ]; bool imageFitsIntoAtlas = true; diff --git a/neo/shaders/builtin/lighting/interactionSM.ps.hlsl b/neo/shaders/builtin/lighting/interactionSM.ps.hlsl index 932c1716..315f162f 100644 --- a/neo/shaders/builtin/lighting/interactionSM.ps.hlsl +++ b/neo/shaders/builtin/lighting/interactionSM.ps.hlsl @@ -226,10 +226,11 @@ void main( PS_IN fragment, out PS_OUT result ) shadowTexcoord.xyz /= shadowTexcoord.w; - shadowTexcoord.z = shadowTexcoord.z * rpScreenCorrectionFactor.w; + // receiver / occluder terminology like in ESM + float receiver = shadowTexcoord.z * rpScreenCorrectionFactor.w; //shadowTexcoord.z = shadowTexcoord.z * 0.999991; //shadowTexcoord.z = shadowTexcoord.z - bias; - shadowTexcoord.w = float( shadowIndex ); + //shadowTexcoord.w = float( shadowIndex ); // multiple taps @@ -306,7 +307,7 @@ void main( PS_IN fragment, out PS_OUT result ) shadow *= stepSize; -#elif 0 +#elif 1 #if 0 @@ -331,7 +332,7 @@ void main( PS_IN fragment, out PS_OUT result ) float shadow = 0.0; // RB: casting a float to int and using it as index can really kill the performance ... - float numSamples = 6.0; + float numSamples = 12.0; float stepSize = 1.0 / numSamples; float random = BlueNoise( fragment.position.xy, 1.0 ); @@ -344,16 +345,19 @@ void main( PS_IN fragment, out PS_OUT result ) rot.y = sin( random ); float shadowTexelSize = rpScreenCorrectionFactor.z * rpJitterTexScale.x; - for( int i = 0; i < 6; i++ ) + for( int si = 0; si < 12; si++ ) { - float2 jitter = poissonDisk[i]; + float2 jitter = poissonDisk[si]; float2 jitterRotated; jitterRotated.x = jitter.x * rot.x - jitter.y * rot.y; jitterRotated.y = jitter.x * rot.y + jitter.y * rot.x; - float4 shadowTexcoordJittered = float4( shadowTexcoord.xy + jitterRotated * shadowTexelSize, shadowTexcoord.z, shadowTexcoord.w ); + // [0 .. 1] -> rectangle in atlas transform + float2 shadowTexcoordAtlas = shadowTexcoord.xy * rpJitterTexScale.y + rpShadowAtlasOffsets[ shadowIndex ].xy; - shadow += idtex2Dproj( s_Shadow, t_ShadowMapArray, shadowTexcoordJittered.xywz ); + float2 shadowTexcoordJittered = shadowTexcoordAtlas.xy + jitterRotated * shadowTexelSize; + + shadow += t_ShadowAtlas.SampleCmpLevelZero( s_Shadow, shadowTexcoordJittered.xy, receiver ); } shadow *= stepSize; @@ -379,9 +383,12 @@ void main( PS_IN fragment, out PS_OUT result ) { float2 jitter = VogelDiskSample( si, numSamples, vogelPhi ); - float4 shadowTexcoordJittered = float4( shadowTexcoord.xy + jitter * shadowTexelSize, shadowTexcoord.z, shadowTexcoord.w ); + // [0 .. 1] -> rectangle in atlas transform + float2 shadowTexcoordAtlas = shadowTexcoord.xy * rpJitterTexScale.y + rpShadowAtlasOffsets[ shadowIndex ].xy; - shadow += t_ShadowMapArray.SampleCmpLevelZero( s_Shadow, shadowTexcoordJittered.xyw, shadowTexcoordJittered.z ); + float2 shadowTexcoordJittered = shadowTexcoordAtlas + jitter * shadowTexelSize; + + shadow += t_ShadowAtlas.SampleCmpLevelZero( s_Shadow, shadowTexcoordJittered.xy, receiver ); } shadow *= stepSize; @@ -395,7 +402,7 @@ void main( PS_IN fragment, out PS_OUT result ) // [0 .. 1] -> rectangle in atlas transform uvShadow = uvShadow * rpJitterTexScale.y + rpShadowAtlasOffsets[ shadowIndex ].xy; - float shadow = t_ShadowAtlas.SampleCmpLevelZero( s_Shadow, uvShadow.xy, shadowTexcoord.z ); + float shadow = t_ShadowAtlas.SampleCmpLevelZero( s_Shadow, uvShadow.xy, receiver ); #if 0 if( shadowIndex == 0 )