You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#lockdown nick.penwarden ========================== MAJOR FEATURES + CHANGES ========================== Change 2967522 on 2016/05/05 by Martin.Mittring fixed UE-30208 Ensure taking high resolution screenshot renamed cvar from r.SaveUncompressedEXRFrame to r.SaveEXR.CompressionQuality and change meaning Change 2967541 on 2016/05/05 by Martin.Mittring added cvar help entry to the editor menu Change 2967544 on 2016/05/05 by Martin.Mittring * added ensures to track down UE-22073 [CrashReport] Crash when changing Editor Window Size - FDeferredShadingSceneRenderer::ClearTranslucentVolumeLighting() * fixed typo * improved r.DisplayInternals Change 2967685 on 2016/05/05 by Rolando.Caloca DR - Fix 2013 compile #jira UE-30369 Change 2967883 on 2016/05/05 by Olaf.Piesche Making inherit rotation work for mesh particles #jira UE-30153 Change 2967948 on 2016/05/05 by Daniel.Wright MaterialParameterCollections now create default resources (uniform buffers) which are used when no valid FScene is present (eg DrawTile while exporting materials to lightmass) Change 2967954 on 2016/05/05 by Daniel.Wright New refraction mode 'Pixel Normal Offset', which uses the difference between the per-pixel normal and the per-vertex normal to compute the refraction offset. This is useful for refraction from large water surfaces without reading outside of screen bounds as much. Change 2967970 on 2016/05/05 by Olaf.Piesche Improvement for depth buffer collision; reduce tunneling by sampling midpoint instead of predicted position. #jira UE-27297 Change 2968125 on 2016/05/05 by Daniel.Wright Hopeful fix for mac compile error with enum Change 2968126 on 2016/05/05 by Daniel.Wright Forward declare to fix compile error Change 2969070 on 2016/05/06 by Martin.Mittring fixed Clang Compile error Change 2969224 on 2016/05/06 by Martin.Mittring fixed Clang Change 2969275 on 2016/05/06 by Rolando.Caloca DR - Fix for simulation time from BP not matching material editor expression time #jira UE-26431 Change 2969413 on 2016/05/06 by Daniel.Wright Simple forward shading path * Support for a directional light in the base pass, which can be shadowed either by distance field shadowmaps or a single shadow factor from the Indirect Lighting Cache * Binding and outputting to GBuffers is disabled when using simple forward shading, along with dependencies of the GBuffers * Specular, normal maps and the 3rd SH band of skylighting are all hardcoded off. Materials are forced fully rough. * Enabled with 'r.SimpleForwardShading 1', which can be changed at runtime * Added r.SupportSimpleForwardShading, which determines if the necessary shaders are compiled * Removed r.SimpleDynamicLighting, whose functionality (unshadowed directional light in the base pass) is a subset of simple forward shading, and was unused Change 2969414 on 2016/05/06 by Daniel.Wright Added cvar 'r.Fog' for scalability Change 2969415 on 2016/05/06 by Daniel.Wright Low end scalability setup for Paragon Change 2969583 on 2016/05/06 by Daniel.Wright Effectively disabled the WRITES_PRECSHADOWFACTOR_TO_GBUFFER optimization, as all combinations use the GBuffer target * This fixes bSingleSampleShadowFromStationaryLights which was broken in cl 2863775 when selective GBuffer outputs was enabled Change 2969597 on 2016/05/06 by Olaf.Piesche Adding emitter tick times to Cascade viewport overlays #jira UE-25172 Change 2969599 on 2016/05/06 by Daniel.Wright Added r.Shadow.ForceSingleSampleShadowingFromStationary for scalability Change 2969795 on 2016/05/06 by Daniel.Wright Made r.SimpleForwardShading a scalability cvar Change 2969796 on 2016/05/06 by Daniel.Wright Enabled simple forward shading for the lowest shadow quality in Paragon * Moved Orion.Character.NonLocalHeroPreshadows to be under shadow quality * Enabling r.Shadow.ForceSingleSampleShadowingFromStationary when shadows are disabled through r.ShadowQuality Change 2972338 on 2016/05/10 by Martin.Mittring Added ImageValidator V0.11 to Perforce (for automated screenshot comparison) Change 2972450 on 2016/05/10 by Martin.Mittring fixed sorting issues, added column sort Change 2972564 on 2016/05/10 by Martin.Mittring fixed PixelCountToFail Change 2972572 on 2016/05/10 by Martin.Mittring added color Change 2972667 on 2016/05/10 by Daniel.Wright Capsule shadows support an off-center projection - fixes stereo rendering Indirect lighting cache is updated for primitives with a visible indirect capsule shadow - fixes indirect shadows disappearing when the caster is off-screen in the Static skylight case Change 2972687 on 2016/05/10 by Martin.Mittring split data from view Change 2972713 on 2016/05/10 by Martin.Mittring background validation Change 2972742 on 2016/05/10 by Martin.Mittring do not lock files in folder Change 2972837 on 2016/05/10 by Daniel.Wright Comment for tiled reflection culling edge failure case Change 2972891 on 2016/05/10 by Daniel.Wright Simple forward shading only supported on PC now Change 2972927 on 2016/05/10 by Martin.Mittring fixed comparison, added directory watcher Change 2972952 on 2016/05/10 by Martin.Mittring tooltips Change 2972965 on 2016/05/10 by Martin.Mittring readme Change 2972986 on 2016/05/10 by Martin.Mittring polish Change 2973015 on 2016/05/10 by Zabir.Hoque Clamp max cubemap resolutions for reflection capture component. Change 2973067 on 2016/05/10 by Uriel.Doyon Removed temporary streaming data from ULevel. Now the data goes directly in FStreamingManagerTexture. Removed deprecated classes and structures associated with old data. Uniformized dynamic primitives and static primitives streaming logic. Static primitive instances are now bound to level component and have visibility information. MeshTexCoordSize Debug now shows live update when tweaking "StreamingDistanceMultiplier" Change 2973129 on 2016/05/10 by Martin.Mittring fixed crash (uninit var) Change 2973167 on 2016/05/10 by Olaf.Piesche Fixing mac compiler warnings; removed beam tangent from particle source and target, as it's treated separately anyway. Change 2973654 on 2016/05/11 by Gil.Gribb FIxed bad resolve from main merge Change 2973787 on 2016/05/11 by Simon.Tovey PR #2080: Added 7 additional blueprint nodes and assoicated functions to Particle System Compoenent (Contributed by alwintom) #2080 Change 2973794 on 2016/05/11 by Simon.Tovey GitHub 1646 : Increase Wireframe Linear Color Value for Particles in Cascade Preview viewport #1646 Change 2973814 on 2016/05/11 by Chris.Bunner Fixed D3D warning. Change 2973868 on 2016/05/11 by Martin.Mittring fixed compiler warning Change 2974104 on 2016/05/11 by Uriel.Doyon Optimized TextureStreaming ASync task by improving cache efficency. Removed ForcedFullyLoad texture sets and merged them with the other entries (to prevent checking in two data structures). Change 2974163 on 2016/05/11 by Uriel.Doyon Fixed Editor Build Change 2974263 on 2016/05/11 by Olaf.Piesche Fix for particle beam source/target selection Change 2974313 on 2016/05/11 by Martin.Mittring nicer icon Change 2974632 on 2016/05/11 by Martin.Mittring zoom (mouse wheel) and pan support Change 2974651 on 2016/05/11 by Martin.Mittring UE-30565 Blend Radius does not override Priority for blendable post process material array #test:PC Change 2974994 on 2016/05/12 by Uriel.Doyon Fixed uninitialized members in texture streaming when updating dynamic primitives. #jira UE-30632 Change 2975514 on 2016/05/12 by Olaf.Piesche Getting mesh particle transform down to pixel shader, making available in TransformVector/TransformPosition nodes #udn 288158, and requests from several artists Change 2975970 on 2016/05/12 by Zabir.Hoque Enable setting high precision normals/tangets as a part of static mesh import. Change 2976134 on 2016/05/12 by Daniel.Wright Moved RHI prefix out of command list macros so you can find callers in a Find in Files for RHIBlendState, etc Change 2976135 on 2016/05/12 by Daniel.Wright Added material property bAllowNegativeEmissiveColor which is useful when rendering to an offscreen render target Change 2976139 on 2016/05/12 by Daniel.Wright Blueprint can now be used to draw to a TextureRenderTarget2D with DrawMaterialToRenderTarget Canvas can now draw to a TextureRenderTarget2D in a Blueprint with BeginDrawCanvasToRenderTarget / EndDrawCanvasToRenderTarget Change 2976199 on 2016/05/12 by Brian.Karis Improved screen space ray cast intersection heuristic. Change 2976203 on 2016/05/12 by Brian.Karis Fixed hair NaNs Change 2976214 on 2016/05/12 by Zabir.Hoque Fix compiler error on Clang Change 2976239 on 2016/05/12 by Brian.Karis Improved hair shadows Change 2976240 on 2016/05/12 by Brian.Karis Made recompileshaders specific file work again. Kind of hacky but better than nothing Change 2976290 on 2016/05/12 by Zabir.Hoque Few more clang compiler fixes. #jira UE-30713 Change 2976517 on 2016/05/13 by Zabir.Hoque Final set of fixes for compile breaks. Change 2976535 on 2016/05/13 by Zabir.Hoque Fix mono builds Change 2977270 on 2016/05/13 by Zabir.Hoque Incorrectly used 7 as max texcoords. Corrected to #define MAX_TEX_COORDS #lockdown gil.gribb Change 2980140 on 2016/05/17 by Gil.Gribb Merging //UE4/Dev-Main@2980127 to Dev-Rendering (//UE4/Dev-Rendering) #lockdown nick.penwarden Change 2980211 on 2016/05/17 by Ben.Marsh EC: Build DDC in Dev-Rendering every 3 hours. #lockdown Gil.Gribb Change 2980876 on 2016/05/17 by Michael.Trepka Metal shader compile fix #lockdown gil.gribb [CL 2981788 by Gil Gribb in Main branch]
1297 lines
53 KiB
C++
1297 lines
53 KiB
C++
// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
Reflection Environment - feature that provides HDR glossy reflections on any surfaces, leveraging precomputation to prefilter cubemaps of the scene
|
|
=============================================================================*/
|
|
|
|
#include "RendererPrivate.h"
|
|
#include "ScenePrivate.h"
|
|
#include "SceneFilterRendering.h"
|
|
#include "PostProcessing.h"
|
|
#include "UniformBuffer.h"
|
|
#include "ShaderParameters.h"
|
|
#include "ScreenRendering.h"
|
|
#include "ScreenSpaceReflections.h"
|
|
#include "PostProcessTemporalAA.h"
|
|
#include "PostProcessDownsample.h"
|
|
#include "ReflectionEnvironment.h"
|
|
#include "ShaderParameterUtils.h"
|
|
#include "LightRendering.h"
|
|
#include "SceneUtils.h"
|
|
#include "LightPropagationVolumeBlendable.h"
|
|
|
|
/** Tile size for the reflection environment compute shader, tweaked for 680 GTX. */
|
|
const int32 GReflectionEnvironmentTileSizeX = 16;
|
|
const int32 GReflectionEnvironmentTileSizeY = 16;
|
|
|
|
extern TAutoConsoleVariable<int32> CVarLPVMixing;
|
|
|
|
static TAutoConsoleVariable<int32> CVarDiffuseFromCaptures(
|
|
TEXT("r.DiffuseFromCaptures"),
|
|
0,
|
|
TEXT("Apply indirect diffuse lighting from captures instead of lightmaps.\n")
|
|
TEXT(" 0 is off (default), 1 is on"),
|
|
ECVF_RenderThreadSafe);
|
|
|
|
static TAutoConsoleVariable<int32> CVarReflectionEnvironment(
|
|
TEXT("r.ReflectionEnvironment"),
|
|
1,
|
|
TEXT("Whether to render the reflection environment feature, which implements local reflections through Reflection Capture actors.\n")
|
|
TEXT(" 0: off\n")
|
|
TEXT(" 1: on and blend with scene (default)")
|
|
TEXT(" 2: on and overwrite scene (only in non-shipping builds)"),
|
|
ECVF_RenderThreadSafe | ECVF_Scalability);
|
|
|
|
|
|
static TAutoConsoleVariable<int32> CVarDoTiledReflections(
|
|
TEXT("r.DoTiledReflections"),
|
|
1,
|
|
TEXT("Compute Reflection Environment with Tiled compute shader..\n")
|
|
TEXT(" 0: off\n")
|
|
TEXT(" 1: on (default)"),
|
|
ECVF_RenderThreadSafe);
|
|
|
|
static TAutoConsoleVariable<float> CVarSkySpecularOcclusionStrength(
|
|
TEXT("r.SkySpecularOcclusionStrength"),
|
|
1,
|
|
TEXT("Strength of skylight specular occlusion from DFAO (default is 1.0)"),
|
|
ECVF_RenderThreadSafe);
|
|
|
|
// to avoid having direct access from many places
|
|
static int GetReflectionEnvironmentCVar()
|
|
{
|
|
int32 RetVal = CVarReflectionEnvironment.GetValueOnAnyThread();
|
|
|
|
#if (UE_BUILD_SHIPPING || UE_BUILD_TEST)
|
|
// Disabling the debug part of this CVar when in shipping
|
|
if (RetVal == 2)
|
|
{
|
|
RetVal = 1;
|
|
}
|
|
#endif
|
|
|
|
return RetVal;
|
|
}
|
|
|
|
bool IsReflectionEnvironmentAvailable(ERHIFeatureLevel::Type InFeatureLevel)
|
|
{
|
|
return (InFeatureLevel >= ERHIFeatureLevel::SM4) && (GetReflectionEnvironmentCVar() != 0);
|
|
}
|
|
|
|
bool IsReflectionCaptureAvailable()
|
|
{
|
|
static IConsoleVariable* AllowStaticLightingVar = IConsoleManager::Get().FindConsoleVariable(TEXT("r.AllowStaticLighting"));
|
|
return (!AllowStaticLightingVar || AllowStaticLightingVar->GetInt() != 0);
|
|
}
|
|
|
|
void FReflectionEnvironmentCubemapArray::InitDynamicRHI()
|
|
{
|
|
if (GetFeatureLevel() >= ERHIFeatureLevel::SM5)
|
|
{
|
|
const int32 NumReflectionCaptureMips = FMath::CeilLogTwo(CubemapSize) + 1;
|
|
|
|
ReleaseCubeArray();
|
|
|
|
FPooledRenderTargetDesc Desc(
|
|
FPooledRenderTargetDesc::CreateCubemapDesc(
|
|
CubemapSize,
|
|
// Alpha stores sky mask
|
|
PF_FloatRGBA,
|
|
FClearValueBinding::None,
|
|
TexCreate_None,
|
|
TexCreate_None,
|
|
false,
|
|
// Cubemap array of 1 produces a regular cubemap, so guarantee it will be allocated as an array
|
|
FMath::Max<uint32>(MaxCubemaps, 2),
|
|
NumReflectionCaptureMips
|
|
)
|
|
);
|
|
|
|
Desc.AutoWritable = false;
|
|
|
|
FRHICommandListImmediate& RHICmdList = FRHICommandListExecutor::GetImmediateCommandList();
|
|
|
|
// Allocate TextureCubeArray for the scene's reflection captures
|
|
GRenderTargetPool.FindFreeElement(RHICmdList, Desc, ReflectionEnvs, TEXT("ReflectionEnvs"));
|
|
}
|
|
}
|
|
|
|
void FReflectionEnvironmentCubemapArray::ReleaseCubeArray()
|
|
{
|
|
// it's unlikely we can reuse the TextureCubeArray so when we release it we want to really remove it
|
|
GRenderTargetPool.FreeUnusedResource(ReflectionEnvs);
|
|
}
|
|
|
|
void FReflectionEnvironmentCubemapArray::ReleaseDynamicRHI()
|
|
{
|
|
ReleaseCubeArray();
|
|
}
|
|
|
|
void FReflectionEnvironmentCubemapArray::UpdateMaxCubemaps(uint32 InMaxCubemaps, int32 InCubemapSize)
|
|
{
|
|
MaxCubemaps = InMaxCubemaps;
|
|
CubemapSize = InCubemapSize;
|
|
|
|
// Reallocate the cubemap array
|
|
if (IsInitialized())
|
|
{
|
|
UpdateRHI();
|
|
}
|
|
else
|
|
{
|
|
InitResource();
|
|
}
|
|
}
|
|
|
|
class FDistanceFieldAOSpecularOcclusionParameters
|
|
{
|
|
public:
|
|
|
|
void Bind(const FShaderParameterMap& ParameterMap)
|
|
{
|
|
BentNormalAOTexture.Bind(ParameterMap, TEXT("BentNormalAOTexture"));
|
|
BentNormalAOSampler.Bind(ParameterMap, TEXT("BentNormalAOSampler"));
|
|
ApplyBentNormalAO.Bind(ParameterMap, TEXT("ApplyBentNormalAO"));
|
|
InvSkySpecularOcclusionStrength.Bind(ParameterMap, TEXT("InvSkySpecularOcclusionStrength"));
|
|
MinSkySpecularOcclusion.Bind(ParameterMap, TEXT("MinSkySpecularOcclusion"));
|
|
}
|
|
|
|
template<typename ShaderRHIParamRef, typename TRHICmdList>
|
|
void SetParameters(TRHICmdList& RHICmdList, const ShaderRHIParamRef& ShaderRHI, const TRefCountPtr<IPooledRenderTarget>& DynamicBentNormalAO, float SkySpecularOcclusionStrength, float MinOcclusionValue)
|
|
{
|
|
FTextureRHIParamRef BentNormalAO = GWhiteTexture->TextureRHI;
|
|
bool bApplyBentNormalAO = false;
|
|
|
|
if (DynamicBentNormalAO)
|
|
{
|
|
BentNormalAO = DynamicBentNormalAO->GetRenderTargetItem().ShaderResourceTexture;
|
|
bApplyBentNormalAO = true;
|
|
}
|
|
|
|
SetTextureParameter(RHICmdList, ShaderRHI, BentNormalAOTexture, BentNormalAOSampler, TStaticSamplerState<SF_Point>::GetRHI(), BentNormalAO);
|
|
SetShaderValue(RHICmdList, ShaderRHI, ApplyBentNormalAO, bApplyBentNormalAO ? 1.0f : 0.0f);
|
|
SetShaderValue(RHICmdList, ShaderRHI, InvSkySpecularOcclusionStrength, 1.0f / FMath::Max(SkySpecularOcclusionStrength, .1f));
|
|
SetShaderValue(RHICmdList, ShaderRHI, MinSkySpecularOcclusion, MinOcclusionValue);
|
|
}
|
|
|
|
friend FArchive& operator<<(FArchive& Ar,FDistanceFieldAOSpecularOcclusionParameters& P)
|
|
{
|
|
Ar << P.BentNormalAOTexture << P.BentNormalAOSampler << P.ApplyBentNormalAO << P.InvSkySpecularOcclusionStrength << P.MinSkySpecularOcclusion;
|
|
return Ar;
|
|
}
|
|
|
|
private:
|
|
FShaderResourceParameter BentNormalAOTexture;
|
|
FShaderResourceParameter BentNormalAOSampler;
|
|
FShaderParameter ApplyBentNormalAO;
|
|
FShaderParameter InvSkySpecularOcclusionStrength;
|
|
FShaderParameter MinSkySpecularOcclusion;
|
|
};
|
|
|
|
struct FReflectionCaptureSortData
|
|
{
|
|
uint32 Guid;
|
|
int32 CaptureIndex;
|
|
FVector4 PositionAndRadius;
|
|
FVector4 CaptureProperties;
|
|
FMatrix BoxTransform;
|
|
FVector4 BoxScales;
|
|
FVector4 CaptureOffset;
|
|
FTexture* SM4FullHDRCubemap;
|
|
|
|
bool operator < (const FReflectionCaptureSortData& Other) const
|
|
{
|
|
if( PositionAndRadius.W != Other.PositionAndRadius.W )
|
|
{
|
|
return PositionAndRadius.W < Other.PositionAndRadius.W;
|
|
}
|
|
else
|
|
{
|
|
return Guid < Other.Guid;
|
|
}
|
|
}
|
|
};
|
|
|
|
/** Per-reflection capture data needed by the shader. */
|
|
BEGIN_UNIFORM_BUFFER_STRUCT(FReflectionCaptureData,)
|
|
DECLARE_UNIFORM_BUFFER_STRUCT_MEMBER_ARRAY(FVector4,PositionAndRadius,[GMaxNumReflectionCaptures])
|
|
// R is brightness, G is array index, B is shape
|
|
DECLARE_UNIFORM_BUFFER_STRUCT_MEMBER_ARRAY(FVector4,CaptureProperties,[GMaxNumReflectionCaptures])
|
|
// Stores the box transform for a box shape, other data is packed for other shapes
|
|
DECLARE_UNIFORM_BUFFER_STRUCT_MEMBER_ARRAY(FMatrix,BoxTransform,[GMaxNumReflectionCaptures])
|
|
DECLARE_UNIFORM_BUFFER_STRUCT_MEMBER_ARRAY(FVector4,CaptureOffset,[GMaxNumReflectionCaptures])
|
|
DECLARE_UNIFORM_BUFFER_STRUCT_MEMBER_ARRAY(FVector4,BoxScales,[GMaxNumReflectionCaptures])
|
|
END_UNIFORM_BUFFER_STRUCT(FReflectionCaptureData)
|
|
|
|
IMPLEMENT_UNIFORM_BUFFER_STRUCT(FReflectionCaptureData,TEXT("ReflectionCapture"));
|
|
|
|
/** Compute shader that does tiled deferred culling of reflection captures, then sorts and composites them. */
|
|
class FReflectionEnvironmentTiledDeferredCS : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FReflectionEnvironmentTiledDeferredCS,Global)
|
|
public:
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM5);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Platform, OutEnvironment);
|
|
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZEX"), GReflectionEnvironmentTileSizeX);
|
|
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZEY"), GReflectionEnvironmentTileSizeY);
|
|
OutEnvironment.SetDefine(TEXT("MAX_CAPTURES"), GMaxNumReflectionCaptures);
|
|
OutEnvironment.SetDefine(TEXT("TILED_DEFERRED_CULL_SHADER"), 1);
|
|
OutEnvironment.CompilerFlags.Add(CFLAG_StandardOptimization);
|
|
}
|
|
|
|
FReflectionEnvironmentTiledDeferredCS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
DeferredParameters.Bind(Initializer.ParameterMap);
|
|
ReflectionEnvironmentColorTexture.Bind(Initializer.ParameterMap,TEXT("ReflectionEnvironmentColorTexture"));
|
|
ReflectionEnvironmentColorSampler.Bind(Initializer.ParameterMap,TEXT("ReflectionEnvironmentColorSampler"));
|
|
ScreenSpaceReflections.Bind(Initializer.ParameterMap, TEXT("ScreenSpaceReflections"));
|
|
InSceneColor.Bind(Initializer.ParameterMap, TEXT("InSceneColor"));
|
|
OutSceneColor.Bind(Initializer.ParameterMap, TEXT("OutSceneColor"));
|
|
NumCaptures.Bind(Initializer.ParameterMap, TEXT("NumCaptures"));
|
|
ViewDimensionsParameter.Bind(Initializer.ParameterMap, TEXT("ViewDimensions"));
|
|
PreIntegratedGF.Bind(Initializer.ParameterMap, TEXT("PreIntegratedGF"));
|
|
PreIntegratedGFSampler.Bind(Initializer.ParameterMap, TEXT("PreIntegratedGFSampler"));
|
|
SkyLightParameters.Bind(Initializer.ParameterMap);
|
|
SpecularOcclusionParameters.Bind(Initializer.ParameterMap);
|
|
}
|
|
|
|
FReflectionEnvironmentTiledDeferredCS()
|
|
{
|
|
}
|
|
|
|
void SetParameters(
|
|
FRHIAsyncComputeCommandListImmediate& RHICmdList,
|
|
const FSceneView& View,
|
|
FTextureRHIParamRef SSRTexture,
|
|
TArray<FReflectionCaptureSortData>& SortData,
|
|
FUnorderedAccessViewRHIParamRef OutSceneColorUAV,
|
|
const TRefCountPtr<IPooledRenderTarget>& DynamicBentNormalAO
|
|
)
|
|
{
|
|
const FComputeShaderRHIParamRef ShaderRHI = GetComputeShader();
|
|
|
|
FGlobalShader::SetParameters(RHICmdList, ShaderRHI, View);
|
|
DeferredParameters.Set(RHICmdList, ShaderRHI, View);
|
|
|
|
FScene* Scene = (FScene*)View.Family->Scene;
|
|
|
|
check(Scene->ReflectionSceneData.CubemapArray.IsValid());
|
|
check(Scene->ReflectionSceneData.CubemapArray.GetRenderTarget().IsValid());
|
|
|
|
FSceneRenderTargetItem& CubemapArray = Scene->ReflectionSceneData.CubemapArray.GetRenderTarget();
|
|
|
|
SetTextureParameter(
|
|
RHICmdList,
|
|
ShaderRHI,
|
|
ReflectionEnvironmentColorTexture,
|
|
ReflectionEnvironmentColorSampler,
|
|
TStaticSamplerState<SF_Trilinear, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI(),
|
|
CubemapArray.ShaderResourceTexture);
|
|
|
|
SetTextureParameter(RHICmdList, ShaderRHI, ScreenSpaceReflections, SSRTexture );
|
|
|
|
SetTextureParameter(RHICmdList, ShaderRHI, InSceneColor, FSceneRenderTargets::Get(RHICmdList).GetSceneColor()->GetRenderTargetItem().ShaderResourceTexture );
|
|
|
|
RHICmdList.TransitionResource(EResourceTransitionAccess::ERWBarrier, EResourceTransitionPipeline::EGfxToCompute, OutSceneColorUAV);
|
|
OutSceneColor.SetTexture(RHICmdList, ShaderRHI, NULL, OutSceneColorUAV);
|
|
|
|
SetShaderValue(RHICmdList, ShaderRHI, ViewDimensionsParameter, View.ViewRect);
|
|
|
|
FReflectionCaptureData SamplePositionsBuffer;
|
|
|
|
for (int32 CaptureIndex = 0; CaptureIndex < SortData.Num(); CaptureIndex++)
|
|
{
|
|
SamplePositionsBuffer.PositionAndRadius[CaptureIndex] = SortData[CaptureIndex].PositionAndRadius;
|
|
SamplePositionsBuffer.CaptureProperties[CaptureIndex] = SortData[CaptureIndex].CaptureProperties;
|
|
SamplePositionsBuffer.BoxTransform[CaptureIndex] = SortData[CaptureIndex].BoxTransform;
|
|
SamplePositionsBuffer.CaptureOffset[CaptureIndex] = SortData[CaptureIndex].CaptureOffset;
|
|
SamplePositionsBuffer.BoxScales[CaptureIndex] = SortData[CaptureIndex].BoxScales;
|
|
}
|
|
|
|
SetUniformBufferParameterImmediate(RHICmdList, ShaderRHI, GetUniformBufferParameter<FReflectionCaptureData>(), SamplePositionsBuffer);
|
|
SetShaderValue(RHICmdList, ShaderRHI, NumCaptures, SortData.Num());
|
|
|
|
SetTextureParameter(RHICmdList, ShaderRHI, PreIntegratedGF, PreIntegratedGFSampler, TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI(), GSystemTextures.PreintegratedGF->GetRenderTargetItem().ShaderResourceTexture);
|
|
|
|
SkyLightParameters.SetParameters(RHICmdList, ShaderRHI, Scene, View.Family->EngineShowFlags.SkyLighting);
|
|
|
|
const float MinOcclusion = Scene->SkyLight ? Scene->SkyLight->MinOcclusion : 0;
|
|
SpecularOcclusionParameters.SetParameters(RHICmdList, ShaderRHI, DynamicBentNormalAO, CVarSkySpecularOcclusionStrength.GetValueOnRenderThread(), MinOcclusion);
|
|
}
|
|
|
|
void UnsetParameters(FRHIAsyncComputeCommandListImmediate& RHICmdList, FUnorderedAccessViewRHIParamRef OutSceneColorUAV)
|
|
{
|
|
const FComputeShaderRHIParamRef ShaderRHI = GetComputeShader();
|
|
OutSceneColor.UnsetUAV(RHICmdList, ShaderRHI);
|
|
}
|
|
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << DeferredParameters;
|
|
Ar << ReflectionEnvironmentColorTexture;
|
|
Ar << ReflectionEnvironmentColorSampler;
|
|
Ar << ScreenSpaceReflections;
|
|
Ar << InSceneColor;
|
|
Ar << OutSceneColor;
|
|
Ar << NumCaptures;
|
|
Ar << ViewDimensionsParameter;
|
|
Ar << PreIntegratedGF;
|
|
Ar << PreIntegratedGFSampler;
|
|
Ar << SkyLightParameters;
|
|
Ar << SpecularOcclusionParameters;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
|
|
private:
|
|
|
|
FDeferredPixelShaderParameters DeferredParameters;
|
|
FShaderResourceParameter ReflectionEnvironmentColorTexture;
|
|
FShaderResourceParameter ReflectionEnvironmentColorSampler;
|
|
FShaderResourceParameter ScreenSpaceReflections;
|
|
FShaderResourceParameter InSceneColor;
|
|
FRWShaderParameter OutSceneColor;
|
|
FShaderParameter NumCaptures;
|
|
FShaderParameter ViewDimensionsParameter;
|
|
FShaderResourceParameter PreIntegratedGF;
|
|
FShaderResourceParameter PreIntegratedGFSampler;
|
|
FSkyLightReflectionParameters SkyLightParameters;
|
|
FDistanceFieldAOSpecularOcclusionParameters SpecularOcclusionParameters;
|
|
};
|
|
|
|
template< uint32 bUseLightmaps, uint32 bHasSkyLight, uint32 bBoxCapturesOnly, uint32 bSphereCapturesOnly, uint32 bSupportDFAOIndirectOcclusion >
|
|
class TReflectionEnvironmentTiledDeferredCS : public FReflectionEnvironmentTiledDeferredCS
|
|
{
|
|
DECLARE_SHADER_TYPE(TReflectionEnvironmentTiledDeferredCS, Global);
|
|
|
|
/** Default constructor. */
|
|
TReflectionEnvironmentTiledDeferredCS() {}
|
|
public:
|
|
TReflectionEnvironmentTiledDeferredCS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FReflectionEnvironmentTiledDeferredCS(Initializer)
|
|
{}
|
|
|
|
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FReflectionEnvironmentTiledDeferredCS::ModifyCompilationEnvironment(Platform, OutEnvironment);
|
|
OutEnvironment.SetDefine(TEXT("USE_LIGHTMAPS"), bUseLightmaps);
|
|
OutEnvironment.SetDefine(TEXT("HAS_SKYLIGHT"), bHasSkyLight);
|
|
OutEnvironment.SetDefine(TEXT("HAS_BOX_CAPTURES"), bBoxCapturesOnly);
|
|
OutEnvironment.SetDefine(TEXT("HAS_SPHERE_CAPTURES"), bSphereCapturesOnly);
|
|
OutEnvironment.SetDefine(TEXT("SUPPORT_DFAO_INDIRECT_OCCLUSION"), bSupportDFAOIndirectOcclusion);
|
|
}
|
|
};
|
|
|
|
// Typedef is necessary because the C preprocessor thinks the comma in the template parameter list is a comma in the macro parameter list.
|
|
#define IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(A, B, C, D, E) \
|
|
typedef TReflectionEnvironmentTiledDeferredCS<A,B,C,D,E> TReflectionEnvironmentTiledDeferredCS##A##B##C##D##E; \
|
|
IMPLEMENT_SHADER_TYPE(template<>,TReflectionEnvironmentTiledDeferredCS##A##B##C##D##E,TEXT("ReflectionEnvironmentComputeShaders"),TEXT("ReflectionEnvironmentTiledDeferredMain"),SF_Compute)
|
|
|
|
IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(0, 0, 0, 0, 0);
|
|
IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(0, 0, 0, 1, 0);
|
|
IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(0, 0, 1, 0, 0);
|
|
IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(0, 0, 1, 1, 0);
|
|
|
|
IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(0, 1, 0, 0, 0);
|
|
IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(0, 1, 0, 1, 0);
|
|
IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(0, 1, 1, 0, 0);
|
|
IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(0, 1, 1, 1, 0);
|
|
|
|
IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(1, 0, 0, 0, 0);
|
|
IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(1, 0, 0, 1, 0);
|
|
IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(1, 0, 1, 0, 0);
|
|
IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(1, 0, 1, 1, 0);
|
|
|
|
IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(1, 1, 0, 0, 0);
|
|
IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(1, 1, 0, 1, 0);
|
|
IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(1, 1, 1, 0, 0);
|
|
IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(1, 1, 1, 1, 0);
|
|
|
|
IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(0, 0, 0, 0, 1);
|
|
IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(0, 0, 0, 1, 1);
|
|
IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(0, 0, 1, 0, 1);
|
|
IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(0, 0, 1, 1, 1);
|
|
|
|
IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(0, 1, 0, 0, 1);
|
|
IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(0, 1, 0, 1, 1);
|
|
IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(0, 1, 1, 0, 1);
|
|
IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(0, 1, 1, 1, 1);
|
|
|
|
IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(1, 0, 0, 0, 1);
|
|
IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(1, 0, 0, 1, 1);
|
|
IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(1, 0, 1, 0, 1);
|
|
IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(1, 0, 1, 1, 1);
|
|
|
|
IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(1, 1, 0, 0, 1);
|
|
IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(1, 1, 0, 1, 1);
|
|
IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(1, 1, 1, 0, 1);
|
|
IMPLEMENT_REFLECTION_COMPUTESHADER_TYPE(1, 1, 1, 1, 1);
|
|
|
|
template< uint32 bSSR, uint32 bReflectionEnv, uint32 bSkylight, uint32 bSupportDFAOIndirectOcclusion >
|
|
class FReflectionApplyPS : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FReflectionApplyPS, Global);
|
|
public:
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM4);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Platform, OutEnvironment);
|
|
OutEnvironment.SetDefine(TEXT("APPLY_SSR"), bSSR);
|
|
OutEnvironment.SetDefine(TEXT("APPLY_REFLECTION_ENV"), bReflectionEnv);
|
|
OutEnvironment.SetDefine(TEXT("APPLY_SKYLIGHT"), bSkylight);
|
|
OutEnvironment.SetDefine(TEXT("SUPPORT_DFAO_INDIRECT_OCCLUSION"), bSupportDFAOIndirectOcclusion);
|
|
}
|
|
|
|
/** Default constructor. */
|
|
FReflectionApplyPS() {}
|
|
|
|
/** Initialization constructor. */
|
|
FReflectionApplyPS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
DeferredParameters.Bind(Initializer.ParameterMap);
|
|
SkyLightParameters.Bind(Initializer.ParameterMap);
|
|
ReflectionEnvTexture.Bind(Initializer.ParameterMap,TEXT("ReflectionEnvTexture"));
|
|
ReflectionEnvSampler.Bind(Initializer.ParameterMap,TEXT("ReflectionEnvSampler"));
|
|
ScreenSpaceReflectionsTexture.Bind(Initializer.ParameterMap,TEXT("ScreenSpaceReflectionsTexture"));
|
|
ScreenSpaceReflectionsSampler.Bind(Initializer.ParameterMap,TEXT("ScreenSpaceReflectionsSampler"));
|
|
PreIntegratedGF.Bind(Initializer.ParameterMap, TEXT("PreIntegratedGF"));
|
|
PreIntegratedGFSampler.Bind(Initializer.ParameterMap, TEXT("PreIntegratedGFSampler"));
|
|
SpecularOcclusionParameters.Bind(Initializer.ParameterMap);
|
|
}
|
|
|
|
void SetParameters(FRHICommandList& RHICmdList, const FSceneView& View, FTextureRHIParamRef ReflectionEnv, FTextureRHIParamRef ScreenSpaceReflections, const TRefCountPtr<IPooledRenderTarget>& DynamicBentNormalAO)
|
|
{
|
|
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
|
|
|
|
FGlobalShader::SetParameters(RHICmdList, ShaderRHI, View);
|
|
DeferredParameters.Set(RHICmdList, ShaderRHI, View);
|
|
SkyLightParameters.SetParameters(RHICmdList, ShaderRHI, (FScene*)View.Family->Scene, true);
|
|
|
|
SetTextureParameter(RHICmdList, ShaderRHI, ReflectionEnvTexture, ReflectionEnvSampler, TStaticSamplerState<SF_Point>::GetRHI(), ReflectionEnv );
|
|
SetTextureParameter(RHICmdList, ShaderRHI, ScreenSpaceReflectionsTexture, ScreenSpaceReflectionsSampler, TStaticSamplerState<SF_Point>::GetRHI(), ScreenSpaceReflections );
|
|
SetTextureParameter(RHICmdList, ShaderRHI, PreIntegratedGF, PreIntegratedGFSampler, TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI(), GSystemTextures.PreintegratedGF->GetRenderTargetItem().ShaderResourceTexture );
|
|
|
|
FScene* Scene = (FScene*)View.Family->Scene;
|
|
const float MinOcclusion = Scene->SkyLight ? Scene->SkyLight->MinOcclusion : 0;
|
|
SpecularOcclusionParameters.SetParameters(RHICmdList, ShaderRHI, DynamicBentNormalAO, CVarSkySpecularOcclusionStrength.GetValueOnRenderThread(), MinOcclusion);
|
|
}
|
|
|
|
// FShader interface.
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << DeferredParameters;
|
|
Ar << SkyLightParameters;
|
|
Ar << ReflectionEnvTexture;
|
|
Ar << ReflectionEnvSampler;
|
|
Ar << ScreenSpaceReflectionsTexture;
|
|
Ar << ScreenSpaceReflectionsSampler;
|
|
Ar << PreIntegratedGF;
|
|
Ar << PreIntegratedGFSampler;
|
|
Ar << SpecularOcclusionParameters;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
|
|
private:
|
|
|
|
FDeferredPixelShaderParameters DeferredParameters;
|
|
FSkyLightReflectionParameters SkyLightParameters;
|
|
FShaderResourceParameter ReflectionEnvTexture;
|
|
FShaderResourceParameter ReflectionEnvSampler;
|
|
FShaderResourceParameter ScreenSpaceReflectionsTexture;
|
|
FShaderResourceParameter ScreenSpaceReflectionsSampler;
|
|
FShaderResourceParameter PreIntegratedGF;
|
|
FShaderResourceParameter PreIntegratedGFSampler;
|
|
FDistanceFieldAOSpecularOcclusionParameters SpecularOcclusionParameters;
|
|
};
|
|
|
|
// Typedef is necessary because the C preprocessor thinks the comma in the template parameter list is a comma in the macro parameter list.
|
|
#define IMPLEMENT_REFLECTION_APPLY_PIXELSHADER_TYPE(A, B, C, D) \
|
|
typedef FReflectionApplyPS<A,B,C,D> FReflectionApplyPS##A##B##C##D; \
|
|
IMPLEMENT_SHADER_TYPE(template<>,FReflectionApplyPS##A##B##C##D,TEXT("ReflectionEnvironmentShaders"),TEXT("ReflectionApplyPS"),SF_Pixel);
|
|
|
|
IMPLEMENT_REFLECTION_APPLY_PIXELSHADER_TYPE(0,0,0,0);
|
|
IMPLEMENT_REFLECTION_APPLY_PIXELSHADER_TYPE(0,0,1,0);
|
|
IMPLEMENT_REFLECTION_APPLY_PIXELSHADER_TYPE(0,1,0,0);
|
|
IMPLEMENT_REFLECTION_APPLY_PIXELSHADER_TYPE(0,1,1,0);
|
|
IMPLEMENT_REFLECTION_APPLY_PIXELSHADER_TYPE(1,0,0,0);
|
|
IMPLEMENT_REFLECTION_APPLY_PIXELSHADER_TYPE(1,0,1,0);
|
|
IMPLEMENT_REFLECTION_APPLY_PIXELSHADER_TYPE(1,1,0,0);
|
|
IMPLEMENT_REFLECTION_APPLY_PIXELSHADER_TYPE(1,1,1,0);
|
|
|
|
IMPLEMENT_REFLECTION_APPLY_PIXELSHADER_TYPE(0,0,0,1);
|
|
IMPLEMENT_REFLECTION_APPLY_PIXELSHADER_TYPE(0,0,1,1);
|
|
IMPLEMENT_REFLECTION_APPLY_PIXELSHADER_TYPE(0,1,0,1);
|
|
IMPLEMENT_REFLECTION_APPLY_PIXELSHADER_TYPE(0,1,1,1);
|
|
IMPLEMENT_REFLECTION_APPLY_PIXELSHADER_TYPE(1,0,0,1);
|
|
IMPLEMENT_REFLECTION_APPLY_PIXELSHADER_TYPE(1,0,1,1);
|
|
IMPLEMENT_REFLECTION_APPLY_PIXELSHADER_TYPE(1,1,0,1);
|
|
IMPLEMENT_REFLECTION_APPLY_PIXELSHADER_TYPE(1,1,1,1);
|
|
|
|
class FReflectionCaptureSpecularBouncePS : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FReflectionCaptureSpecularBouncePS, Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM4);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Platform,OutEnvironment);
|
|
}
|
|
|
|
/** Default constructor. */
|
|
FReflectionCaptureSpecularBouncePS() {}
|
|
|
|
public:
|
|
FDeferredPixelShaderParameters DeferredParameters;
|
|
|
|
/** Initialization constructor. */
|
|
FReflectionCaptureSpecularBouncePS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
DeferredParameters.Bind(Initializer.ParameterMap);
|
|
}
|
|
|
|
void SetParameters(FRHICommandList& RHICmdList, const FSceneView& View)
|
|
{
|
|
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
|
|
|
|
FGlobalShader::SetParameters(RHICmdList, ShaderRHI, View);
|
|
|
|
DeferredParameters.Set(RHICmdList, ShaderRHI, View);
|
|
}
|
|
|
|
// FShader interface.
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << DeferredParameters;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_SHADER_TYPE(,FReflectionCaptureSpecularBouncePS,TEXT("ReflectionEnvironmentShaders"),TEXT("SpecularBouncePS"),SF_Pixel);
|
|
|
|
template<bool bSphereCapture>
|
|
class TStandardDeferredReflectionPS : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(TStandardDeferredReflectionPS, Global);
|
|
public:
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM4);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Platform, OutEnvironment);
|
|
OutEnvironment.SetDefine(TEXT("SPHERE_CAPTURE"), (uint32)bSphereCapture);
|
|
OutEnvironment.SetDefine(TEXT("BOX_CAPTURE"), (uint32)!bSphereCapture);
|
|
}
|
|
|
|
/** Default constructor. */
|
|
TStandardDeferredReflectionPS() {}
|
|
|
|
/** Initialization constructor. */
|
|
TStandardDeferredReflectionPS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
CapturePositionAndRadius.Bind(Initializer.ParameterMap, TEXT("CapturePositionAndRadius"));
|
|
CaptureProperties.Bind(Initializer.ParameterMap, TEXT("CaptureProperties"));
|
|
CaptureBoxTransform.Bind(Initializer.ParameterMap, TEXT("CaptureBoxTransform"));
|
|
CaptureBoxScales.Bind(Initializer.ParameterMap, TEXT("CaptureBoxScales"));
|
|
CaptureOffset.Bind(Initializer.ParameterMap, TEXT("CaptureOffset"));
|
|
CaptureArrayIndex.Bind(Initializer.ParameterMap, TEXT("CaptureArrayIndex"));
|
|
ReflectionEnvironmentColorTexture.Bind(Initializer.ParameterMap, TEXT("ReflectionEnvironmentColorTexture"));
|
|
ReflectionEnvironmentColorTextureArray.Bind(Initializer.ParameterMap, TEXT("ReflectionEnvironmentColorTextureArray"));
|
|
ReflectionEnvironmentColorSampler.Bind(Initializer.ParameterMap, TEXT("ReflectionEnvironmentColorSampler"));
|
|
DeferredParameters.Bind(Initializer.ParameterMap);
|
|
}
|
|
|
|
void SetParameters(FRHICommandList& RHICmdList, const FSceneView& View, const FReflectionCaptureSortData& SortData)
|
|
{
|
|
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
|
|
FGlobalShader::SetParameters(RHICmdList, ShaderRHI, View);
|
|
|
|
if (View.GetFeatureLevel() >= ERHIFeatureLevel::SM5)
|
|
{
|
|
FScene* Scene = (FScene*)View.Family->Scene;
|
|
|
|
check(Scene->ReflectionSceneData.CubemapArray.IsValid());
|
|
check(Scene->ReflectionSceneData.CubemapArray.GetRenderTarget().IsValid());
|
|
|
|
FSceneRenderTargetItem& CubemapArray = Scene->ReflectionSceneData.CubemapArray.GetRenderTarget();
|
|
|
|
SetTextureParameter(RHICmdList, ShaderRHI, ReflectionEnvironmentColorTextureArray, ReflectionEnvironmentColorSampler, TStaticSamplerState<SF_Trilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI(), CubemapArray.ShaderResourceTexture);
|
|
SetShaderValue(RHICmdList, ShaderRHI, CaptureArrayIndex, SortData.CaptureIndex);
|
|
}
|
|
else
|
|
{
|
|
SetTextureParameter(RHICmdList, ShaderRHI, ReflectionEnvironmentColorTexture, ReflectionEnvironmentColorSampler, TStaticSamplerState<SF_Trilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI(), SortData.SM4FullHDRCubemap->TextureRHI);
|
|
}
|
|
|
|
DeferredParameters.Set(RHICmdList, ShaderRHI, View);
|
|
SetShaderValue(RHICmdList, ShaderRHI, CapturePositionAndRadius, SortData.PositionAndRadius);
|
|
SetShaderValue(RHICmdList, ShaderRHI, CaptureProperties, SortData.CaptureProperties);
|
|
SetShaderValue(RHICmdList, ShaderRHI, CaptureBoxTransform, SortData.BoxTransform);
|
|
SetShaderValue(RHICmdList, ShaderRHI, CaptureBoxScales, SortData.BoxScales);
|
|
SetShaderValue(RHICmdList, ShaderRHI, CaptureOffset, FVector(SortData.CaptureOffset));
|
|
}
|
|
|
|
// FShader interface.
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << CapturePositionAndRadius;
|
|
Ar << CaptureProperties;
|
|
Ar << CaptureBoxTransform;
|
|
Ar << CaptureBoxScales;
|
|
Ar << CaptureOffset;
|
|
Ar << CaptureArrayIndex;
|
|
Ar << ReflectionEnvironmentColorTexture;
|
|
Ar << ReflectionEnvironmentColorTextureArray;
|
|
Ar << ReflectionEnvironmentColorSampler;
|
|
Ar << DeferredParameters;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
|
|
private:
|
|
|
|
FShaderParameter CapturePositionAndRadius;
|
|
FShaderParameter CaptureProperties;
|
|
FShaderParameter CaptureBoxTransform;
|
|
FShaderParameter CaptureBoxScales;
|
|
FShaderParameter CaptureOffset;
|
|
FShaderParameter CaptureArrayIndex;
|
|
FShaderResourceParameter ReflectionEnvironmentColorTexture;
|
|
FShaderResourceParameter ReflectionEnvironmentColorTextureArray;
|
|
FShaderResourceParameter ReflectionEnvironmentColorSampler;
|
|
FDeferredPixelShaderParameters DeferredParameters;
|
|
};
|
|
|
|
IMPLEMENT_SHADER_TYPE(template<>,TStandardDeferredReflectionPS<true>,TEXT("ReflectionEnvironmentShaders"),TEXT("StandardDeferredReflectionPS"),SF_Pixel);
|
|
IMPLEMENT_SHADER_TYPE(template<>,TStandardDeferredReflectionPS<false>,TEXT("ReflectionEnvironmentShaders"),TEXT("StandardDeferredReflectionPS"),SF_Pixel);
|
|
|
|
void FDeferredShadingSceneRenderer::RenderReflectionCaptureSpecularBounceForAllViews(FRHICommandListImmediate& RHICmdList)
|
|
{
|
|
FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList);
|
|
SceneContext.BeginRenderingSceneColor(RHICmdList, ESimpleRenderTargetMode::EUninitializedColorExistingDepth, FExclusiveDepthStencil::DepthRead_StencilWrite);
|
|
RHICmdList.SetRasterizerState(TStaticRasterizerState< FM_Solid, CM_None >::GetRHI());
|
|
RHICmdList.SetDepthStencilState(TStaticDepthStencilState< false, CF_Always >::GetRHI());
|
|
RHICmdList.SetBlendState(TStaticBlendState< CW_RGB, BO_Add, BF_One, BF_One >::GetRHI());
|
|
|
|
auto ShaderMap = GetGlobalShaderMap(FeatureLevel);
|
|
TShaderMapRef< FPostProcessVS > VertexShader(ShaderMap);
|
|
TShaderMapRef< FReflectionCaptureSpecularBouncePS > PixelShader(ShaderMap);
|
|
|
|
static FGlobalBoundShaderState BoundShaderState;
|
|
|
|
SetGlobalBoundShaderState(RHICmdList, FeatureLevel, BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader);
|
|
|
|
for (int32 ViewIndex = 0, Num = Views.Num(); ViewIndex < Num; ViewIndex++)
|
|
{
|
|
const FViewInfo& View = Views[ViewIndex];
|
|
|
|
RHICmdList.SetViewport(View.ViewRect.Min.X, View.ViewRect.Min.Y, 0.0f, View.ViewRect.Max.X, View.ViewRect.Max.Y, 1.0f);
|
|
|
|
|
|
PixelShader->SetParameters(RHICmdList, View);
|
|
|
|
DrawRectangle(
|
|
RHICmdList,
|
|
0, 0,
|
|
View.ViewRect.Width(), View.ViewRect.Height(),
|
|
0, 0,
|
|
View.ViewRect.Width(), View.ViewRect.Height(),
|
|
FIntPoint(View.ViewRect.Width(), View.ViewRect.Height()),
|
|
SceneContext.GetBufferSizeXY(),
|
|
*VertexShader,
|
|
EDRF_UseTriangleOptimization);
|
|
}
|
|
|
|
SceneContext.FinishRenderingSceneColor(RHICmdList);
|
|
}
|
|
|
|
bool FDeferredShadingSceneRenderer::ShouldDoReflectionEnvironment() const
|
|
{
|
|
const ERHIFeatureLevel::Type SceneFeatureLevel = Scene->GetFeatureLevel();
|
|
|
|
return IsReflectionEnvironmentAvailable(SceneFeatureLevel)
|
|
&& Scene->ReflectionSceneData.RegisteredReflectionCaptures.Num()
|
|
&& ViewFamily.EngineShowFlags.ReflectionEnvironment
|
|
&& (SceneFeatureLevel == ERHIFeatureLevel::SM4 || Scene->ReflectionSceneData.CubemapArray.IsValid());
|
|
}
|
|
|
|
void GatherAndSortReflectionCaptures(const FScene* Scene, TArray<FReflectionCaptureSortData>& OutSortData, int32& OutNumBoxCaptures, int32& OutNumSphereCaptures)
|
|
{
|
|
OutSortData.Reset(Scene->ReflectionSceneData.RegisteredReflectionCaptures.Num());
|
|
OutNumBoxCaptures = 0;
|
|
OutNumSphereCaptures = 0;
|
|
|
|
const int32 MaxCubemaps = Scene->ReflectionSceneData.CubemapArray.GetMaxCubemaps();
|
|
|
|
// Pack only visible reflection captures into the uniform buffer, each with an index to its cubemap array entry
|
|
for (int32 ReflectionProxyIndex = 0; ReflectionProxyIndex < Scene->ReflectionSceneData.RegisteredReflectionCaptures.Num() && OutSortData.Num() < GMaxNumReflectionCaptures; ReflectionProxyIndex++)
|
|
{
|
|
FReflectionCaptureProxy* CurrentCapture = Scene->ReflectionSceneData.RegisteredReflectionCaptures[ReflectionProxyIndex];
|
|
// Find the cubemap index this component was allocated with
|
|
const FCaptureComponentSceneState* ComponentStatePtr = Scene->ReflectionSceneData.AllocatedReflectionCaptureState.Find(CurrentCapture->Component);
|
|
|
|
if (ComponentStatePtr)
|
|
{
|
|
int32 CubemapIndex = ComponentStatePtr->CaptureIndex;
|
|
check(CubemapIndex < MaxCubemaps);
|
|
|
|
FReflectionCaptureSortData NewSortEntry;
|
|
|
|
NewSortEntry.CaptureIndex = CubemapIndex;
|
|
NewSortEntry.SM4FullHDRCubemap = NULL;
|
|
NewSortEntry.Guid = CurrentCapture->Guid;
|
|
NewSortEntry.PositionAndRadius = FVector4(CurrentCapture->Position, CurrentCapture->InfluenceRadius);
|
|
float ShapeTypeValue = (float)CurrentCapture->Shape;
|
|
NewSortEntry.CaptureProperties = FVector4(CurrentCapture->Brightness, CubemapIndex, ShapeTypeValue, 0);
|
|
NewSortEntry.CaptureOffset = FVector4(CurrentCapture->CaptureOffset, 0);
|
|
|
|
if (CurrentCapture->Shape == EReflectionCaptureShape::Plane)
|
|
{
|
|
//planes count as boxes in the compute shader.
|
|
++OutNumBoxCaptures;
|
|
NewSortEntry.BoxTransform = FMatrix(
|
|
FPlane(CurrentCapture->ReflectionPlane),
|
|
FPlane(CurrentCapture->ReflectionXAxisAndYScale),
|
|
FPlane(0, 0, 0, 0),
|
|
FPlane(0, 0, 0, 0));
|
|
|
|
NewSortEntry.BoxScales = FVector4(0);
|
|
}
|
|
else if (CurrentCapture->Shape == EReflectionCaptureShape::Sphere)
|
|
{
|
|
++OutNumSphereCaptures;
|
|
}
|
|
else
|
|
{
|
|
++OutNumBoxCaptures;
|
|
NewSortEntry.BoxTransform = CurrentCapture->BoxTransform;
|
|
NewSortEntry.BoxScales = FVector4(CurrentCapture->BoxScales, CurrentCapture->BoxTransitionDistance);
|
|
}
|
|
|
|
OutSortData.Add(NewSortEntry);
|
|
}
|
|
}
|
|
|
|
OutSortData.Sort();
|
|
}
|
|
|
|
template<bool bSuportDFAOIndirectOcclusion>
|
|
FReflectionEnvironmentTiledDeferredCS* SelectReflectionEnvironmentTiledDeferredCSInner(TShaderMap<FGlobalShaderType>* ShaderMap, bool bUseLightmaps, bool bHasSkyLight, bool bHasBoxCaptures, bool bHasSphereCaptures)
|
|
{
|
|
FReflectionEnvironmentTiledDeferredCS* ComputeShader = nullptr;
|
|
if (bUseLightmaps)
|
|
{
|
|
if (bHasSkyLight)
|
|
{
|
|
if (bHasBoxCaptures && bHasSphereCaptures)
|
|
{
|
|
ComputeShader = *TShaderMapRef< TReflectionEnvironmentTiledDeferredCS<1, 1, 1, 1, bSuportDFAOIndirectOcclusion> >(ShaderMap);
|
|
}
|
|
else if (bHasBoxCaptures)
|
|
{
|
|
ComputeShader = *TShaderMapRef< TReflectionEnvironmentTiledDeferredCS<1, 1, 1, 0, bSuportDFAOIndirectOcclusion> >(ShaderMap);
|
|
}
|
|
else if (bHasSphereCaptures)
|
|
{
|
|
ComputeShader = *TShaderMapRef< TReflectionEnvironmentTiledDeferredCS<1, 1, 0, 1, bSuportDFAOIndirectOcclusion> >(ShaderMap);
|
|
}
|
|
else
|
|
{
|
|
ComputeShader = *TShaderMapRef< TReflectionEnvironmentTiledDeferredCS<1, 1, 0, 0, bSuportDFAOIndirectOcclusion> >(ShaderMap);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (bHasBoxCaptures && bHasSphereCaptures)
|
|
{
|
|
ComputeShader = *TShaderMapRef< TReflectionEnvironmentTiledDeferredCS<1, 0, 1, 1, bSuportDFAOIndirectOcclusion> >(ShaderMap);
|
|
}
|
|
else if (bHasBoxCaptures)
|
|
{
|
|
ComputeShader = *TShaderMapRef< TReflectionEnvironmentTiledDeferredCS<1, 0, 1, 0, bSuportDFAOIndirectOcclusion> >(ShaderMap);
|
|
}
|
|
else if (bHasSphereCaptures)
|
|
{
|
|
ComputeShader = *TShaderMapRef< TReflectionEnvironmentTiledDeferredCS<1, 0, 0, 1, bSuportDFAOIndirectOcclusion> >(ShaderMap);
|
|
}
|
|
else
|
|
{
|
|
ComputeShader = *TShaderMapRef< TReflectionEnvironmentTiledDeferredCS<1, 0, 0, 0, bSuportDFAOIndirectOcclusion> >(ShaderMap);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (bHasSkyLight)
|
|
{
|
|
if (bHasBoxCaptures && bHasSphereCaptures)
|
|
{
|
|
ComputeShader = *TShaderMapRef< TReflectionEnvironmentTiledDeferredCS<0, 1, 1, 1, bSuportDFAOIndirectOcclusion> >(ShaderMap);
|
|
}
|
|
else if (bHasBoxCaptures)
|
|
{
|
|
ComputeShader = *TShaderMapRef< TReflectionEnvironmentTiledDeferredCS<0, 1, 1, 0, bSuportDFAOIndirectOcclusion> >(ShaderMap);
|
|
}
|
|
else if (bHasSphereCaptures)
|
|
{
|
|
ComputeShader = *TShaderMapRef< TReflectionEnvironmentTiledDeferredCS<0, 1, 0, 1, bSuportDFAOIndirectOcclusion> >(ShaderMap);
|
|
}
|
|
else
|
|
{
|
|
ComputeShader = *TShaderMapRef< TReflectionEnvironmentTiledDeferredCS<0, 1, 0, 0, bSuportDFAOIndirectOcclusion> >(ShaderMap);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (bHasBoxCaptures && bHasSphereCaptures)
|
|
{
|
|
ComputeShader = *TShaderMapRef< TReflectionEnvironmentTiledDeferredCS<0, 0, 1, 1, bSuportDFAOIndirectOcclusion> >(ShaderMap);
|
|
}
|
|
else if (bHasBoxCaptures)
|
|
{
|
|
ComputeShader = *TShaderMapRef< TReflectionEnvironmentTiledDeferredCS<0, 0, 1, 0, bSuportDFAOIndirectOcclusion> >(ShaderMap);
|
|
}
|
|
else if (bHasSphereCaptures)
|
|
{
|
|
ComputeShader = *TShaderMapRef< TReflectionEnvironmentTiledDeferredCS<0, 0, 0, 1, bSuportDFAOIndirectOcclusion> >(ShaderMap);
|
|
}
|
|
else
|
|
{
|
|
ComputeShader = *TShaderMapRef< TReflectionEnvironmentTiledDeferredCS<0, 0, 0, 0, bSuportDFAOIndirectOcclusion> >(ShaderMap);
|
|
}
|
|
}
|
|
}
|
|
check(ComputeShader);
|
|
return ComputeShader;
|
|
}
|
|
|
|
FReflectionEnvironmentTiledDeferredCS* SelectReflectionEnvironmentTiledDeferredCS(TShaderMap<FGlobalShaderType>* ShaderMap, bool bUseLightmaps, bool bHasSkyLight, bool bHasBoxCaptures, bool bHasSphereCaptures, bool bSuportDFAOIndirectOcclusion)
|
|
{
|
|
if (bSuportDFAOIndirectOcclusion)
|
|
{
|
|
return SelectReflectionEnvironmentTiledDeferredCSInner<true>(ShaderMap, bUseLightmaps, bHasSkyLight, bHasBoxCaptures, bHasSphereCaptures);
|
|
}
|
|
else
|
|
{
|
|
return SelectReflectionEnvironmentTiledDeferredCSInner<false>(ShaderMap, bUseLightmaps, bHasSkyLight, bHasBoxCaptures, bHasSphereCaptures);
|
|
}
|
|
}
|
|
|
|
void FDeferredShadingSceneRenderer::RenderTiledDeferredImageBasedReflections(FRHICommandListImmediate& RHICmdList, const TRefCountPtr<IPooledRenderTarget>& DynamicBentNormalAO)
|
|
{
|
|
FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList);
|
|
static const auto AllowStaticLightingVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.AllowStaticLighting"));
|
|
const bool bUseLightmaps = (AllowStaticLightingVar->GetValueOnRenderThread() == 1) && (CVarDiffuseFromCaptures.GetValueOnRenderThread() == 0);
|
|
|
|
TRefCountPtr<IPooledRenderTarget> NewSceneColor;
|
|
{
|
|
SceneContext.ResolveSceneColor(RHICmdList, FResolveRect(0, 0, ViewFamily.FamilySizeX, ViewFamily.FamilySizeY));
|
|
|
|
FPooledRenderTargetDesc Desc = SceneContext.GetSceneColor()->GetDesc();
|
|
Desc.TargetableFlags |= TexCreate_UAV;
|
|
Desc.TargetableFlags |= TexCreate_NoFastClear;
|
|
Desc.ClearValue = FClearValueBinding::None;
|
|
|
|
// we don't create a new name to make it easier to use "vis SceneColor" and get the last HDRSceneColor
|
|
GRenderTargetPool.FindFreeElement(RHICmdList, Desc, NewSceneColor, TEXT("SceneColor") );
|
|
}
|
|
|
|
// If we are in SM5, use the compute shader gather method
|
|
for (int32 ViewIndex = 0, Num = Views.Num(); ViewIndex < Num; ViewIndex++)
|
|
{
|
|
FViewInfo& View = Views[ViewIndex];
|
|
|
|
const uint32 bSSR = ShouldRenderScreenSpaceReflections(Views[ViewIndex]);
|
|
|
|
TRefCountPtr<IPooledRenderTarget> SSROutput = GSystemTextures.BlackDummy;
|
|
if( bSSR )
|
|
{
|
|
RenderScreenSpaceReflections(RHICmdList, View, SSROutput);
|
|
}
|
|
|
|
RenderDeferredPlanarReflections(RHICmdList, false, SSROutput);
|
|
|
|
// ReflectionEnv is assumed to be on when going into this method
|
|
{
|
|
SetRenderTarget(RHICmdList, NULL, NULL);
|
|
|
|
FReflectionEnvironmentTiledDeferredCS* ComputeShader = NULL;
|
|
// Render the reflection environment with tiled deferred culling
|
|
TArray<FReflectionCaptureSortData> SortData;
|
|
int32 NumBoxCaptures = 0;
|
|
int32 NumSphereCaptures = 0;
|
|
GatherAndSortReflectionCaptures(Scene, SortData, NumBoxCaptures, NumSphereCaptures);
|
|
|
|
bool bHasBoxCaptures = (NumBoxCaptures > 0);
|
|
bool bHasSphereCaptures = (NumSphereCaptures > 0);
|
|
bool bHasSkyLight = Scene && Scene->SkyLight && !Scene->SkyLight->bHasStaticLighting;
|
|
|
|
static const FName TiledReflBeginComputeName(TEXT("ReflectionEnvBeginComputeFence"));
|
|
static const FName TiledReflEndComputeName(TEXT("ReflectionEnvEndComputeFence"));
|
|
FComputeFenceRHIRef ReflectionBeginFence = RHICmdList.CreateComputeFence(TiledReflBeginComputeName);
|
|
FComputeFenceRHIRef ReflectionEndFence = RHICmdList.CreateComputeFence(TiledReflEndComputeName);
|
|
|
|
//Grab the async compute commandlist.
|
|
FRHIAsyncComputeCommandListImmediate& RHICmdListComputeImmediate = FRHICommandListExecutor::GetImmediateAsyncComputeCommandList();
|
|
{
|
|
SCOPED_COMPUTE_EVENTF(RHICmdListComputeImmediate, ReflectionEnvironment, TEXT("ReflectionEnvironment ComputeShader %dx%d Tile:%dx%d Box:%d Sphere:%d SkyLight:%d"),
|
|
View.ViewRect.Width(), View.ViewRect.Height(), GReflectionEnvironmentTileSizeX, GReflectionEnvironmentTileSizeY,
|
|
NumBoxCaptures, NumSphereCaptures, bHasSkyLight);
|
|
|
|
ComputeShader = SelectReflectionEnvironmentTiledDeferredCS(View.ShaderMap, bUseLightmaps, bHasSkyLight, bHasBoxCaptures, bHasSphereCaptures, DynamicBentNormalAO != NULL);
|
|
|
|
//Really we should write this fence where we transition the final depedency for the reflections. We may add an RHI command just for writing fences if this
|
|
//can't be done in the general case. In the meantime, hack this command a bit to write the fence.
|
|
RHICmdList.TransitionResources(EResourceTransitionAccess::EReadable, EResourceTransitionPipeline::EGfxToCompute, nullptr, 0, ReflectionBeginFence);
|
|
|
|
//we must wait on the fence written from the Gfx pipe to let us know all our dependencies are ready.
|
|
RHICmdListComputeImmediate.WaitComputeFence(ReflectionBeginFence);
|
|
|
|
//standard compute setup, but on the async commandlist.
|
|
RHICmdListComputeImmediate.SetComputeShader(ComputeShader->GetComputeShader());
|
|
|
|
FUnorderedAccessViewRHIParamRef OutUAV = NewSceneColor->GetRenderTargetItem().UAV;
|
|
ComputeShader->SetParameters(RHICmdListComputeImmediate, View, SSROutput->GetRenderTargetItem().ShaderResourceTexture, SortData, OutUAV, DynamicBentNormalAO);
|
|
|
|
uint32 GroupSizeX = (View.ViewRect.Size().X + GReflectionEnvironmentTileSizeX - 1) / GReflectionEnvironmentTileSizeX;
|
|
uint32 GroupSizeY = (View.ViewRect.Size().Y + GReflectionEnvironmentTileSizeY - 1) / GReflectionEnvironmentTileSizeY;
|
|
DispatchComputeShader(RHICmdListComputeImmediate, ComputeShader, GroupSizeX, GroupSizeY, 1);
|
|
|
|
ComputeShader->UnsetParameters(RHICmdListComputeImmediate, OutUAV);
|
|
|
|
//transition the output to readable and write the fence to allow the Gfx pipe to carry on.
|
|
RHICmdListComputeImmediate.TransitionResources(EResourceTransitionAccess::EReadable, EResourceTransitionPipeline::EComputeToGfx, &OutUAV, 1, ReflectionEndFence);
|
|
}
|
|
|
|
//immediately dispatch our async compute commands to the RHI thread to be submitted to the GPU as soon as possible.
|
|
//dispatch after the scope so the drawevent pop is inside the dispatch
|
|
FRHIAsyncComputeCommandListImmediate::ImmediateDispatch(RHICmdListComputeImmediate);
|
|
|
|
//Gfx pipe must wait for the async compute reflection job to complete.
|
|
RHICmdList.WaitComputeFence(ReflectionEndFence);
|
|
}
|
|
}
|
|
|
|
SceneContext.SetSceneColor(NewSceneColor);
|
|
check(SceneContext.GetSceneColor());
|
|
}
|
|
|
|
void FDeferredShadingSceneRenderer::RenderStandardDeferredImageBasedReflections(FRHICommandListImmediate& RHICmdList, bool bReflectionEnv, const TRefCountPtr<IPooledRenderTarget>& DynamicBentNormalAO)
|
|
{
|
|
if(!ViewFamily.EngineShowFlags.Lighting)
|
|
{
|
|
return;
|
|
}
|
|
|
|
const bool bSkyLight = Scene->SkyLight
|
|
&& Scene->SkyLight->ProcessedTexture
|
|
&& !Scene->SkyLight->bHasStaticLighting
|
|
&& ViewFamily.EngineShowFlags.SkyLighting;
|
|
|
|
static TArray<FReflectionCaptureSortData> SortData;
|
|
|
|
if (bReflectionEnv)
|
|
{
|
|
// shared for multiple views
|
|
|
|
SortData.Reset(Scene->ReflectionSceneData.RegisteredReflectionCaptures.Num());
|
|
|
|
// Gather visible reflection capture data
|
|
for (int32 ReflectionProxyIndex = 0; ReflectionProxyIndex < Scene->ReflectionSceneData.RegisteredReflectionCaptures.Num() && SortData.Num() < GMaxNumReflectionCaptures; ReflectionProxyIndex++)
|
|
{
|
|
FReflectionCaptureProxy* CurrentCapture = Scene->ReflectionSceneData.RegisteredReflectionCaptures[ReflectionProxyIndex];
|
|
FReflectionCaptureSortData NewSortEntry;
|
|
|
|
NewSortEntry.CaptureIndex = -1;
|
|
|
|
if (FeatureLevel >= ERHIFeatureLevel::SM5)
|
|
{
|
|
const FCaptureComponentSceneState* ComponentStatePtr = Scene->ReflectionSceneData.AllocatedReflectionCaptureState.Find(CurrentCapture->Component);
|
|
NewSortEntry.CaptureIndex = ComponentStatePtr ? ComponentStatePtr->CaptureIndex : -1;
|
|
}
|
|
|
|
NewSortEntry.SM4FullHDRCubemap = CurrentCapture->SM4FullHDRCubemap;
|
|
NewSortEntry.Guid = CurrentCapture->Guid;
|
|
NewSortEntry.PositionAndRadius = FVector4(CurrentCapture->Position, CurrentCapture->InfluenceRadius);
|
|
float ShapeTypeValue = (float)CurrentCapture->Shape;
|
|
NewSortEntry.CaptureProperties = FVector4(CurrentCapture->Brightness, 0, ShapeTypeValue, 0);
|
|
NewSortEntry.CaptureOffset = FVector4(CurrentCapture->CaptureOffset);
|
|
|
|
if (CurrentCapture->Shape == EReflectionCaptureShape::Plane)
|
|
{
|
|
NewSortEntry.BoxTransform = FMatrix(
|
|
FPlane(CurrentCapture->ReflectionPlane),
|
|
FPlane(CurrentCapture->ReflectionXAxisAndYScale),
|
|
FPlane(0, 0, 0, 0),
|
|
FPlane(0, 0, 0, 0));
|
|
|
|
NewSortEntry.BoxScales = FVector4(0);
|
|
}
|
|
else
|
|
{
|
|
NewSortEntry.BoxTransform = CurrentCapture->BoxTransform;
|
|
|
|
NewSortEntry.BoxScales = FVector4(CurrentCapture->BoxScales, CurrentCapture->BoxTransitionDistance);
|
|
}
|
|
|
|
SortData.Add(NewSortEntry);
|
|
}
|
|
|
|
SortData.Sort();
|
|
}
|
|
FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList);
|
|
|
|
// Use standard deferred shading to composite reflection capture contribution
|
|
for (int32 ViewIndex = 0, Num = Views.Num(); ViewIndex < Num; ViewIndex++)
|
|
{
|
|
FViewInfo& View = Views[ViewIndex];
|
|
FSceneViewState* ViewState = (FSceneViewState*)View.State;
|
|
|
|
bool bLPV = false;
|
|
|
|
if(ViewState && ViewState->GetLightPropagationVolume(View.GetFeatureLevel()))
|
|
{
|
|
const FLightPropagationVolumeSettings& LPVSettings = View.FinalPostProcessSettings.BlendableManager.GetSingleFinalDataConst<FLightPropagationVolumeSettings>();
|
|
|
|
bLPV = LPVSettings.LPVIntensity > 0.0f;
|
|
}
|
|
|
|
bool bAmbient = View.FinalPostProcessSettings.ContributingCubemaps.Num() > 0;
|
|
bool bMixing = bLPV && (CVarLPVMixing.GetValueOnRenderThread() != 0);
|
|
bool bEnvironmentMixing = bMixing && (bAmbient || bLPV);
|
|
bool bRequiresApply = bSkyLight
|
|
// If Reflection Environment is active and mixed with indirect lighting (Ambient + LPV), apply is required!
|
|
|| (View.Family->EngineShowFlags.ReflectionEnvironment && (bReflectionEnv || bEnvironmentMixing) );
|
|
|
|
const bool bSSR = ShouldRenderScreenSpaceReflections(View);
|
|
|
|
TRefCountPtr<IPooledRenderTarget> SSROutput = GSystemTextures.BlackDummy;
|
|
if (bSSR)
|
|
{
|
|
bRequiresApply = true;
|
|
|
|
RenderScreenSpaceReflections(RHICmdList, View, SSROutput);
|
|
}
|
|
|
|
bool bApplyFromSSRTexture = bSSR;
|
|
|
|
if (RenderDeferredPlanarReflections(RHICmdList, true, SSROutput))
|
|
{
|
|
bRequiresApply = true;
|
|
bApplyFromSSRTexture = true;
|
|
}
|
|
|
|
/* Light Accumulation moved to SceneRenderTargets */
|
|
TRefCountPtr<IPooledRenderTarget> LightAccumulation = SceneContext.LightAccumulation;
|
|
|
|
if (!LightAccumulation)
|
|
{
|
|
// should never be used but during debugging it can happen
|
|
ensureMsgf(LightAccumulation, TEXT("White dummy system texture about to be corrupted."));
|
|
LightAccumulation = GSystemTextures.WhiteDummy;
|
|
}
|
|
|
|
if (bReflectionEnv)
|
|
{
|
|
bRequiresApply = true;
|
|
|
|
SCOPED_DRAW_EVENTF(RHICmdList, ReflectionEnvironment, TEXT("ReflectionEnvironment PixelShader"));
|
|
|
|
{
|
|
// Clear to no reflection contribution, alpha of 1 indicates full background contribution
|
|
ESimpleRenderTargetMode SimpleRenderTargetMode = ESimpleRenderTargetMode::EExistingColorAndDepth;
|
|
|
|
// If Reflection Environment is mixed with indirect lighting (Ambient + LPV), skip clear!
|
|
if (!bMixing)
|
|
{
|
|
SimpleRenderTargetMode = ESimpleRenderTargetMode::EClearColorExistingDepth;
|
|
}
|
|
SetRenderTarget(RHICmdList, LightAccumulation->GetRenderTargetItem().TargetableTexture, NULL, SimpleRenderTargetMode);
|
|
}
|
|
|
|
|
|
RHICmdList.SetViewport(View.ViewRect.Min.X, View.ViewRect.Min.Y, 0.0f, View.ViewRect.Max.X, View.ViewRect.Max.Y, 1.0f);
|
|
|
|
// rgb accumulates reflection contribution front to back, alpha accumulates (1 - alpha0) * (1 - alpha 1)...
|
|
RHICmdList.SetBlendState(TStaticBlendState<CW_RGBA, BO_Add, BF_DestAlpha, BF_One, BO_Add, BF_Zero, BF_InverseSourceAlpha>::GetRHI());
|
|
|
|
for (int32 ReflectionCaptureIndex = 0; ReflectionCaptureIndex < SortData.Num(); ReflectionCaptureIndex++)
|
|
{
|
|
const FReflectionCaptureSortData& ReflectionCapture = SortData[ReflectionCaptureIndex];
|
|
|
|
if (FeatureLevel >= ERHIFeatureLevel::SM5 || ReflectionCapture.SM4FullHDRCubemap)
|
|
{
|
|
const FSphere LightBounds(ReflectionCapture.PositionAndRadius, ReflectionCapture.PositionAndRadius.W);
|
|
|
|
TShaderMapRef<TDeferredLightVS<true> > VertexShader(View.ShaderMap);
|
|
|
|
// Use the appropriate shader for the capture shape
|
|
if (ReflectionCapture.CaptureProperties.Z == 0)
|
|
{
|
|
TShaderMapRef<TStandardDeferredReflectionPS<true> > PixelShader(View.ShaderMap);
|
|
|
|
static FGlobalBoundShaderState BoundShaderState;
|
|
|
|
SetGlobalBoundShaderState(RHICmdList, FeatureLevel, BoundShaderState, GetVertexDeclarationFVector4(), *VertexShader, *PixelShader);
|
|
|
|
PixelShader->SetParameters(RHICmdList, View, ReflectionCapture);
|
|
}
|
|
else
|
|
{
|
|
TShaderMapRef<TStandardDeferredReflectionPS<false> > PixelShader(View.ShaderMap);
|
|
|
|
static FGlobalBoundShaderState BoundShaderState;
|
|
|
|
SetGlobalBoundShaderState(RHICmdList, FeatureLevel, BoundShaderState, GetVertexDeclarationFVector4(), *VertexShader, *PixelShader);
|
|
|
|
PixelShader->SetParameters(RHICmdList, View, ReflectionCapture);
|
|
}
|
|
|
|
SetBoundingGeometryRasterizerAndDepthState(RHICmdList, View, LightBounds);
|
|
VertexShader->SetSimpleLightParameters(RHICmdList, View, LightBounds);
|
|
StencilingGeometry::DrawSphere(RHICmdList);
|
|
}
|
|
}
|
|
RHICmdList.CopyToResolveTarget(LightAccumulation->GetRenderTargetItem().TargetableTexture, LightAccumulation->GetRenderTargetItem().ShaderResourceTexture, false, FResolveParams());
|
|
|
|
GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, LightAccumulation);
|
|
}
|
|
|
|
if (bRequiresApply)
|
|
{
|
|
// Apply reflections to screen
|
|
SCOPED_DRAW_EVENT(RHICmdList, ReflectionApply);
|
|
|
|
SceneContext.BeginRenderingSceneColor(RHICmdList, ESimpleRenderTargetMode::EUninitializedColorExistingDepth, FExclusiveDepthStencil::DepthRead_StencilWrite, true);
|
|
|
|
RHICmdList.SetViewport(View.ViewRect.Min.X, View.ViewRect.Min.Y, 0.0f, View.ViewRect.Max.X, View.ViewRect.Max.Y, 1.0f);
|
|
RHICmdList.SetRasterizerState(TStaticRasterizerState<FM_Solid, CM_None>::GetRHI());
|
|
RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI());
|
|
|
|
if (GetReflectionEnvironmentCVar() == 2)
|
|
{
|
|
// override scene color for debugging
|
|
RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI());
|
|
}
|
|
else
|
|
{
|
|
// additive to scene color
|
|
RHICmdList.SetBlendState(TStaticBlendState<CW_RGBA, BO_Add, BF_One, BF_One, BO_Add, BF_One, BF_One>::GetRHI());
|
|
}
|
|
|
|
TShaderMapRef< FPostProcessVS > VertexShader(View.ShaderMap);
|
|
|
|
// Activate Reflection Environment if we choose to mix it with indirect lighting (Ambient + LPV)
|
|
// todo: refactor (we abuse another boolean to pass the data through)
|
|
bReflectionEnv = bReflectionEnv || bEnvironmentMixing;
|
|
|
|
const bool bSupportDFAOIndirectShadowing = DynamicBentNormalAO != NULL;
|
|
|
|
#define CASE(A,B,C,D) \
|
|
case ((A << 3) | (B << 2) | (C << 1) | D) : \
|
|
{ \
|
|
TShaderMapRef< FReflectionApplyPS<A, B, C, D> > PixelShader(View.ShaderMap); \
|
|
static FGlobalBoundShaderState BoundShaderState; \
|
|
SetGlobalBoundShaderState(RHICmdList, FeatureLevel, BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); \
|
|
PixelShader->SetParameters(RHICmdList, View, LightAccumulation->GetRenderTargetItem().ShaderResourceTexture, SSROutput->GetRenderTargetItem().ShaderResourceTexture, DynamicBentNormalAO); \
|
|
}; \
|
|
break
|
|
|
|
switch (((uint32)bApplyFromSSRTexture << 3) | ((uint32)bReflectionEnv << 2) | ((uint32)bSkyLight << 1) | (uint32)bSupportDFAOIndirectShadowing)
|
|
{
|
|
CASE(0, 0, 0, 0);
|
|
CASE(0, 0, 1, 0);
|
|
CASE(0, 1, 0, 0);
|
|
CASE(0, 1, 1, 0);
|
|
CASE(1, 0, 0, 0);
|
|
CASE(1, 0, 1, 0);
|
|
CASE(1, 1, 0, 0);
|
|
CASE(1, 1, 1, 0);
|
|
CASE(0, 0, 0, 1);
|
|
CASE(0, 0, 1, 1);
|
|
CASE(0, 1, 0, 1);
|
|
CASE(0, 1, 1, 1);
|
|
CASE(1, 0, 0, 1);
|
|
CASE(1, 0, 1, 1);
|
|
CASE(1, 1, 0, 1);
|
|
CASE(1, 1, 1, 1);
|
|
}
|
|
#undef CASE
|
|
|
|
DrawRectangle(
|
|
RHICmdList,
|
|
0, 0,
|
|
View.ViewRect.Width(), View.ViewRect.Height(),
|
|
View.ViewRect.Min.X, View.ViewRect.Min.Y,
|
|
View.ViewRect.Width(), View.ViewRect.Height(),
|
|
FIntPoint(View.ViewRect.Width(), View.ViewRect.Height()),
|
|
SceneContext.GetBufferSizeXY(),
|
|
*VertexShader);
|
|
|
|
SceneContext.FinishRenderingSceneColor(RHICmdList);
|
|
}
|
|
}
|
|
}
|
|
|
|
void FDeferredShadingSceneRenderer::RenderDeferredReflections(FRHICommandListImmediate& RHICmdList, const TRefCountPtr<IPooledRenderTarget>& DynamicBentNormalAO)
|
|
{
|
|
if (ViewFamily.EngineShowFlags.VisualizeLightCulling)
|
|
{
|
|
return;
|
|
}
|
|
|
|
bool bAnyViewIsReflectionCapture = false;
|
|
for (int32 ViewIndex = 0, Num = Views.Num(); ViewIndex < Num; ViewIndex++)
|
|
{
|
|
const FViewInfo& View = Views[ViewIndex];
|
|
bAnyViewIsReflectionCapture = bAnyViewIsReflectionCapture || View.bIsReflectionCapture;
|
|
}
|
|
|
|
// If we're currently capturing a reflection capture, output SpecularColor * IndirectIrradiance for metals so they are not black in reflections,
|
|
// Since we don't have multiple bounce specular reflections
|
|
if (bAnyViewIsReflectionCapture)
|
|
{
|
|
RenderReflectionCaptureSpecularBounceForAllViews(RHICmdList);
|
|
}
|
|
else
|
|
{
|
|
const uint32 bDoTiledReflections = CVarDoTiledReflections.GetValueOnRenderThread() != 0;
|
|
const bool bReflectionEnvironment = ShouldDoReflectionEnvironment();
|
|
const bool bReflectionsWithCompute = bDoTiledReflections && (FeatureLevel >= ERHIFeatureLevel::SM5) && bReflectionEnvironment && Scene->ReflectionSceneData.CubemapArray.IsValid();
|
|
|
|
if (bReflectionsWithCompute)
|
|
{
|
|
RenderTiledDeferredImageBasedReflections(RHICmdList, DynamicBentNormalAO);
|
|
}
|
|
else
|
|
{
|
|
RenderStandardDeferredImageBasedReflections(RHICmdList, bReflectionEnvironment, DynamicBentNormalAO);
|
|
}
|
|
}
|
|
}
|