From 63fe4a167a1ea5e22a798be4c3a7ad89eb32c426 Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Thu, 31 Mar 2022 18:42:52 +0200 Subject: [PATCH] Sort and render shadows into shadowmap atlas --- neo/renderer/Framebuffer.h | 8 +- neo/renderer/NVRHI/Framebuffer_NVRHI.cpp | 4 +- neo/renderer/RenderBackend.cpp | 107 ++++++++++++++++++++--- neo/renderer/RenderCommon.h | 2 + 4 files changed, 101 insertions(+), 20 deletions(-) diff --git a/neo/renderer/Framebuffer.h b/neo/renderer/Framebuffer.h index 5d27e82a..e049b822 100644 --- a/neo/renderer/Framebuffer.h +++ b/neo/renderer/Framebuffer.h @@ -41,11 +41,9 @@ static const int RADIANCE_OCTAHEDRON_SIZE = 512; static const int IRRADIANCE_OCTAHEDRON_SIZE = 30 + 2; static const int SHADOW_ATLAS_SIZE = 8192; -#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 +//static int shadowMapResolutions[MAX_SHADOWMAP_RESOLUTIONS] = { 2048, 1024, 512, 512, 256 }; +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/NVRHI/Framebuffer_NVRHI.cpp b/neo/renderer/NVRHI/Framebuffer_NVRHI.cpp index d13305b9..da4e4da5 100644 --- a/neo/renderer/NVRHI/Framebuffer_NVRHI.cpp +++ b/neo/renderer/NVRHI/Framebuffer_NVRHI.cpp @@ -153,8 +153,8 @@ void Framebuffer::ResizeFramebuffers() } globalFramebuffers.shadowAtlasFBO = new Framebuffer( "_shadowAtlas", - nvrhi::FramebufferDesc() - .setDepthAttachment( globalImages->shadowAtlasImage->texture ) ); + nvrhi::FramebufferDesc() + .setDepthAttachment( globalImages->shadowAtlasImage->texture ) ); globalFramebuffers.ldrFBO = new Framebuffer( "_ldr", nvrhi::FramebufferDesc() diff --git a/neo/renderer/RenderBackend.cpp b/neo/renderer/RenderBackend.cpp index 14865cf7..1dddfefa 100644 --- a/neo/renderer/RenderBackend.cpp +++ b/neo/renderer/RenderBackend.cpp @@ -3355,32 +3355,25 @@ void idRenderBackend::ShadowMapPassFast( const drawSurf_t* drawSurfs, const view #if defined( USE_NVRHI ) + int slice = Max( 0, side ); + if( atlas ) { //globalFramebuffers.shadowAtlasFBO->Bind(); // TODO light offset in atlas - //GL_ViewportAndScissor( 0, 0, shadowMapResolutions[vLight->shadowLOD], shadowMapResolutions[vLight->shadowLOD] ); + GL_ViewportAndScissor( vLight->imageAtlasOffset[slice].x, vLight->imageAtlasOffset[slice].y, vLight->imageSize.x, vLight->imageSize.y ); } else { - if( side < 0 ) - { - globalFramebuffers.shadowFBO[vLight->shadowLOD][0]->Bind(); - } - else - { - globalFramebuffers.shadowFBO[vLight->shadowLOD][side]->Bind(); - } - + globalFramebuffers.shadowFBO[vLight->shadowLOD][slice]->Bind(); GL_ViewportAndScissor( 0, 0, shadowMapResolutions[vLight->shadowLOD], shadowMapResolutions[vLight->shadowLOD] ); const nvrhi::FramebufferAttachment& att = currentFrameBuffer->GetApiObject()->getDesc().depthAttachment; if( att.texture ) { - int slice = std::max( 0, side ); commandList->clearDepthStencilTexture( att.texture, nvrhi::TextureSubresourceSet().setArraySlices( slice, 1 ), true, 1.f, false, 0x80 ); } } @@ -3814,6 +3807,7 @@ void idRenderBackend::ShadowMapPassOld( const drawSurf_t* drawSurfs, const viewL renderLog.CloseBlock(); } +void RectAllocatorBinPack2D( const idList& inputSizes, const idStrList& inputNames, idList& outputPositions, idVec2i& totalSize, const int START_MAX ); void idRenderBackend::ShadowAtlasPass( const viewDef_t* _viewDef ) { @@ -3842,15 +3836,86 @@ void idRenderBackend::ShadowAtlasPass( const viewDef_t* _viewDef ) } // - // for each light, perform shadowing to a big atlas Framebuffer + // sort lights into atlas // + + int shadowIndex = 0; + idList inputSizes; + idStrList inputNames; + for( const viewLight_t* vLight = viewDef->viewLights; vLight != NULL; vLight = vLight->next ) { if( vLight->lightShader->IsFogLight() ) { continue; } - + + if( vLight->lightShader->IsBlendLight() ) + { + continue; + } + + if( vLight->localInteractions == NULL && vLight->globalInteractions == NULL && vLight->translucentInteractions == NULL ) + { + continue; + } + + int side, sideStop; + + if( vLight->parallel ) + { + side = 0; + sideStop = r_shadowMapSplits.GetInteger() + 1; + } + else if( vLight->pointLight ) + { + if( r_shadowMapSingleSide.GetInteger() != -1 ) + { + side = r_shadowMapSingleSide.GetInteger(); + sideStop = side + 1; + } + else + { + side = 0; + sideStop = 6; + } + } + else + { + side = -1; + sideStop = 0; + } + + const idMaterial* lightShader = vLight->lightShader; + + for( ; side < sideStop ; side++ ) + { + //ShadowMapPassFast( vLight->globalShadows, vLight, side, true ); + + inputSizes.Append( idVec2i( shadowMapResolutions[ vLight->shadowLOD ], shadowMapResolutions[ vLight->shadowLOD ] ) ); + inputNames.Append( lightShader->GetName() ); + + shadowIndex++; + } + } + + idList outputPositions; + idVec2i totalSize; + + RectAllocatorBinPack2D( inputSizes, inputNames, outputPositions, totalSize, SHADOW_ATLAS_SIZE ); + + // + // for each light, perform shadowing to a big atlas Framebuffer + // + shadowIndex = 0; + + for( viewLight_t* vLight = viewDef->viewLights; vLight != NULL; vLight = vLight->next ) + { + if( vLight->lightShader->IsFogLight() ) + { + continue; + } + if( vLight->lightShader->IsBlendLight() ) { continue; @@ -3898,8 +3963,24 @@ void idRenderBackend::ShadowAtlasPass( const viewDef_t* _viewDef ) sideStop = 0; } + vLight->imageSize.x = shadowMapResolutions[ vLight->shadowLOD ]; + vLight->imageSize.y = shadowMapResolutions[ vLight->shadowLOD ]; + for( ; side < sideStop ; side++ ) { + int slice = Max( 0, side ); + + vLight->imageAtlasOffset[ slice ].x = outputPositions[ shadowIndex ].x; + vLight->imageAtlasOffset[ slice ].y = outputPositions[ shadowIndex ].y; + + shadowIndex++; + + if( vLight->imageAtlasOffset[ slice ].x == -1 || vLight->imageAtlasOffset[ slice ].y == -1 ) + { + // didn't fit into atlas anymore + continue; + } + ShadowMapPassFast( vLight->globalShadows, vLight, side, true ); } diff --git a/neo/renderer/RenderCommon.h b/neo/renderer/RenderCommon.h index 1851a84f..39e3f4e0 100644 --- a/neo/renderer/RenderCommon.h +++ b/neo/renderer/RenderCommon.h @@ -416,6 +416,8 @@ struct viewLight_t bool parallel; // lightCenter gives the direction to the light at infinity idVec3 lightCenter; // offset the lighting direction for shading and int shadowLOD; // level of detail for shadowmap selection + idVec2i imageSize; + idVec2i imageAtlasOffset[6]; // RB end idRenderMatrix inverseBaseLightProject; // the matrix for deforming the 'zeroOneCubeModel' to exactly cover the light volume in world space const idMaterial* lightShader; // light shader used by backend