2020-06-23 18:40:00 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
/*=============================================================================
VolumetricRenderTarget . cpp
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
# include "VolumetricRenderTarget.h"
# include "DeferredShadingRenderer.h"
# include "RenderCore/Public/RenderGraphUtils.h"
# include "RenderCore/Public/PixelShaderUtils.h"
# include "ScenePrivate.h"
# include "SceneTextureParameters.h"
2020-09-01 14:07:48 -04:00
# include "SingleLayerWaterRendering.h"
2020-12-11 14:21:20 -04:00
# include "VolumetricCloudRendering.h"
2021-10-12 21:21:22 -04:00
# include "RendererUtils.h"
2020-06-23 18:40:00 -04:00
//PRAGMA_DISABLE_OPTIMIZATION
static TAutoConsoleVariable < int32 > CVarVolumetricRenderTarget (
TEXT ( " r.VolumetricRenderTarget " ) , 1 ,
TEXT ( " " ) ,
ECVF_SetByScalability | ECVF_RenderThreadSafe ) ;
static TAutoConsoleVariable < float > CVarVolumetricRenderTargetUvNoiseScale (
TEXT ( " r.VolumetricRenderTarget.UvNoiseScale " ) , 0.5f ,
2020-10-29 13:38:15 -04:00
TEXT ( " Used when r.VolumetricRenderTarget.UpsamplingMode is in a mode using jitter - this value scales the amount of jitter. " ) ,
2020-06-23 18:40:00 -04:00
ECVF_SetByScalability ) ;
2021-04-09 10:12:51 -04:00
static TAutoConsoleVariable < float > CVarVolumetricRenderTargetUvNoiseSampleAcceptanceWeight (
TEXT ( " r.VolumetricRenderTarget.UvNoiseSampleAcceptanceWeight " ) , 20.0f ,
TEXT ( " Used when r.VolumetricRenderTarget.UpsamplingMode is in a mode using jitter - this value control the acceptance of noisy cloud samples according to their similarities. A higher value means large differences will be less accepted for blending. " ) ,
ECVF_SetByScalability ) ;
2020-06-23 18:40:00 -04:00
static TAutoConsoleVariable < int32 > CVarVolumetricRenderTargetMode (
TEXT ( " r.VolumetricRenderTarget.Mode " ) , 0 ,
2020-12-11 14:21:20 -04:00
TEXT ( " [0] trace quarter resolution + reconstruct at half resolution + upsample [1] trace half res + reconstruct full res + upsample [2] trace at quarter resolution + reconstruct full resolution (cannot intersect with opaque meshes and forces UpsamplingMode=2 [3] trace 1/8 resolution + reconstruct at half resolution + upsample) " ) ,
2020-06-23 18:40:00 -04:00
ECVF_SetByScalability ) ;
static TAutoConsoleVariable < int32 > CVarVolumetricRenderTargetUpsamplingMode (
2020-09-24 00:43:27 -04:00
TEXT ( " r.VolumetricRenderTarget.UpsamplingMode " ) , 4 ,
2020-10-29 13:38:15 -04:00
TEXT ( " Used in compositing volumetric RT over the scene. [0] bilinear [1] bilinear + jitter [2] nearest + depth test [3] bilinear + jitter + keep closest [4] bilaterial upsampling " ) ,
2020-06-23 18:40:00 -04:00
ECVF_SetByScalability ) ;
2020-12-11 14:21:20 -04:00
static TAutoConsoleVariable < int32 > CVarVolumetricRenderTargetPreferAsyncCompute (
TEXT ( " r.VolumetricRenderTarget.PreferAsyncCompute " ) , 0 ,
TEXT ( " Whether to prefer using async compute to generate volumetric cloud render targets. " ) ,
ECVF_SetByScalability | ECVF_RenderThreadSafe ) ;
2021-03-31 08:32:53 -04:00
static TAutoConsoleVariable < int32 > CVarVolumetricRenderTargetReprojectionBoxConstraint (
TEXT ( " r.VolumetricRenderTarget.ReprojectionBoxConstraint " ) , 0 ,
TEXT ( " Whether reprojected data should be constrained to the new incoming cloud data neighborhod value. " ) ,
ECVF_SetByScalability | ECVF_RenderThreadSafe ) ;
2020-06-23 18:40:00 -04:00
2021-04-09 10:12:51 -04:00
static float GetUvNoiseSampleAcceptanceWeight ( )
{
return FMath : : Max ( 0.0f , CVarVolumetricRenderTargetUvNoiseSampleAcceptanceWeight . GetValueOnRenderThread ( ) ) ;
}
2020-06-23 18:40:00 -04:00
static bool ShouldPipelineCompileVolumetricRenderTargetShaders ( EShaderPlatform ShaderPlatform )
{
return GetMaxSupportedFeatureLevel ( ShaderPlatform ) > = ERHIFeatureLevel : : SM5 ;
}
2020-08-11 01:36:57 -04:00
bool ShouldViewRenderVolumetricCloudRenderTarget ( const FViewInfo & ViewInfo )
2020-06-23 18:40:00 -04:00
{
return CVarVolumetricRenderTarget . GetValueOnRenderThread ( ) & & ShouldPipelineCompileVolumetricRenderTargetShaders ( ViewInfo . GetShaderPlatform ( ) )
2021-12-02 03:05:51 -05:00
& & ( ViewInfo . ViewState ! = nullptr ) & & ! ViewInfo . bIsReflectionCapture ;
2020-06-23 18:40:00 -04:00
}
2020-09-24 00:43:27 -04:00
bool IsVolumetricRenderTargetEnabled ( )
{
return CVarVolumetricRenderTarget . GetValueOnRenderThread ( ) > 0 ;
}
2020-12-11 14:21:20 -04:00
bool IsVolumetricRenderTargetAsyncCompute ( )
{
// TODO remove that when we remove the pixel shading path in 5.0
static auto CVar = IConsoleManager : : Get ( ) . FindConsoleVariable ( TEXT ( " r.VolumetricCloud.DisableCompute " ) ) ;
const bool bCloudComputePathDisabled = CVar & & CVar - > GetInt ( ) > 1 ;
return GSupportsEfficientAsyncCompute & & CVarVolumetricRenderTargetPreferAsyncCompute . GetValueOnRenderThread ( ) > 0 & & ! bCloudComputePathDisabled ;
}
2020-08-11 01:36:57 -04:00
static bool ShouldViewComposeVolumetricRenderTarget ( const FViewInfo & ViewInfo )
2020-06-23 18:40:00 -04:00
{
2020-09-24 00:43:27 -04:00
return ShouldViewRenderVolumetricCloudRenderTarget ( ViewInfo ) ;
2020-06-23 18:40:00 -04:00
}
2020-08-11 01:36:57 -04:00
static uint32 GetMainDownsampleFactor ( int32 Mode )
2020-06-23 18:40:00 -04:00
{
2020-08-11 01:36:57 -04:00
switch ( Mode )
2020-06-23 18:40:00 -04:00
{
case 0 :
2020-12-11 14:21:20 -04:00
case 3 :
2020-06-23 18:40:00 -04:00
return 2 ; // Reconstruct at half resolution of view
break ;
case 1 :
case 2 :
return 1 ; // Reconstruct at full resolution of view
break ;
}
check ( false ) ; // unhandled mode
return 2 ;
}
2020-08-11 01:36:57 -04:00
static uint32 GetTraceDownsampleFactor ( int32 Mode )
2020-06-23 18:40:00 -04:00
{
2020-08-11 01:36:57 -04:00
switch ( Mode )
2020-06-23 18:40:00 -04:00
{
case 0 :
2020-12-11 14:21:20 -04:00
return 2 ; // Trace at half resolution of the reconstructed buffer (with it being at the half the resolution of the main view)
2020-06-23 18:40:00 -04:00
break ;
case 1 :
2020-12-11 14:21:20 -04:00
return 2 ; // Trace at half resolution of the reconstructed buffer (with it being at the same resolution as main view)
2020-06-23 18:40:00 -04:00
break ;
case 2 :
2020-12-11 14:21:20 -04:00
return 4 ; // Trace at quarter resolution of the reconstructed buffer (with it being at the same resolution as main view)
break ;
case 3 :
return 4 ; // Trace at quarter resolution of the reconstructed buffer (with it being at the half the resolution of the main view)
2020-06-23 18:40:00 -04:00
break ;
}
check ( false ) ; // unhandled mode
return 2 ;
}
2021-09-22 10:01:48 -04:00
static void GetTextureSafeUvCoordBound ( FRDGTextureRef Texture , FUintVector4 & TextureValidCoordRect , FVector4f & TextureValidUvRect )
2020-06-23 18:40:00 -04:00
{
FIntVector TexSize = Texture - > Desc . GetSize ( ) ;
TextureValidCoordRect . X = 0 ;
TextureValidCoordRect . Y = 0 ;
TextureValidCoordRect . Z = TexSize . X - 1 ;
TextureValidCoordRect . W = TexSize . Y - 1 ;
TextureValidUvRect . X = 0.51f / float ( TexSize . X ) ;
TextureValidUvRect . Y = 0.51f / float ( TexSize . Y ) ;
TextureValidUvRect . Z = ( float ( TexSize . X ) - 0.51f ) / float ( TexSize . X ) ;
TextureValidUvRect . W = ( float ( TexSize . Y ) - 0.51f ) / float ( TexSize . Y ) ;
} ;
2020-11-06 11:50:06 -04:00
static bool AnyViewRequiresProcessing ( TArrayView < FViewInfo > Views )
2020-09-01 14:07:48 -04:00
{
bool bAnyViewRequiresProcessing = false ;
for ( int32 ViewIndex = 0 ; ViewIndex < Views . Num ( ) ; ViewIndex + + )
{
FViewInfo & ViewInfo = Views [ ViewIndex ] ;
bAnyViewRequiresProcessing | = ShouldViewComposeVolumetricRenderTarget ( ViewInfo ) ;
}
return bAnyViewRequiresProcessing ;
}
2020-06-23 18:40:00 -04:00
/*=============================================================================
UVolumetricCloudComponent implementation .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
FVolumetricRenderTargetViewStateData : : FVolumetricRenderTargetViewStateData ( )
: CurrentRT ( 1 )
, bFirstTimeUsed ( true )
, bHistoryValid ( false )
2020-08-11 01:36:57 -04:00
, FullResolution ( FIntPoint : : ZeroValue )
2020-06-23 18:40:00 -04:00
, VolumetricReconstructRTResolution ( FIntPoint : : ZeroValue )
, VolumetricTracingRTResolution ( FIntPoint : : ZeroValue )
{
2020-08-11 01:36:57 -04:00
VolumetricReconstructRTDownsampleFactor = 0 ;
VolumetricTracingRTDownsampleFactor = 0 ;
2020-06-23 18:40:00 -04:00
}
FVolumetricRenderTargetViewStateData : : ~ FVolumetricRenderTargetViewStateData ( )
{
}
2020-08-11 01:36:57 -04:00
void FVolumetricRenderTargetViewStateData : : Initialise (
FIntPoint & ViewRectResolutionIn ,
float InUvNoiseScale ,
int32 InMode ,
2020-10-29 13:38:15 -04:00
int32 InUpsamplingMode )
2020-06-23 18:40:00 -04:00
{
2020-08-11 01:36:57 -04:00
// Update internal settings
UvNoiseScale = InUvNoiseScale ;
2020-12-11 14:21:20 -04:00
Mode = FMath : : Clamp ( InMode , 0 , 3 ) ;
2020-10-29 13:38:15 -04:00
UpsamplingMode = Mode = = 2 ? 2 : FMath : : Clamp ( InUpsamplingMode , 0 , 4 ) ; // if we are using mode 2 then we cannot intersect with depth and upsampling should be 2 (simple on/off intersection)
2020-08-11 01:36:57 -04:00
2020-06-23 18:40:00 -04:00
if ( bFirstTimeUsed )
{
bFirstTimeUsed = false ;
bHistoryValid = false ;
FrameId = 0 ;
NoiseFrameIndex = 0 ;
NoiseFrameIndexModPattern = 0 ;
CurrentPixelOffset = FIntPoint : : ZeroValue ;
}
{
CurrentRT = 1 - CurrentRT ;
const uint32 PreviousRT = 1 - CurrentRT ;
// We always reallocate on a resolution change to adapt to dynamic resolution scaling.
// TODO allocate once at max resolution and change source and destination coord/uvs/rect.
2020-08-11 01:36:57 -04:00
if ( FullResolution ! = ViewRectResolutionIn | | GetMainDownsampleFactor ( Mode ) ! = VolumetricReconstructRTDownsampleFactor | | GetTraceDownsampleFactor ( Mode ) ! = VolumetricTracingRTDownsampleFactor )
2020-06-23 18:40:00 -04:00
{
2020-08-11 01:36:57 -04:00
VolumetricReconstructRTDownsampleFactor = GetMainDownsampleFactor ( Mode ) ;
VolumetricTracingRTDownsampleFactor = GetTraceDownsampleFactor ( Mode ) ;
2020-06-23 18:40:00 -04:00
FullResolution = ViewRectResolutionIn ;
VolumetricReconstructRTResolution = FIntPoint : : DivideAndRoundUp ( FullResolution , VolumetricReconstructRTDownsampleFactor ) ; // Half resolution
VolumetricTracingRTResolution = FIntPoint : : DivideAndRoundUp ( VolumetricReconstructRTResolution , VolumetricTracingRTDownsampleFactor ) ; // Half resolution of the volumetric buffer
// Need a new size so release the low resolution trace buffer
VolumetricTracingRT . SafeRelease ( ) ;
VolumetricTracingRTDepth . SafeRelease ( ) ;
}
FIntVector CurrentTargetResVec = VolumetricReconstructRT [ CurrentRT ] . IsValid ( ) ? VolumetricReconstructRT [ CurrentRT ] - > GetDesc ( ) . GetSize ( ) : FIntVector : : ZeroValue ;
FIntPoint CurrentTargetRes = FIntPoint : : DivideAndRoundUp ( FullResolution , VolumetricReconstructRTDownsampleFactor ) ;
if ( VolumetricReconstructRT [ CurrentRT ] . IsValid ( ) & & FIntPoint ( CurrentTargetResVec . X , CurrentTargetResVec . Y ) ! = CurrentTargetRes )
{
// Resolution does not match so release target we are going to render in
VolumetricReconstructRT [ CurrentRT ] . SafeRelease ( ) ;
VolumetricReconstructRTDepth [ CurrentRT ] . SafeRelease ( ) ;
}
// Regular every frame update
{
// Do not mark history as valid if the half resolution buffer is not valid. That means nothing has been rendered last frame.
// That can happen when cloud is used to render into that buffer
bHistoryValid = VolumetricReconstructRT [ PreviousRT ] . IsValid ( ) ;
NoiseFrameIndex + = FrameId = = 0 ? 1 : 0 ;
NoiseFrameIndexModPattern = NoiseFrameIndex % ( VolumetricTracingRTDownsampleFactor * VolumetricTracingRTDownsampleFactor ) ;
FrameId + + ;
FrameId = FrameId % ( VolumetricTracingRTDownsampleFactor * VolumetricTracingRTDownsampleFactor ) ;
if ( VolumetricTracingRTDownsampleFactor = = 2 )
{
static int32 OrderDithering2x2 [ 4 ] = { 0 , 2 , 3 , 1 } ;
int32 LocalFrameId = OrderDithering2x2 [ FrameId ] ;
CurrentPixelOffset = FIntPoint ( LocalFrameId % VolumetricTracingRTDownsampleFactor , LocalFrameId / VolumetricTracingRTDownsampleFactor ) ;
}
else if ( VolumetricTracingRTDownsampleFactor = = 4 )
{
static int32 OrderDithering4x4 [ 16 ] = { 0 , 8 , 2 , 10 , 12 , 4 , 14 , 6 , 3 , 11 , 1 , 9 , 15 , 7 , 13 , 5 } ;
int32 LocalFrameId = OrderDithering4x4 [ FrameId ] ;
CurrentPixelOffset = FIntPoint ( LocalFrameId % VolumetricTracingRTDownsampleFactor , LocalFrameId / VolumetricTracingRTDownsampleFactor ) ;
}
else
{
// Default linear parse
CurrentPixelOffset = FIntPoint ( FrameId % VolumetricTracingRTDownsampleFactor , FrameId / VolumetricTracingRTDownsampleFactor ) ;
}
}
}
}
FRDGTextureRef FVolumetricRenderTargetViewStateData : : GetOrCreateVolumetricTracingRT ( FRDGBuilder & GraphBuilder )
{
check ( FullResolution ! = FIntPoint : : ZeroValue ) ; // check that initialization has been done at least once
2020-09-24 00:43:27 -04:00
if ( ! VolumetricTracingRT . IsValid ( ) )
2020-06-23 18:40:00 -04:00
{
2020-09-24 00:43:27 -04:00
FPooledRenderTargetDesc Desc = FPooledRenderTargetDesc : : Create2DDesc (
VolumetricTracingRTResolution , PF_FloatRGBA , FClearValueBinding ( FLinearColor ( 0.0f , 0.0f , 0.0f , 1.0f ) ) ,
2020-12-11 14:21:20 -04:00
TexCreate_None , TexCreate_ShaderResource | TexCreate_RenderTargetable | TexCreate_UAV , false ) ;
2022-01-13 17:56:22 -05:00
GRenderTargetPool . FindFreeElement ( GraphBuilder . RHICmdList , Desc , VolumetricTracingRT , TEXT ( " VolumetricRenderTarget.Tracing " ) ) ;
2020-06-23 18:40:00 -04:00
}
2020-09-24 00:43:27 -04:00
return GraphBuilder . RegisterExternalTexture ( VolumetricTracingRT ) ;
2020-06-23 18:40:00 -04:00
}
FRDGTextureRef FVolumetricRenderTargetViewStateData : : GetOrCreateVolumetricTracingRTDepth ( FRDGBuilder & GraphBuilder )
{
check ( FullResolution ! = FIntPoint : : ZeroValue ) ; // check that initialization has been done at least once
2020-09-24 00:43:27 -04:00
if ( ! VolumetricTracingRTDepth . IsValid ( ) )
2020-06-23 18:40:00 -04:00
{
2020-09-24 00:43:27 -04:00
FPooledRenderTargetDesc Desc = FPooledRenderTargetDesc : : Create2DDesc (
VolumetricTracingRTResolution , PF_G16R16F , FClearValueBinding ( FLinearColor ( 63000.0f , 63000.0f , 63000.0f , 63000.0f ) ) ,
2020-12-11 14:21:20 -04:00
TexCreate_None , TexCreate_ShaderResource | TexCreate_RenderTargetable | TexCreate_UAV , false ) ;
2022-01-13 17:56:22 -05:00
GRenderTargetPool . FindFreeElement ( GraphBuilder . RHICmdList , Desc , VolumetricTracingRTDepth , TEXT ( " VolumetricRenderTarget.TracingDepth " ) ) ;
2020-06-23 18:40:00 -04:00
}
2020-09-24 00:43:27 -04:00
return GraphBuilder . RegisterExternalTexture ( VolumetricTracingRTDepth ) ;
2020-06-23 18:40:00 -04:00
}
FRDGTextureRef FVolumetricRenderTargetViewStateData : : GetOrCreateDstVolumetricReconstructRT ( FRDGBuilder & GraphBuilder )
{
check ( VolumetricReconstructRTResolution ! = FIntPoint : : ZeroValue ) ; // check that initialization has been done at least once
2020-09-24 00:43:27 -04:00
if ( ! VolumetricReconstructRT [ CurrentRT ] . IsValid ( ) )
2020-06-23 18:40:00 -04:00
{
2020-09-24 00:43:27 -04:00
FPooledRenderTargetDesc Desc = FPooledRenderTargetDesc : : Create2DDesc (
VolumetricReconstructRTResolution , PF_FloatRGBA , FClearValueBinding ( FLinearColor ( 0.0f , 0.0f , 0.0f , 1.0f ) ) ,
TexCreate_None , TexCreate_ShaderResource | TexCreate_RenderTargetable , false ) ;
2022-01-13 17:56:22 -05:00
GRenderTargetPool . FindFreeElement ( GraphBuilder . RHICmdList , Desc , VolumetricReconstructRT [ CurrentRT ] , TEXT ( " VolumetricRenderTarget.Reconstruct " ) ) ;
2020-06-23 18:40:00 -04:00
}
2020-09-24 00:43:27 -04:00
return GraphBuilder . RegisterExternalTexture ( VolumetricReconstructRT [ CurrentRT ] ) ;
2020-06-23 18:40:00 -04:00
}
FRDGTextureRef FVolumetricRenderTargetViewStateData : : GetOrCreateDstVolumetricReconstructRTDepth ( FRDGBuilder & GraphBuilder )
{
check ( VolumetricReconstructRTResolution ! = FIntPoint : : ZeroValue ) ; // check that initialization has been done at least once
2020-09-24 00:43:27 -04:00
if ( ! VolumetricReconstructRTDepth [ CurrentRT ] . IsValid ( ) )
2020-06-23 18:40:00 -04:00
{
2020-09-24 00:43:27 -04:00
FPooledRenderTargetDesc Desc = FPooledRenderTargetDesc : : Create2DDesc (
VolumetricReconstructRTResolution , PF_G16R16F , FClearValueBinding ( FLinearColor ( 63000.0f , 63000.0f , 63000.0f , 63000.0f ) ) ,
TexCreate_None , TexCreate_ShaderResource | TexCreate_RenderTargetable , false ) ;
2022-01-13 17:56:22 -05:00
GRenderTargetPool . FindFreeElement ( GraphBuilder . RHICmdList , Desc , VolumetricReconstructRTDepth [ CurrentRT ] , TEXT ( " VolumetricRenderTarget.ReconstructDepth " ) ) ;
2020-06-23 18:40:00 -04:00
}
2020-09-24 00:43:27 -04:00
return GraphBuilder . RegisterExternalTexture ( VolumetricReconstructRTDepth [ CurrentRT ] ) ;
2020-06-23 18:40:00 -04:00
}
2020-09-24 00:43:27 -04:00
TRefCountPtr < IPooledRenderTarget > FVolumetricRenderTargetViewStateData : : GetDstVolumetricReconstructRT ( )
2020-06-23 18:40:00 -04:00
{
2020-09-24 00:43:27 -04:00
return VolumetricReconstructRT [ CurrentRT ] ;
2020-06-23 18:40:00 -04:00
}
2020-09-24 00:43:27 -04:00
TRefCountPtr < IPooledRenderTarget > FVolumetricRenderTargetViewStateData : : GetDstVolumetricReconstructRTDepth ( )
2020-06-23 18:40:00 -04:00
{
2020-09-24 00:43:27 -04:00
return VolumetricReconstructRTDepth [ CurrentRT ] ;
2020-06-23 18:40:00 -04:00
}
FRDGTextureRef FVolumetricRenderTargetViewStateData : : GetOrCreateSrcVolumetricReconstructRT ( FRDGBuilder & GraphBuilder )
{
check ( VolumetricReconstructRTResolution ! = FIntPoint : : ZeroValue ) ; // check that initialization has been done at least once
check ( VolumetricReconstructRT [ 1u - CurrentRT ] . IsValid ( ) ) ;
return GraphBuilder . RegisterExternalTexture ( VolumetricReconstructRT [ 1u - CurrentRT ] ) ;
}
FRDGTextureRef FVolumetricRenderTargetViewStateData : : GetOrCreateSrcVolumetricReconstructRTDepth ( FRDGBuilder & GraphBuilder )
{
check ( VolumetricReconstructRTResolution ! = FIntPoint : : ZeroValue ) ; // check that initialization has been done at least once
check ( VolumetricReconstructRT [ 1u - CurrentRT ] . IsValid ( ) ) ;
return GraphBuilder . RegisterExternalTexture ( VolumetricReconstructRTDepth [ 1u - CurrentRT ] ) ;
}
2020-09-24 00:43:27 -04:00
FUintVector4 FVolumetricRenderTargetViewStateData : : GetTracingCoordToZbufferCoordScaleBias ( ) const
2020-06-23 18:40:00 -04:00
{
2020-09-24 00:43:27 -04:00
if ( Mode = = 2 | | Mode = = 1 )
{
// In this case, the source depth buffer full resolution depth buffer is the full resolution scene one
const uint32 CombinedDownsampleFactor = VolumetricReconstructRTDownsampleFactor * VolumetricTracingRTDownsampleFactor ;
return FUintVector4 ( CombinedDownsampleFactor , CombinedDownsampleFactor , // Scale is the combined downsample factor
CurrentPixelOffset . X * VolumetricReconstructRTDownsampleFactor , CurrentPixelOffset . Y * VolumetricReconstructRTDownsampleFactor ) ; // Each sample will then sample from full res according to reconstructed RT offset times its downsample factor
}
// Otherwise, a half resolution depth buffer is used
const uint32 SourceDepthBufferRTDownsampleFactor = 2 ;
const uint32 CombinedDownsampleFactor = VolumetricReconstructRTDownsampleFactor * VolumetricTracingRTDownsampleFactor / SourceDepthBufferRTDownsampleFactor ;
return FUintVector4 ( CombinedDownsampleFactor , CombinedDownsampleFactor , // Scale is the combined downsample factor
CurrentPixelOffset . X * VolumetricReconstructRTDownsampleFactor / VolumetricReconstructRTDownsampleFactor , // Each sample will then sample from full res according to reconstructed RT offset times its downsample factor
CurrentPixelOffset . Y * VolumetricReconstructRTDownsampleFactor / VolumetricReconstructRTDownsampleFactor ) ;
2020-06-23 18:40:00 -04:00
}
2021-05-25 02:43:26 -04:00
FUintVector4 FVolumetricRenderTargetViewStateData : : GetTracingCoordToFullResPixelCoordScaleBias ( ) const
{
// In this case, the source depth buffer full resolution depth buffer is the full resolution scene one
const uint32 CombinedDownsampleFactor = VolumetricReconstructRTDownsampleFactor * VolumetricTracingRTDownsampleFactor ;
return FUintVector4 ( CombinedDownsampleFactor , CombinedDownsampleFactor , // Scale is the combined downsample factor
CurrentPixelOffset . X * VolumetricReconstructRTDownsampleFactor , CurrentPixelOffset . Y * VolumetricReconstructRTDownsampleFactor ) ; // Each sample will then sample from full res according to reconstructed RT offset times its downsample factor
}
2020-06-23 18:40:00 -04:00
/*=============================================================================
FSceneRenderer implementation .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
2020-11-06 11:50:06 -04:00
void InitVolumetricRenderTargetForViews ( FRDGBuilder & GraphBuilder , TArrayView < FViewInfo > Views )
2020-06-23 18:40:00 -04:00
{
for ( int32 ViewIndex = 0 ; ViewIndex < Views . Num ( ) ; ViewIndex + + )
{
FViewInfo & ViewInfo = Views [ ViewIndex ] ;
2020-08-11 01:36:57 -04:00
if ( ! ShouldViewRenderVolumetricCloudRenderTarget ( ViewInfo ) )
2020-06-23 18:40:00 -04:00
{
continue ;
}
2020-08-11 01:36:57 -04:00
FVolumetricRenderTargetViewStateData & VolumetricCloudRT = ViewInfo . ViewState - > VolumetricCloudRenderTarget ;
2020-06-23 18:40:00 -04:00
FIntPoint ViewRect = ViewInfo . ViewRect . Size ( ) ;
2020-08-11 01:36:57 -04:00
VolumetricCloudRT . Initialise ( // TODO this is going to reallocate a buffer each time dynamic resolution scaling is applied
ViewRect ,
CVarVolumetricRenderTargetUvNoiseScale . GetValueOnAnyThread ( ) ,
CVarVolumetricRenderTargetMode . GetValueOnRenderThread ( ) ,
2020-10-29 13:38:15 -04:00
CVarVolumetricRenderTargetUpsamplingMode . GetValueOnAnyThread ( ) ) ;
2020-06-23 18:40:00 -04:00
2020-08-11 01:36:57 -04:00
FViewUniformShaderParameters ViewVolumetricCloudRTParameters = * ViewInfo . CachedViewUniformShaderParameters ;
2020-06-23 18:40:00 -04:00
{
2020-08-11 01:36:57 -04:00
const FIntPoint & VolumetricReconstructResolution = VolumetricCloudRT . GetCurrentVolumetricReconstructRTResolution ( ) ;
const FIntPoint & VolumetricTracingResolution = VolumetricCloudRT . GetCurrentVolumetricTracingRTResolution ( ) ;
const FIntPoint & CurrentPixelOffset = VolumetricCloudRT . GetCurrentTracingPixelOffset ( ) ;
const uint32 VolumetricReconstructRTDownSample = VolumetricCloudRT . GetVolumetricReconstructRTDownsampleFactor ( ) ;
const uint32 VolumetricTracingRTDownSample = VolumetricCloudRT . GetVolumetricTracingRTDownsampleFactor ( ) ;
2020-06-23 18:40:00 -04:00
// We jitter and reconstruct the volumetric view before TAA so we do not want any of its jitter.
// We do use TAA remove bilinear artifact at up sampling time.
FViewMatrices ViewMatrices = ViewInfo . ViewMatrices ;
ViewMatrices . HackRemoveTemporalAAProjectionJitter ( ) ;
float DownSampleFactor = float ( VolumetricReconstructRTDownSample * VolumetricTracingRTDownSample ) ;
// Offset to the correct half resolution pixel
FVector2D CenterCoord = FVector2D ( VolumetricReconstructRTDownSample / 2.0f ) ;
FVector2D TargetCoord = FVector2D ( CurrentPixelOffset ) + FVector2D ( 0.5f , 0.5f ) ;
FVector2D OffsetCoord = ( TargetCoord - CenterCoord ) * ( FVector2D ( - 2.0f , 2.0f ) / FVector2D ( VolumetricReconstructResolution ) ) ;
ViewMatrices . HackAddTemporalAAProjectionJitter ( OffsetCoord ) ;
ViewInfo . SetupViewRectUniformBufferParameters (
2020-08-11 01:36:57 -04:00
ViewVolumetricCloudRTParameters ,
2020-06-23 18:40:00 -04:00
VolumetricTracingResolution ,
FIntRect ( 0 , 0 , VolumetricTracingResolution . X , VolumetricTracingResolution . Y ) ,
ViewMatrices ,
ViewInfo . PrevViewInfo . ViewMatrices // This could also be changed if needed
) ;
}
2020-08-11 01:36:57 -04:00
ViewInfo . VolumetricRenderTargetViewUniformBuffer = TUniformBufferRef < FViewUniformShaderParameters > : : CreateUniformBufferImmediate ( ViewVolumetricCloudRTParameters , UniformBuffer_SingleFrame ) ;
2020-06-23 18:40:00 -04:00
}
}
//////////////////////////////////////////////////////////////////////////
class FReconstructVolumetricRenderTargetPS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER ( FReconstructVolumetricRenderTargetPS ) ;
SHADER_USE_PARAMETER_STRUCT ( FReconstructVolumetricRenderTargetPS , FGlobalShader ) ;
class FHistoryAvailable : SHADER_PERMUTATION_BOOL ( " PERMUTATION_HISTORY_AVAILABLE " ) ;
2021-03-31 08:32:53 -04:00
class FReprojectionBoxConstraint : SHADER_PERMUTATION_BOOL ( " PERMUTATION_REPROJECTION_BOX_CONSTRAINT " ) ;
using FPermutationDomain = TShaderPermutationDomain < FHistoryAvailable , FReprojectionBoxConstraint > ;
2020-06-23 18:40:00 -04:00
BEGIN_SHADER_PARAMETER_STRUCT ( FParameters , )
SHADER_PARAMETER_STRUCT_REF ( FViewUniformShaderParameters , ViewUniformBuffer )
SHADER_PARAMETER_RDG_TEXTURE ( Texture2D , TracingVolumetricTexture )
SHADER_PARAMETER_RDG_TEXTURE ( Texture2D , TracingVolumetricDepthTexture )
SHADER_PARAMETER_RDG_TEXTURE ( Texture2D , PreviousFrameVolumetricTexture )
SHADER_PARAMETER_RDG_TEXTURE ( Texture2D , PreviousFrameVolumetricDepthTexture )
2020-09-24 00:43:27 -04:00
SHADER_PARAMETER_RDG_TEXTURE ( Texture2D , HalfResDepthTexture )
2020-06-23 18:40:00 -04:00
SHADER_PARAMETER_SAMPLER ( SamplerState , LinearTextureSampler )
RENDER_TARGET_BINDING_SLOTS ( )
2021-09-22 10:01:48 -04:00
SHADER_PARAMETER ( FVector4f , DstVolumetricTextureSizeAndInvSize )
SHADER_PARAMETER ( FVector4f , PreviousVolumetricTextureSizeAndInvSize )
2020-06-23 18:40:00 -04:00
SHADER_PARAMETER ( FIntPoint , CurrentTracingPixelOffset )
2021-04-08 14:32:07 -04:00
SHADER_PARAMETER ( FIntPoint , ViewViewRectMin )
2020-06-23 18:40:00 -04:00
SHADER_PARAMETER ( int32 , DownSampleFactor )
SHADER_PARAMETER ( int32 , VolumetricRenderTargetMode )
SHADER_PARAMETER ( FUintVector4 , TracingVolumetricTextureValidCoordRect )
2021-09-22 10:01:48 -04:00
SHADER_PARAMETER ( FVector4f , TracingVolumetricTextureValidUvRect )
2020-06-23 18:40:00 -04:00
SHADER_PARAMETER ( FUintVector4 , PreviousFrameVolumetricTextureValidCoordRect )
2021-09-22 10:01:48 -04:00
SHADER_PARAMETER ( FVector4f , PreviousFrameVolumetricTextureValidUvRect )
2020-06-23 18:40:00 -04:00
SHADER_PARAMETER ( float , TemporalFactor )
END_SHADER_PARAMETER_STRUCT ( )
static FPermutationDomain RemapPermutation ( FPermutationDomain PermutationVector )
{
return PermutationVector ;
}
static bool ShouldCompilePermutation ( const FGlobalShaderPermutationParameters & Parameters )
{
return ShouldPipelineCompileVolumetricRenderTargetShaders ( Parameters . Platform ) ;
}
static void ModifyCompilationEnvironment ( const FGlobalShaderPermutationParameters & Parameters , FShaderCompilerEnvironment & OutEnvironment )
{
FGlobalShader : : ModifyCompilationEnvironment ( Parameters , OutEnvironment ) ;
OutEnvironment . SetDefine ( TEXT ( " SHADER_RECONSTRUCT_VOLUMETRICRT " ) , TEXT ( " 1 " ) ) ;
}
} ;
IMPLEMENT_GLOBAL_SHADER ( FReconstructVolumetricRenderTargetPS , " /Engine/Private/VolumetricRenderTarget.usf " , " ReconstructVolumetricRenderTargetPS " , SF_Pixel ) ;
//////////////////////////////////////////////////////////////////////////
2020-11-06 11:50:06 -04:00
void ReconstructVolumetricRenderTarget (
FRDGBuilder & GraphBuilder ,
TArrayView < FViewInfo > Views ,
FRDGTextureRef SceneDepthTexture ,
2020-12-11 14:21:20 -04:00
FRDGTextureRef HalfResolutionDepthCheckerboardMinMaxTexture ,
bool bWaitFinishFence )
2020-06-23 18:40:00 -04:00
{
2020-09-01 14:07:48 -04:00
if ( ! AnyViewRequiresProcessing ( Views ) )
2020-06-23 18:40:00 -04:00
{
return ;
}
2021-01-11 14:49:16 -04:00
const FRDGSystemTextures & SystemTextures = FRDGSystemTextures : : Get ( GraphBuilder ) ;
2020-09-24 00:43:27 -04:00
2020-06-23 18:40:00 -04:00
for ( int32 ViewIndex = 0 ; ViewIndex < Views . Num ( ) ; ViewIndex + + )
{
FViewInfo & ViewInfo = Views [ ViewIndex ] ;
2020-08-11 01:36:57 -04:00
if ( ! ShouldViewComposeVolumetricRenderTarget ( ViewInfo ) )
2020-06-23 18:40:00 -04:00
{
continue ;
}
2020-10-29 13:38:15 -04:00
2020-08-11 01:36:57 -04:00
FVolumetricRenderTargetViewStateData & VolumetricCloudRT = ViewInfo . ViewState - > VolumetricCloudRenderTarget ;
2020-06-23 18:40:00 -04:00
2020-08-11 01:36:57 -04:00
FRDGTextureRef DstVolumetric = VolumetricCloudRT . GetOrCreateDstVolumetricReconstructRT ( GraphBuilder ) ;
FRDGTextureRef DstVolumetricDepth = VolumetricCloudRT . GetOrCreateDstVolumetricReconstructRTDepth ( GraphBuilder ) ;
FRDGTextureRef SrcTracingVolumetric = VolumetricCloudRT . GetOrCreateVolumetricTracingRT ( GraphBuilder ) ;
FRDGTextureRef SrcTracingVolumetricDepth = VolumetricCloudRT . GetOrCreateVolumetricTracingRTDepth ( GraphBuilder ) ;
2021-01-11 14:49:16 -04:00
FRDGTextureRef PreviousFrameVolumetricTexture = VolumetricCloudRT . GetHistoryValid ( ) ? VolumetricCloudRT . GetOrCreateSrcVolumetricReconstructRT ( GraphBuilder ) : SystemTextures . Black ;
FRDGTextureRef PreviousFrameVolumetricDepthTexture = VolumetricCloudRT . GetHistoryValid ( ) ? VolumetricCloudRT . GetOrCreateSrcVolumetricReconstructRTDepth ( GraphBuilder ) : SystemTextures . Black ;
2020-06-23 18:40:00 -04:00
2020-08-11 01:36:57 -04:00
const uint32 TracingVolumetricCloudRTDownSample = VolumetricCloudRT . GetVolumetricTracingRTDownsampleFactor ( ) ;
2020-06-23 18:40:00 -04:00
FReconstructVolumetricRenderTargetPS : : FPermutationDomain PermutationVector ;
2020-08-11 01:36:57 -04:00
PermutationVector . Set < FReconstructVolumetricRenderTargetPS : : FHistoryAvailable > ( VolumetricCloudRT . GetHistoryValid ( ) ) ;
2021-03-31 08:32:53 -04:00
PermutationVector . Set < FReconstructVolumetricRenderTargetPS : : FReprojectionBoxConstraint > ( CVarVolumetricRenderTargetReprojectionBoxConstraint . GetValueOnAnyThread ( ) > 0 ) ;
2020-06-23 18:40:00 -04:00
TShaderMapRef < FReconstructVolumetricRenderTargetPS > PixelShader ( ViewInfo . ShaderMap , PermutationVector ) ;
FReconstructVolumetricRenderTargetPS : : FParameters * PassParameters = GraphBuilder . AllocParameters < FReconstructVolumetricRenderTargetPS : : FParameters > ( ) ;
2021-04-08 14:32:07 -04:00
PassParameters - > ViewUniformBuffer = ViewInfo . VolumetricRenderTargetViewUniformBuffer ; // Using a special uniform buffer because the view has some special resolution and no split screen offset.
2020-06-23 18:40:00 -04:00
PassParameters - > RenderTargets [ 0 ] = FRenderTargetBinding ( DstVolumetric , ERenderTargetLoadAction : : ENoAction ) ;
PassParameters - > RenderTargets [ 1 ] = FRenderTargetBinding ( DstVolumetricDepth , ERenderTargetLoadAction : : ENoAction ) ;
PassParameters - > TracingVolumetricTexture = SrcTracingVolumetric ;
PassParameters - > TracingVolumetricDepthTexture = SrcTracingVolumetricDepth ;
PassParameters - > PreviousFrameVolumetricTexture = PreviousFrameVolumetricTexture ;
PassParameters - > PreviousFrameVolumetricDepthTexture = PreviousFrameVolumetricDepthTexture ;
PassParameters - > LinearTextureSampler = TStaticSamplerState < SF_Bilinear > : : GetRHI ( ) ;
2020-08-11 01:36:57 -04:00
PassParameters - > CurrentTracingPixelOffset = VolumetricCloudRT . GetCurrentTracingPixelOffset ( ) ;
2021-04-08 14:32:07 -04:00
PassParameters - > ViewViewRectMin = ViewInfo . ViewRect . Min / GetMainDownsampleFactor ( VolumetricCloudRT . GetMode ( ) ) ; // because we use the special VolumetricRenderTargetViewUniformBuffer, we have to specify View.RectMin separately.
2020-08-11 01:36:57 -04:00
PassParameters - > DownSampleFactor = TracingVolumetricCloudRTDownSample ;
PassParameters - > VolumetricRenderTargetMode = VolumetricCloudRT . GetMode ( ) ;
2020-12-11 14:21:20 -04:00
PassParameters - > HalfResDepthTexture = ( VolumetricCloudRT . GetMode ( ) = = 0 | | VolumetricCloudRT . GetMode ( ) = = 3 ) ? HalfResolutionDepthCheckerboardMinMaxTexture : SceneDepthTexture ;
2021-05-11 01:10:20 -04:00
const bool bVisualizeConservativeDensityOrDebugSampleCount = ShouldViewVisualizeVolumetricCloudConservativeDensity ( ViewInfo , ViewInfo . Family - > EngineShowFlags ) | | GetVolumetricCloudDebugSampleCountMode ( ViewInfo . Family - > EngineShowFlags ) > 0 ; ;
PassParameters - > HalfResDepthTexture = bVisualizeConservativeDensityOrDebugSampleCount ?
2021-01-11 14:49:16 -04:00
( ( bool ) ERHIZBuffer : : IsInverted ? SystemTextures . Black : SystemTextures . White ) :
2020-12-11 14:21:20 -04:00
( ( VolumetricCloudRT . GetMode ( ) = = 0 | | VolumetricCloudRT . GetMode ( ) = = 3 ) ?
HalfResolutionDepthCheckerboardMinMaxTexture :
2021-01-11 14:49:16 -04:00
SceneDepthTexture ) ;
2020-09-24 00:43:27 -04:00
2020-06-23 18:40:00 -04:00
GetTextureSafeUvCoordBound ( SrcTracingVolumetric , PassParameters - > TracingVolumetricTextureValidCoordRect , PassParameters - > TracingVolumetricTextureValidUvRect ) ;
GetTextureSafeUvCoordBound ( PreviousFrameVolumetricTexture , PassParameters - > PreviousFrameVolumetricTextureValidCoordRect , PassParameters - > PreviousFrameVolumetricTextureValidUvRect ) ;
FIntVector DstVolumetricSize = DstVolumetric - > Desc . GetSize ( ) ;
FVector2D DstVolumetricTextureSize = FVector2D ( float ( DstVolumetricSize . X ) , float ( DstVolumetricSize . Y ) ) ;
FVector2D PreviousVolumetricTextureSize = FVector2D ( float ( PreviousFrameVolumetricTexture - > Desc . GetSize ( ) . X ) , float ( PreviousFrameVolumetricTexture - > Desc . GetSize ( ) . Y ) ) ;
2021-09-22 10:01:48 -04:00
PassParameters - > DstVolumetricTextureSizeAndInvSize = FVector4f ( DstVolumetricTextureSize . X , DstVolumetricTextureSize . Y , 1.0f / DstVolumetricTextureSize . X , 1.0f / DstVolumetricTextureSize . Y ) ;
PassParameters - > PreviousVolumetricTextureSizeAndInvSize = FVector4f ( PreviousVolumetricTextureSize . X , PreviousVolumetricTextureSize . Y , 1.0f / PreviousVolumetricTextureSize . X , 1.0f / PreviousVolumetricTextureSize . Y ) ;
2020-06-23 18:40:00 -04:00
FPixelShaderUtils : : AddFullscreenPass < FReconstructVolumetricRenderTargetPS > (
2020-12-11 14:21:20 -04:00
GraphBuilder , ViewInfo . ShaderMap , RDG_EVENT_NAME ( " VolumetricReconstruct " ) , PixelShader , PassParameters ,
2020-06-23 18:40:00 -04:00
FIntRect ( 0 , 0 , DstVolumetricSize . X , DstVolumetricSize . Y ) ) ;
}
}
//////////////////////////////////////////////////////////////////////////
class FComposeVolumetricRTOverScenePS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER ( FComposeVolumetricRTOverScenePS ) ;
SHADER_USE_PARAMETER_STRUCT ( FComposeVolumetricRTOverScenePS , FGlobalShader ) ;
2020-09-24 00:43:27 -04:00
class FUpsamplingMode : SHADER_PERMUTATION_RANGE_INT ( " PERMUTATION_UPSAMPLINGMODE " , 0 , 5 ) ;
class FRenderUnderWaterBuffer : SHADER_PERMUTATION_BOOL ( " PERMUTATION_RENDER_UNDERWATER_BUFFER " ) ; // Render into the water scene color buffer (used when rendering from water system)
class FRenderCameraUnderWater : SHADER_PERMUTATION_BOOL ( " PERMUTATION_RENDER_CAMERA_UNDERWATER " ) ; // When water us used and the camera is under water, use that permutation (to handle camera intersection with water and double cloud composition)
2021-10-12 21:21:22 -04:00
class FMSAASampleCount : SHADER_PERMUTATION_SPARSE_INT ( " MSAA_SAMPLE_COUNT " , 1 , 2 , 4 , 8 ) ;
using FPermutationDomain = TShaderPermutationDomain < FUpsamplingMode , FRenderUnderWaterBuffer , FRenderCameraUnderWater , FMSAASampleCount > ;
2020-06-23 18:40:00 -04:00
BEGIN_SHADER_PARAMETER_STRUCT ( FParameters , )
SHADER_PARAMETER_STRUCT_REF ( FViewUniformShaderParameters , ViewUniformBuffer )
SHADER_PARAMETER_RDG_TEXTURE ( Texture2D , VolumetricTexture )
SHADER_PARAMETER_RDG_TEXTURE ( Texture2D , VolumetricDepthTexture )
2020-09-01 14:07:48 -04:00
SHADER_PARAMETER_RDG_TEXTURE ( Texture2D , WaterLinearDepthTexture )
2021-10-12 21:21:22 -04:00
SHADER_PARAMETER_RDG_TEXTURE ( Texture2DMS < float > , MSAADepthTexture )
2020-06-23 18:40:00 -04:00
SHADER_PARAMETER_SAMPLER ( SamplerState , LinearTextureSampler )
2022-05-17 09:42:32 -04:00
SHADER_PARAMETER_SAMPLER ( SamplerState , WaterLinearDepthSampler )
2020-06-23 18:40:00 -04:00
RENDER_TARGET_BINDING_SLOTS ( )
SHADER_PARAMETER ( float , UvOffsetScale )
2021-04-09 10:12:51 -04:00
SHADER_PARAMETER ( float , UvOffsetSampleAcceptanceWeight )
2021-09-22 10:01:48 -04:00
SHADER_PARAMETER ( FVector4f , VolumetricTextureSizeAndInvSize )
2021-11-18 14:37:34 -05:00
SHADER_PARAMETER ( FVector2f , FullResolutionToVolumetricBufferResolutionScale )
SHADER_PARAMETER ( FVector2f , FullResolutionToWaterBufferScale )
2021-09-22 10:01:48 -04:00
SHADER_PARAMETER ( FVector4f , SceneWithoutSingleLayerWaterViewRect )
2020-06-23 18:40:00 -04:00
SHADER_PARAMETER ( FUintVector4 , VolumetricTextureValidCoordRect )
2021-09-22 10:01:48 -04:00
SHADER_PARAMETER ( FVector4f , VolumetricTextureValidUvRect )
2021-04-08 14:32:07 -04:00
SHADER_PARAMETER_RDG_UNIFORM_BUFFER ( FSceneTextureUniformParameters , SceneTextures )
2020-06-23 18:40:00 -04:00
END_SHADER_PARAMETER_STRUCT ( )
2020-09-24 00:43:27 -04:00
static FPermutationDomain RemapPermutation ( FPermutationDomain PermutationVector )
2020-06-23 18:40:00 -04:00
{
return PermutationVector ;
}
static bool ShouldCompilePermutation ( const FGlobalShaderPermutationParameters & Parameters )
{
2021-10-12 21:21:22 -04:00
FPermutationDomain PermutationVector ( Parameters . PermutationId ) ;
if ( ( ! IsAnyForwardShadingEnabled ( Parameters . Platform ) | | ! RHISupportsMSAA ( Parameters . Platform ) ) & & PermutationVector . Get < FMSAASampleCount > ( ) > 1 )
{
// We only compile the MSAA support when Forward shading is enabled because MSAA can only be used in this case.
return false ;
}
2020-06-23 18:40:00 -04:00
return ShouldPipelineCompileVolumetricRenderTargetShaders ( Parameters . Platform ) ;
}
static void ModifyCompilationEnvironment ( const FGlobalShaderPermutationParameters & Parameters , FShaderCompilerEnvironment & OutEnvironment )
{
FGlobalShader : : ModifyCompilationEnvironment ( Parameters , OutEnvironment ) ;
OutEnvironment . SetDefine ( TEXT ( " SHADER_COMPOSE_VOLUMETRICRT " ) , TEXT ( " 1 " ) ) ;
}
} ;
IMPLEMENT_GLOBAL_SHADER ( FComposeVolumetricRTOverScenePS , " /Engine/Private/VolumetricRenderTarget.usf " , " ComposeVolumetricRTOverScenePS " , SF_Pixel ) ;
//////////////////////////////////////////////////////////////////////////
2020-11-06 11:50:06 -04:00
void ComposeVolumetricRenderTargetOverScene (
FRDGBuilder & GraphBuilder ,
TArrayView < FViewInfo > Views ,
FRDGTextureRef SceneColorTexture ,
2021-10-12 21:21:22 -04:00
FRDGTextureRef SceneDepthTexture ,
2020-11-06 11:50:06 -04:00
bool bShouldRenderSingleLayerWater ,
2021-04-08 14:32:07 -04:00
const FSceneWithoutWaterTextures & WaterPassData ,
const FMinimalSceneTextures & SceneTextures )
2020-06-23 18:40:00 -04:00
{
2020-09-01 14:07:48 -04:00
if ( ! AnyViewRequiresProcessing ( Views ) )
{
return ;
}
2020-06-23 18:40:00 -04:00
FRHIBlendState * PreMultipliedColorTransmittanceBlend = TStaticBlendState < CW_RGB , BO_Add , BF_One , BF_SourceAlpha , BO_Add , BF_Zero , BF_One > : : GetRHI ( ) ;
for ( int32 ViewIndex = 0 ; ViewIndex < Views . Num ( ) ; ViewIndex + + )
{
FViewInfo & ViewInfo = Views [ ViewIndex ] ;
2020-08-11 01:36:57 -04:00
if ( ! ShouldViewRenderVolumetricCloudRenderTarget ( ViewInfo ) )
2020-06-23 18:40:00 -04:00
{
continue ;
}
2020-08-11 01:36:57 -04:00
FVolumetricRenderTargetViewStateData & VolumetricCloudRT = ViewInfo . ViewState - > VolumetricCloudRenderTarget ;
FRDGTextureRef VolumetricTexture = VolumetricCloudRT . GetOrCreateDstVolumetricReconstructRT ( GraphBuilder ) ;
FRDGTextureRef VolumetricDepthTexture = VolumetricCloudRT . GetOrCreateDstVolumetricReconstructRTDepth ( GraphBuilder ) ;
2020-06-23 18:40:00 -04:00
// When reconstructed and back buffer resolution matches, force using a pixel perfect upsampling.
2020-08-11 01:36:57 -04:00
const uint32 VRTMode = VolumetricCloudRT . GetMode ( ) ;
int UpsamplingMode = VolumetricCloudRT . GetUpsamplingMode ( ) ;
2020-06-23 18:40:00 -04:00
UpsamplingMode = UpsamplingMode = = 3 & & ( VRTMode = = 1 | | VRTMode = = 2 ) ? 2 : UpsamplingMode ;
2021-10-12 21:21:22 -04:00
// We only support MSAA up to 8 sample and in forward
check ( SceneDepthTexture - > Desc . NumSamples < = 8 ) ;
// We only support MSAA in forward, not in deferred.
const bool bForwardShading = IsForwardShadingEnabled ( ViewInfo . GetShaderPlatform ( ) ) ;
check ( bForwardShading | | ( ! bForwardShading & & SceneDepthTexture - > Desc . NumSamples = = 1 ) ) ;
2020-09-01 14:07:48 -04:00
FComposeVolumetricRTOverScenePS : : FPermutationDomain PermutationVector ;
2020-06-23 18:40:00 -04:00
PermutationVector . Set < FComposeVolumetricRTOverScenePS : : FUpsamplingMode > ( UpsamplingMode ) ;
2020-09-24 00:43:27 -04:00
PermutationVector . Set < FComposeVolumetricRTOverScenePS : : FRenderUnderWaterBuffer > ( 0 ) ;
PermutationVector . Set < FComposeVolumetricRTOverScenePS : : FRenderCameraUnderWater > ( ( bShouldRenderSingleLayerWater & & ViewInfo . IsUnderwater ( ) ) ? 1 : 0 ) ;
2021-10-12 21:21:22 -04:00
PermutationVector . Set < FComposeVolumetricRTOverScenePS : : FMSAASampleCount > ( SceneDepthTexture - > Desc . NumSamples ) ;
2020-06-23 18:40:00 -04:00
TShaderMapRef < FComposeVolumetricRTOverScenePS > PixelShader ( ViewInfo . ShaderMap , PermutationVector ) ;
FComposeVolumetricRTOverScenePS : : FParameters * PassParameters = GraphBuilder . AllocParameters < FComposeVolumetricRTOverScenePS : : FParameters > ( ) ;
PassParameters - > ViewUniformBuffer = ViewInfo . ViewUniformBuffer ;
2020-09-24 00:43:27 -04:00
PassParameters - > RenderTargets [ 0 ] = FRenderTargetBinding ( SceneColorTexture , ERenderTargetLoadAction : : ELoad ) ;
2021-10-12 21:21:22 -04:00
PassParameters - > MSAADepthTexture = SceneDepthTexture ;
2020-06-23 18:40:00 -04:00
PassParameters - > VolumetricTexture = VolumetricTexture ;
PassParameters - > VolumetricDepthTexture = VolumetricDepthTexture ;
PassParameters - > LinearTextureSampler = TStaticSamplerState < SF_Bilinear > : : GetRHI ( ) ;
2020-08-11 01:36:57 -04:00
PassParameters - > UvOffsetScale = VolumetricCloudRT . GetUvNoiseScale ( ) ;
2021-04-09 10:12:51 -04:00
PassParameters - > UvOffsetSampleAcceptanceWeight = GetUvNoiseSampleAcceptanceWeight ( ) ;
2022-02-02 01:43:41 -05:00
PassParameters - > FullResolutionToVolumetricBufferResolutionScale = FVector2f ( 1.0f / float ( GetMainDownsampleFactor ( VRTMode ) ) , float ( GetMainDownsampleFactor ( VRTMode ) ) ) ;
2021-04-08 14:32:07 -04:00
PassParameters - > SceneTextures = SceneTextures . UniformBuffer ;
2020-06-23 18:40:00 -04:00
GetTextureSafeUvCoordBound ( PassParameters - > VolumetricTexture , PassParameters - > VolumetricTextureValidCoordRect , PassParameters - > VolumetricTextureValidUvRect ) ;
2020-09-24 00:43:27 -04:00
PassParameters - > WaterLinearDepthTexture = WaterPassData . DepthTexture ;
2022-05-17 09:42:32 -04:00
PassParameters - > WaterLinearDepthSampler = TStaticSamplerState < SF_Point > : : GetRHI ( ) ;
2020-09-24 00:43:27 -04:00
if ( bShouldRenderSingleLayerWater )
{
const FSceneWithoutWaterTextures : : FView & WaterPassViewData = WaterPassData . Views [ ViewIndex ] ;
2022-02-02 01:43:41 -05:00
PassParameters - > FullResolutionToWaterBufferScale = FVector2f ( 1.0f / WaterPassData . RefractionDownsampleFactor , WaterPassData . RefractionDownsampleFactor ) ;
2021-09-22 10:01:48 -04:00
PassParameters - > SceneWithoutSingleLayerWaterViewRect = FVector4f ( WaterPassViewData . ViewRect . Min . X , WaterPassViewData . ViewRect . Min . Y ,
2020-09-24 00:43:27 -04:00
WaterPassViewData . ViewRect . Max . X , WaterPassViewData . ViewRect . Max . Y ) ;
}
2020-06-23 18:40:00 -04:00
FVector2D VolumetricTextureSize = FVector2D ( float ( VolumetricTexture - > Desc . GetSize ( ) . X ) , float ( VolumetricTexture - > Desc . GetSize ( ) . Y ) ) ;
2021-09-22 10:01:48 -04:00
PassParameters - > VolumetricTextureSizeAndInvSize = FVector4f ( VolumetricTextureSize . X , VolumetricTextureSize . Y , 1.0f / VolumetricTextureSize . X , 1.0f / VolumetricTextureSize . Y ) ;
2020-06-23 18:40:00 -04:00
FPixelShaderUtils : : AddFullscreenPass < FComposeVolumetricRTOverScenePS > (
GraphBuilder , ViewInfo . ShaderMap , RDG_EVENT_NAME ( " VolumetricComposeOverScene " ) , PixelShader , PassParameters , ViewInfo . ViewRect ,
PreMultipliedColorTransmittanceBlend ) ;
}
}
2020-09-01 14:07:48 -04:00
//////////////////////////////////////////////////////////////////////////
2020-11-06 11:50:06 -04:00
void ComposeVolumetricRenderTargetOverSceneUnderWater (
FRDGBuilder & GraphBuilder ,
TArrayView < FViewInfo > Views ,
2021-04-08 14:32:07 -04:00
const FSceneWithoutWaterTextures & WaterPassData ,
const FMinimalSceneTextures & SceneTextures )
2020-09-01 14:07:48 -04:00
{
if ( ! AnyViewRequiresProcessing ( Views ) )
{
return ;
}
FRHIBlendState * PreMultipliedColorTransmittanceBlend = TStaticBlendState < CW_RGB , BO_Add , BF_One , BF_SourceAlpha , BO_Add , BF_Zero , BF_One > : : GetRHI ( ) ;
for ( int32 ViewIndex = 0 ; ViewIndex < Views . Num ( ) ; ViewIndex + + )
{
FViewInfo & ViewInfo = Views [ ViewIndex ] ;
if ( ! ShouldViewRenderVolumetricCloudRenderTarget ( ViewInfo ) )
{
continue ;
}
FVolumetricRenderTargetViewStateData & VolumetricCloudRT = ViewInfo . ViewState - > VolumetricCloudRenderTarget ;
FRDGTextureRef VolumetricTexture = VolumetricCloudRT . GetOrCreateDstVolumetricReconstructRT ( GraphBuilder ) ;
FRDGTextureRef VolumetricDepthTexture = VolumetricCloudRT . GetOrCreateDstVolumetricReconstructRTDepth ( GraphBuilder ) ;
2020-09-24 00:43:27 -04:00
const FSceneWithoutWaterTextures : : FView & WaterPassViewData = WaterPassData . Views [ ViewIndex ] ;
2020-09-01 14:07:48 -04:00
// When reconstructed and back buffer resolution matches, force using a pixel perfect upsampling.
const uint32 VRTMode = VolumetricCloudRT . GetMode ( ) ;
int UpsamplingMode = VolumetricCloudRT . GetUpsamplingMode ( ) ;
UpsamplingMode = UpsamplingMode = = 3 & & ( VRTMode = = 1 | | VRTMode = = 2 ) ? 2 : UpsamplingMode ;
FComposeVolumetricRTOverScenePS : : FPermutationDomain PermutationVector ;
PermutationVector . Set < FComposeVolumetricRTOverScenePS : : FUpsamplingMode > ( UpsamplingMode ) ;
2020-09-24 00:43:27 -04:00
PermutationVector . Set < FComposeVolumetricRTOverScenePS : : FRenderUnderWaterBuffer > ( 1 ) ;
PermutationVector . Set < FComposeVolumetricRTOverScenePS : : FRenderCameraUnderWater > ( 0 ) ;
2021-10-12 21:21:22 -04:00
PermutationVector . Set < FComposeVolumetricRTOverScenePS : : FMSAASampleCount > ( 1 ) ;
2020-09-01 14:07:48 -04:00
TShaderMapRef < FComposeVolumetricRTOverScenePS > PixelShader ( ViewInfo . ShaderMap , PermutationVector ) ;
FComposeVolumetricRTOverScenePS : : FParameters * PassParameters = GraphBuilder . AllocParameters < FComposeVolumetricRTOverScenePS : : FParameters > ( ) ;
PassParameters - > ViewUniformBuffer = ViewInfo . ViewUniformBuffer ;
2020-09-24 00:43:27 -04:00
PassParameters - > RenderTargets [ 0 ] = FRenderTargetBinding ( WaterPassData . ColorTexture , ERenderTargetLoadAction : : ELoad ) ;
2020-09-01 14:07:48 -04:00
PassParameters - > VolumetricTexture = VolumetricTexture ;
PassParameters - > VolumetricDepthTexture = VolumetricDepthTexture ;
2020-09-24 00:43:27 -04:00
PassParameters - > WaterLinearDepthTexture = WaterPassData . DepthTexture ;
2020-09-01 14:07:48 -04:00
PassParameters - > LinearTextureSampler = TStaticSamplerState < SF_Bilinear > : : GetRHI ( ) ;
2022-05-17 09:42:32 -04:00
PassParameters - > WaterLinearDepthSampler = TStaticSamplerState < SF_Point > : : GetRHI ( ) ;
2020-09-01 14:07:48 -04:00
PassParameters - > UvOffsetScale = VolumetricCloudRT . GetUvNoiseScale ( ) ;
2021-04-09 10:12:51 -04:00
PassParameters - > UvOffsetSampleAcceptanceWeight = GetUvNoiseSampleAcceptanceWeight ( ) ;
2022-02-02 01:43:41 -05:00
PassParameters - > FullResolutionToVolumetricBufferResolutionScale = FVector2f ( 1.0f / float ( GetMainDownsampleFactor ( VRTMode ) ) , float ( GetMainDownsampleFactor ( VRTMode ) ) ) ;
PassParameters - > FullResolutionToWaterBufferScale = FVector2f ( 1.0f / WaterPassData . RefractionDownsampleFactor , WaterPassData . RefractionDownsampleFactor ) ;
2021-09-22 10:01:48 -04:00
PassParameters - > SceneWithoutSingleLayerWaterViewRect = FVector4f ( WaterPassViewData . ViewRect . Min . X , WaterPassViewData . ViewRect . Min . Y ,
2020-09-24 00:43:27 -04:00
WaterPassViewData . ViewRect . Max . X , WaterPassViewData . ViewRect . Max . Y ) ;
2021-04-08 14:32:07 -04:00
PassParameters - > SceneTextures = SceneTextures . UniformBuffer ;
2020-09-01 14:07:48 -04:00
GetTextureSafeUvCoordBound ( PassParameters - > VolumetricTexture , PassParameters - > VolumetricTextureValidCoordRect , PassParameters - > VolumetricTextureValidUvRect ) ;
FVector2D VolumetricTextureSize = FVector2D ( float ( VolumetricTexture - > Desc . GetSize ( ) . X ) , float ( VolumetricTexture - > Desc . GetSize ( ) . Y ) ) ;
2021-09-22 10:01:48 -04:00
PassParameters - > VolumetricTextureSizeAndInvSize = FVector4f ( VolumetricTextureSize . X , VolumetricTextureSize . Y , 1.0f / VolumetricTextureSize . X , 1.0f / VolumetricTextureSize . Y ) ;
2020-09-01 14:07:48 -04:00
FPixelShaderUtils : : AddFullscreenPass < FComposeVolumetricRTOverScenePS > (
2022-03-29 07:57:48 -04:00
GraphBuilder , ViewInfo . ShaderMap , RDG_EVENT_NAME ( " SLW::VolumetricComposeOverScene " ) , PixelShader , PassParameters , WaterPassViewData . ViewRect ,
2020-09-01 14:07:48 -04:00
PreMultipliedColorTransmittanceBlend ) ;
}
}
//////////////////////////////////////////////////////////////////////////
2020-12-11 14:21:20 -04:00
void ComposeVolumetricRenderTargetOverSceneForVisualization (
FRDGBuilder & GraphBuilder ,
TArrayView < FViewInfo > Views ,
2021-04-08 14:32:07 -04:00
FRDGTextureRef SceneColorTexture ,
const FMinimalSceneTextures & SceneTextures )
2020-12-11 14:21:20 -04:00
{
if ( ! AnyViewRequiresProcessing ( Views ) )
{
return ;
}
for ( int32 ViewIndex = 0 ; ViewIndex < Views . Num ( ) ; ViewIndex + + )
{
FViewInfo & ViewInfo = Views [ ViewIndex ] ;
if ( ! ShouldViewRenderVolumetricCloudRenderTarget ( ViewInfo ) )
{
continue ;
}
FVolumetricRenderTargetViewStateData & VolumetricCloudRT = ViewInfo . ViewState - > VolumetricCloudRenderTarget ;
FRDGTextureRef VolumetricTexture = VolumetricCloudRT . GetOrCreateDstVolumetricReconstructRT ( GraphBuilder ) ;
FRDGTextureRef VolumetricDepthTexture = VolumetricCloudRT . GetOrCreateDstVolumetricReconstructRTDepth ( GraphBuilder ) ;
// When reconstructed and back buffer resolution matches, force using a pixel perfect upsampling.
const uint32 VRTMode = VolumetricCloudRT . GetMode ( ) ;
FComposeVolumetricRTOverScenePS : : FPermutationDomain PermutationVector ;
PermutationVector . Set < FComposeVolumetricRTOverScenePS : : FUpsamplingMode > ( 0 ) ;
PermutationVector . Set < FComposeVolumetricRTOverScenePS : : FRenderUnderWaterBuffer > ( 0 ) ;
PermutationVector . Set < FComposeVolumetricRTOverScenePS : : FRenderCameraUnderWater > ( 0 ) ;
2021-10-12 21:21:22 -04:00
PermutationVector . Set < FComposeVolumetricRTOverScenePS : : FMSAASampleCount > ( 1 ) ;
2020-12-11 14:21:20 -04:00
TShaderMapRef < FComposeVolumetricRTOverScenePS > PixelShader ( ViewInfo . ShaderMap , PermutationVector ) ;
FComposeVolumetricRTOverScenePS : : FParameters * PassParameters = GraphBuilder . AllocParameters < FComposeVolumetricRTOverScenePS : : FParameters > ( ) ;
PassParameters - > ViewUniformBuffer = ViewInfo . ViewUniformBuffer ;
PassParameters - > RenderTargets [ 0 ] = FRenderTargetBinding ( SceneColorTexture , ERenderTargetLoadAction : : ELoad ) ;
PassParameters - > VolumetricTexture = VolumetricTexture ;
PassParameters - > VolumetricDepthTexture = VolumetricDepthTexture ;
PassParameters - > LinearTextureSampler = TStaticSamplerState < SF_Bilinear > : : GetRHI ( ) ;
PassParameters - > UvOffsetScale = VolumetricCloudRT . GetUvNoiseScale ( ) ;
2021-04-09 10:12:51 -04:00
PassParameters - > UvOffsetSampleAcceptanceWeight = GetUvNoiseSampleAcceptanceWeight ( ) ;
2022-02-02 01:43:41 -05:00
PassParameters - > FullResolutionToVolumetricBufferResolutionScale = FVector2f ( 1.0f / float ( GetMainDownsampleFactor ( VRTMode ) ) , float ( GetMainDownsampleFactor ( VRTMode ) ) ) ;
2021-04-08 14:32:07 -04:00
PassParameters - > SceneTextures = SceneTextures . UniformBuffer ;
2020-12-11 14:21:20 -04:00
GetTextureSafeUvCoordBound ( PassParameters - > VolumetricTexture , PassParameters - > VolumetricTextureValidCoordRect , PassParameters - > VolumetricTextureValidUvRect ) ;
PassParameters - > WaterLinearDepthTexture = GSystemTextures . GetBlackDummy ( GraphBuilder ) ;
FVector2D VolumetricTextureSize = FVector2D ( float ( VolumetricTexture - > Desc . GetSize ( ) . X ) , float ( VolumetricTexture - > Desc . GetSize ( ) . Y ) ) ;
2021-09-22 10:01:48 -04:00
PassParameters - > VolumetricTextureSizeAndInvSize = FVector4f ( VolumetricTextureSize . X , VolumetricTextureSize . Y , 1.0f / VolumetricTextureSize . X , 1.0f / VolumetricTextureSize . Y ) ;
2020-12-11 14:21:20 -04:00
FPixelShaderUtils : : AddFullscreenPass < FComposeVolumetricRTOverScenePS > (
GraphBuilder , ViewInfo . ShaderMap , RDG_EVENT_NAME ( " VolumetricComposeOverSceneForVisualization " ) , PixelShader , PassParameters , ViewInfo . ViewRect ) ;
}
}
//////////////////////////////////////////////////////////////////////////
2020-09-01 14:07:48 -04:00
2020-06-23 18:40:00 -04:00
2020-09-24 00:43:27 -04:00
FTemporalRenderTargetState : : FTemporalRenderTargetState ( )
: CurrentRT ( 1 )
, FrameId ( 0 )
, bFirstTimeUsed ( true )
, bHistoryValid ( false )
, Resolution ( FIntPoint : : ZeroValue )
, Format ( PF_MAX )
{
}
FTemporalRenderTargetState : : ~ FTemporalRenderTargetState ( )
{
}
2020-11-24 18:42:39 -04:00
void FTemporalRenderTargetState : : Initialise ( const FIntPoint & ResolutionIn , EPixelFormat FormatIn )
2020-09-24 00:43:27 -04:00
{
// Update internal settings
if ( bFirstTimeUsed )
{
bFirstTimeUsed = false ;
bHistoryValid = false ;
FrameId = 0 ;
}
CurrentRT = 1 - CurrentRT ;
const uint32 PreviousRT = 1 - CurrentRT ;
FIntVector ResolutionVector = FIntVector ( ResolutionIn . X , ResolutionIn . Y , 0 ) ;
for ( int32 i = 0 ; i < kRenderTargetCount ; + + i )
{
if ( RenderTargets [ i ] . IsValid ( ) & & ( RenderTargets [ i ] - > GetDesc ( ) . GetSize ( ) ! = ResolutionVector | | Format ! = FormatIn ) )
{
// Resolution does not match so release target we are going to render in, keep the previous one at a different resolution.
RenderTargets [ i ] . SafeRelease ( ) ;
}
}
Resolution = ResolutionIn ;
Format = FormatIn ;
// Regular every frame update
bHistoryValid = RenderTargets [ PreviousRT ] . IsValid ( ) ;
}
FRDGTextureRef FTemporalRenderTargetState : : GetOrCreateCurrentRT ( FRDGBuilder & GraphBuilder )
{
check ( Resolution . X > 0 & & Resolution . Y > 0 ) ;
if ( RenderTargets [ CurrentRT ] . IsValid ( ) )
{
return GraphBuilder . RegisterExternalTexture ( RenderTargets [ CurrentRT ] ) ;
}
FRDGTextureRef RDGTexture = GraphBuilder . CreateTexture (
FRDGTextureDesc : : Create2D ( Resolution , Format , FClearValueBinding ( FLinearColor ( 0.0f , 0.0f , 0.0f , 1.0f ) ) ,
2021-02-02 05:19:56 -04:00
TexCreate_ShaderResource | TexCreate_UAV | TexCreate_RenderTargetable ) , TEXT ( " VolumetricRenderTarget.GeneralTemporalTexture " ) ) ;
2020-09-24 00:43:27 -04:00
return RDGTexture ;
}
void FTemporalRenderTargetState : : ExtractCurrentRT ( FRDGBuilder & GraphBuilder , FRDGTextureRef RDGTexture )
{
check ( Resolution . X > 0 & & Resolution . Y > 0 ) ;
2021-04-06 11:45:09 -04:00
RenderTargets [ CurrentRT ] = GraphBuilder . ConvertToExternalTexture ( RDGTexture ) ;
2020-09-24 00:43:27 -04:00
}
FRDGTextureRef FTemporalRenderTargetState : : GetOrCreatePreviousRT ( FRDGBuilder & GraphBuilder )
{
check ( Resolution . X > 0 & & Resolution . Y > 0 ) ;
const uint32 PreviousRT = 1u - CurrentRT ;
check ( RenderTargets [ PreviousRT ] . IsValid ( ) ) ;
return GraphBuilder . RegisterExternalTexture ( RenderTargets [ PreviousRT ] ) ;
}
void FTemporalRenderTargetState : : Reset ( )
{
bFirstTimeUsed = false ;
bHistoryValid = false ;
FrameId = 0 ;
for ( int32 i = 0 ; i < kRenderTargetCount ; + + i )
{
RenderTargets [ i ] . SafeRelease ( ) ;
}
Resolution = FIntPoint : : ZeroValue ;
Format = PF_MAX ;
}