Files
UnrealEngineUWP/Engine/Source/Runtime/Renderer/Private/DistanceFieldGlobalIllumination.cpp
Mike Fricker 114458bf0f Clang warning fixes: Fixed missing 'override' specifiers
- Also removed some unreferenced functions that adding 'override' revealed

PR #1002 -- Thank you, Omar007!

[CL 2498415 by Mike Fricker in Main branch]
2015-04-01 07:20:55 -04:00

1390 lines
54 KiB
C++

// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
/*=============================================================================
DistanceFieldGlobalIllumination.cpp
=============================================================================*/
#include "RendererPrivate.h"
#include "ScenePrivate.h"
#include "UniformBuffer.h"
#include "ShaderParameters.h"
#include "PostProcessing.h"
#include "SceneFilterRendering.h"
#include "DistanceFieldLightingShared.h"
#include "DistanceFieldSurfaceCacheLighting.h"
#include "DistanceFieldGlobalIllumination.h"
#include "RHICommandList.h"
#include "SceneUtils.h"
#include "DistanceFieldAtlas.h"
int32 GDistanceFieldGI = 0;
FAutoConsoleVariableRef CVarDistanceFieldGI(
TEXT("r.DistanceFieldGI"),
GDistanceFieldGI,
TEXT(""),
ECVF_Cheat | ECVF_RenderThreadSafe | ECVF_ReadOnly
);
int32 GVPLMeshGlobalIllumination = 1;
FAutoConsoleVariableRef CVarVPLMeshGlobalIllumination(
TEXT("r.VPLMeshGlobalIllumination"),
GVPLMeshGlobalIllumination,
TEXT(""),
ECVF_Cheat | ECVF_RenderThreadSafe
);
int32 GVPLSurfelRepresentation = 1;
FAutoConsoleVariableRef CVarVPLSurfelRepresentation(
TEXT("r.VPLSurfelRepresentation"),
GVPLSurfelRepresentation,
TEXT(""),
ECVF_Cheat | ECVF_RenderThreadSafe
);
int32 GVPLGridDimension = 128;
FAutoConsoleVariableRef CVarVPLGridDimension(
TEXT("r.VPLGridDimension"),
GVPLGridDimension,
TEXT(""),
ECVF_Cheat | ECVF_RenderThreadSafe
);
float GVPLDirectionalLightTraceDistance = 100000;
FAutoConsoleVariableRef CVarVPLDirectionalLightTraceDistance(
TEXT("r.VPLDirectionalLightTraceDistance"),
GVPLDirectionalLightTraceDistance,
TEXT(""),
ECVF_Cheat | ECVF_RenderThreadSafe
);
float GVPLPlacementCameraRadius = 4000;
FAutoConsoleVariableRef CVarVPLPlacementCameraRadius(
TEXT("r.VPLPlacementCameraRadius"),
GVPLPlacementCameraRadius,
TEXT(""),
ECVF_Cheat | ECVF_RenderThreadSafe
);
int32 GVPLViewCulling = 1;
FAutoConsoleVariableRef CVarVPLViewCulling(
TEXT("r.VPLViewCulling"),
GVPLViewCulling,
TEXT(""),
ECVF_Cheat | ECVF_RenderThreadSafe
);
int32 GAOUseConesForGI = 1;
FAutoConsoleVariableRef CVarAOUseConesForGI(
TEXT("r.AOUseConesForGI"),
GAOUseConesForGI,
TEXT(""),
ECVF_Cheat | ECVF_RenderThreadSafe
);
int32 GVPLSpreadUpdateOver = 5;
FAutoConsoleVariableRef CVarVPLSpreadUpdateOver(
TEXT("r.VPLSpreadUpdateOver"),
GVPLSpreadUpdateOver,
TEXT(""),
ECVF_Cheat | ECVF_RenderThreadSafe
);
float GVPLSelfOcclusionReplacement = .3f;
FAutoConsoleVariableRef CVarVPLSelfOcclusionReplacement(
TEXT("r.VPLSelfOcclusionReplacement"),
GVPLSelfOcclusionReplacement,
TEXT(""),
ECVF_Cheat | ECVF_RenderThreadSafe
);
TGlobalResource<FVPLResources> GVPLResources;
TGlobalResource<FVPLResources> GCulledVPLResources;
extern TGlobalResource<FDistanceFieldObjectBufferResource> GShadowCulledObjectBuffers;
class FVPLPlacementCS : public FGlobalShader
{
DECLARE_SHADER_TYPE(FVPLPlacementCS, Global);
public:
static bool ShouldCache(EShaderPlatform Platform)
{
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM5) && DoesPlatformSupportDistanceFieldGI(Platform);
}
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
{
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZEX"), GDistanceFieldAOTileSizeX);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZEY"), GDistanceFieldAOTileSizeY);
}
/** Default constructor. */
FVPLPlacementCS() {}
/** Initialization constructor. */
FVPLPlacementCS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{
VPLParameterBuffer.Bind(Initializer.ParameterMap, TEXT("VPLParameterBuffer"));
VPLData.Bind(Initializer.ParameterMap, TEXT("VPLData"));
InvPlacementGridSize.Bind(Initializer.ParameterMap, TEXT("InvPlacementGridSize"));
WorldToShadow.Bind(Initializer.ParameterMap, TEXT("WorldToShadow"));
ShadowToWorld.Bind(Initializer.ParameterMap, TEXT("ShadowToWorld"));
LightDirectionAndTraceDistance.Bind(Initializer.ParameterMap, TEXT("LightDirectionAndTraceDistance"));
LightColor.Bind(Initializer.ParameterMap, TEXT("LightColor"));
ObjectParameters.Bind(Initializer.ParameterMap);
ShadowTileHeadDataUnpacked.Bind(Initializer.ParameterMap, TEXT("ShadowTileHeadDataUnpacked"));
ShadowTileArrayData.Bind(Initializer.ParameterMap, TEXT("ShadowTileArrayData"));
ShadowTileListGroupSize.Bind(Initializer.ParameterMap, TEXT("ShadowTileListGroupSize"));
VPLPlacementCameraRadius.Bind(Initializer.ParameterMap, TEXT("VPLPlacementCameraRadius"));
}
void SetParameters(
FRHICommandList& RHICmdList,
const FSceneView& View,
const FLightSceneProxy* LightSceneProxy,
FVector2D InvPlacementGridSizeValue,
const FMatrix& WorldToShadowValue,
const FMatrix& ShadowToWorldValue,
FLightTileIntersectionResources* TileIntersectionResources)
{
const FComputeShaderRHIParamRef ShaderRHI = GetComputeShader();
FGlobalShader::SetParameters(RHICmdList, ShaderRHI, View);
ObjectParameters.Set(RHICmdList, ShaderRHI, GShadowCulledObjectBuffers.Buffers);
SetShaderValue(RHICmdList, ShaderRHI, InvPlacementGridSize, InvPlacementGridSizeValue);
SetShaderValue(RHICmdList, ShaderRHI, WorldToShadow, WorldToShadowValue);
SetShaderValue(RHICmdList, ShaderRHI, ShadowToWorld, ShadowToWorldValue);
SetShaderValue(RHICmdList, ShaderRHI, LightDirectionAndTraceDistance, FVector4(LightSceneProxy->GetDirection(), GVPLDirectionalLightTraceDistance));
SetShaderValue(RHICmdList, ShaderRHI, LightColor, LightSceneProxy->GetColor() * LightSceneProxy->GetIndirectLightingScale());
VPLParameterBuffer.SetBuffer(RHICmdList, ShaderRHI, GVPLResources.VPLParameterBuffer);
VPLData.SetBuffer(RHICmdList, ShaderRHI, GVPLResources.VPLData);
check(TileIntersectionResources || !ShadowTileHeadDataUnpacked.IsBound());
if (TileIntersectionResources)
{
SetSRVParameter(RHICmdList, ShaderRHI, ShadowTileHeadDataUnpacked, TileIntersectionResources->TileHeadDataUnpacked.SRV);
SetSRVParameter(RHICmdList, ShaderRHI, ShadowTileArrayData, TileIntersectionResources->TileArrayData.SRV);
SetShaderValue(RHICmdList, ShaderRHI, ShadowTileListGroupSize, TileIntersectionResources->TileDimensions);
}
SetShaderValue(RHICmdList, ShaderRHI, VPLPlacementCameraRadius, GVPLPlacementCameraRadius);
}
void UnsetParameters(FRHICommandList& RHICmdList)
{
VPLParameterBuffer.UnsetUAV(RHICmdList, GetComputeShader());
VPLData.UnsetUAV(RHICmdList, GetComputeShader());
}
// FShader interface.
virtual bool Serialize(FArchive& Ar) override
{
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
Ar << VPLParameterBuffer;
Ar << VPLData;
Ar << InvPlacementGridSize;
Ar << WorldToShadow;
Ar << ShadowToWorld;
Ar << LightDirectionAndTraceDistance;
Ar << LightColor;
Ar << ObjectParameters;
Ar << ShadowTileHeadDataUnpacked;
Ar << ShadowTileArrayData;
Ar << ShadowTileListGroupSize;
Ar << VPLPlacementCameraRadius;
return bShaderHasOutdatedParameters;
}
private:
FRWShaderParameter VPLParameterBuffer;
FRWShaderParameter VPLData;
FShaderParameter InvPlacementGridSize;
FShaderParameter WorldToShadow;
FShaderParameter ShadowToWorld;
FShaderParameter LightDirectionAndTraceDistance;
FShaderParameter LightColor;
FDistanceFieldCulledObjectBufferParameters ObjectParameters;
FShaderResourceParameter ShadowTileHeadDataUnpacked;
FShaderResourceParameter ShadowTileArrayData;
FShaderParameter ShadowTileListGroupSize;
FShaderParameter VPLPlacementCameraRadius;
};
IMPLEMENT_SHADER_TYPE(,FVPLPlacementCS,TEXT("DistanceFieldGlobalIllumination"),TEXT("VPLPlacementCS"),SF_Compute);
class FSetupVPLCullndirectArgumentsCS : public FGlobalShader
{
DECLARE_SHADER_TYPE(FSetupVPLCullndirectArgumentsCS,Global)
public:
static bool ShouldCache(EShaderPlatform Platform)
{
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM5) && DoesPlatformSupportDistanceFieldGI(Platform);
}
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Platform,OutEnvironment);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZEX"), GDistanceFieldAOTileSizeX);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZEY"), GDistanceFieldAOTileSizeY);
}
FSetupVPLCullndirectArgumentsCS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{
DispatchParameters.Bind(Initializer.ParameterMap, TEXT("DispatchParameters"));
VPLParameterBuffer.Bind(Initializer.ParameterMap, TEXT("VPLParameterBuffer"));
}
FSetupVPLCullndirectArgumentsCS()
{
}
void SetParameters(FRHICommandList& RHICmdList, const FSceneView& View)
{
FComputeShaderRHIParamRef ShaderRHI = GetComputeShader();
FGlobalShader::SetParameters(RHICmdList, ShaderRHI, View);
DispatchParameters.SetBuffer(RHICmdList, ShaderRHI, GVPLResources.VPLDispatchIndirectBuffer);
SetSRVParameter(RHICmdList, ShaderRHI, VPLParameterBuffer, GVPLResources.VPLParameterBuffer.SRV);
}
void UnsetParameters(FRHICommandList& RHICmdList)
{
DispatchParameters.UnsetUAV(RHICmdList, GetComputeShader());
}
virtual bool Serialize(FArchive& Ar) override
{
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
Ar << DispatchParameters;
Ar << VPLParameterBuffer;
return bShaderHasOutdatedParameters;
}
private:
FRWShaderParameter DispatchParameters;
FShaderResourceParameter VPLParameterBuffer;
};
IMPLEMENT_SHADER_TYPE(,FSetupVPLCullndirectArgumentsCS,TEXT("DistanceFieldGlobalIllumination"),TEXT("SetupVPLCullndirectArgumentsCS"),SF_Compute);
class FCullVPLsForViewCS : public FGlobalShader
{
DECLARE_SHADER_TYPE(FCullVPLsForViewCS,Global)
public:
static bool ShouldCache(EShaderPlatform Platform)
{
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM5) && DoesPlatformSupportDistanceFieldGI(Platform);
}
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Platform,OutEnvironment);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZEX"), GDistanceFieldAOTileSizeX);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZEY"), GDistanceFieldAOTileSizeY);
}
FCullVPLsForViewCS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{
VPLParameterBuffer.Bind(Initializer.ParameterMap, TEXT("VPLParameterBuffer"));
VPLData.Bind(Initializer.ParameterMap, TEXT("VPLData"));
CulledVPLParameterBuffer.Bind(Initializer.ParameterMap, TEXT("CulledVPLParameterBuffer"));
CulledVPLData.Bind(Initializer.ParameterMap, TEXT("CulledVPLData"));
AOParameters.Bind(Initializer.ParameterMap);
NumConvexHullPlanes.Bind(Initializer.ParameterMap, TEXT("NumConvexHullPlanes"));
ViewFrustumConvexHull.Bind(Initializer.ParameterMap, TEXT("ViewFrustumConvexHull"));
}
FCullVPLsForViewCS()
{
}
void SetParameters(FRHICommandList& RHICmdList, const FScene* Scene, const FSceneView& View, const FDistanceFieldAOParameters& Parameters)
{
FComputeShaderRHIParamRef ShaderRHI = GetComputeShader();
FGlobalShader::SetParameters(RHICmdList, ShaderRHI, View);
CulledVPLParameterBuffer.SetBuffer(RHICmdList, ShaderRHI, GCulledVPLResources.VPLParameterBuffer);
CulledVPLData.SetBuffer(RHICmdList, ShaderRHI, GCulledVPLResources.VPLData);
AOParameters.Set(RHICmdList, ShaderRHI, Parameters);
SetSRVParameter(RHICmdList, ShaderRHI, VPLParameterBuffer, GVPLResources.VPLParameterBuffer.SRV);
SetSRVParameter(RHICmdList, ShaderRHI, VPLData, GVPLResources.VPLData.SRV);
// Shader assumes max 6
check(View.ViewFrustum.Planes.Num() <= 6);
SetShaderValue(RHICmdList, ShaderRHI, NumConvexHullPlanes, View.ViewFrustum.Planes.Num());
SetShaderValueArray(RHICmdList, ShaderRHI, ViewFrustumConvexHull, View.ViewFrustum.Planes.GetData(), View.ViewFrustum.Planes.Num());
}
void UnsetParameters(FRHICommandList& RHICmdList)
{
CulledVPLParameterBuffer.UnsetUAV(RHICmdList, GetComputeShader());
CulledVPLData.UnsetUAV(RHICmdList, GetComputeShader());
}
virtual bool Serialize(FArchive& Ar) override
{
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
Ar << VPLParameterBuffer;
Ar << VPLData;
Ar << CulledVPLParameterBuffer;
Ar << CulledVPLData;
Ar << AOParameters;
Ar << NumConvexHullPlanes;
Ar << ViewFrustumConvexHull;
return bShaderHasOutdatedParameters;
}
private:
FShaderResourceParameter VPLParameterBuffer;
FShaderResourceParameter VPLData;
FRWShaderParameter CulledVPLParameterBuffer;
FRWShaderParameter CulledVPLData;
FAOParameters AOParameters;
FShaderParameter NumConvexHullPlanes;
FShaderParameter ViewFrustumConvexHull;
};
IMPLEMENT_SHADER_TYPE(,FCullVPLsForViewCS,TEXT("DistanceFieldGlobalIllumination"),TEXT("CullVPLsForViewCS"),SF_Compute);
TScopedPointer<FLightTileIntersectionResources> GVPLPlacementTileIntersectionResources;
void PlaceVPLs(
FRHICommandListImmediate& RHICmdList,
const FViewInfo& View,
const FScene* Scene,
const FDistanceFieldAOParameters& Parameters)
{
GVPLResources.AllocateFor(GVPLGridDimension * GVPLGridDimension);
{
uint32 ClearValues[4] = { 0 };
RHICmdList.ClearUAV(GVPLResources.VPLParameterBuffer.UAV, ClearValues);
}
const FLightSceneProxy* DirectionalLightProxy = NULL;
for (TSparseArray<FLightSceneInfoCompact>::TConstIterator LightIt(Scene->Lights); LightIt; ++LightIt)
{
const FLightSceneInfoCompact& LightSceneInfoCompact = *LightIt;
const FLightSceneInfo* const LightSceneInfo = LightSceneInfoCompact.LightSceneInfo;
if (LightSceneInfo->ShouldRenderLightViewIndependent()
&& LightSceneInfo->Proxy->GetLightType() == LightType_Directional
&& LightSceneInfo->Proxy->CastsDynamicShadow())
{
DirectionalLightProxy = LightSceneInfo->Proxy;
break;
}
}
if (DirectionalLightProxy)
{
SCOPED_DRAW_EVENT(RHICmdList, VPLPlacement);
FMatrix DirectionalLightShadowToWorld;
{
int32 NumPlanes = 0;
const FPlane* PlaneData = NULL;
FVector4 ShadowBoundingSphereValue(0, 0, 0, 0);
FShadowCascadeSettings CascadeSettings;
FSphere ShadowBounds;
FConvexVolume FrustumVolume;
static bool bUseShadowmapBounds = true;
if (bUseShadowmapBounds)
{
ShadowBounds = DirectionalLightProxy->GetShadowSplitBoundsDepthRange(
View,
View.ViewMatrices.ViewOrigin,
View.NearClippingDistance,
GVPLPlacementCameraRadius,
&CascadeSettings);
FSphere SubjectBounds(FVector::ZeroVector, ShadowBounds.W);
const FMatrix& WorldToLight = DirectionalLightProxy->GetWorldToLight();
const FMatrix InitializerWorldToLight = FInverseRotationMatrix(FVector(WorldToLight.M[0][0],WorldToLight.M[1][0],WorldToLight.M[2][0]).GetSafeNormal().Rotation());
const FVector InitializerFaceDirection = FVector(1,0,0);
FVector XAxis, YAxis;
InitializerFaceDirection.FindBestAxisVectors(XAxis, YAxis);
const FMatrix WorldToLightScaled = InitializerWorldToLight * FScaleMatrix(FVector(1.0f,1.0f / SubjectBounds.W,1.0f / SubjectBounds.W));
const FMatrix WorldToFace = WorldToLightScaled * FBasisVectorMatrix(-XAxis,YAxis,InitializerFaceDirection.GetSafeNormal(),FVector::ZeroVector);
static bool bSnapPosition = true;
if (bSnapPosition)
{
// Transform the shadow's position into shadowmap space
const FVector TransformedPosition = WorldToFace.TransformPosition(ShadowBounds.Center);
// Determine the distance necessary to snap the shadow's position to the nearest texel
const float SnapX = FMath::Fmod(TransformedPosition.X, 2.0f / GVPLGridDimension);
const float SnapY = FMath::Fmod(TransformedPosition.Y, 2.0f / GVPLGridDimension);
// Snap the shadow's position and transform it back into world space
// This snapping prevents sub-texel camera movements which removes view dependent aliasing from the final shadow result
// This only maintains stable shadows under camera translation and rotation
const FVector SnappedWorldPosition = WorldToFace.InverseFast().TransformPosition(TransformedPosition - FVector(SnapX, SnapY, 0.0f));
ShadowBounds.Center = SnappedWorldPosition;
}
NumPlanes = CascadeSettings.ShadowBoundsAccurate.Planes.Num();
PlaneData = CascadeSettings.ShadowBoundsAccurate.Planes.GetData();
DirectionalLightShadowToWorld = FTranslationMatrix(-ShadowBounds.Center) * WorldToFace * FShadowProjectionMatrix(-GVPLDirectionalLightTraceDistance / 2, GVPLDirectionalLightTraceDistance / 2, FVector4(0,0,0,1));
}
else
{
ShadowBounds = FSphere(View.ViewMatrices.ViewOrigin, GVPLPlacementCameraRadius);
FSphere SubjectBounds(FVector::ZeroVector, ShadowBounds.W);
const FMatrix& WorldToLight = DirectionalLightProxy->GetWorldToLight();
const FMatrix InitializerWorldToLight = FInverseRotationMatrix(FVector(WorldToLight.M[0][0],WorldToLight.M[1][0],WorldToLight.M[2][0]).GetSafeNormal().Rotation());
const FVector InitializerFaceDirection = FVector(1,0,0);
FVector XAxis, YAxis;
InitializerFaceDirection.FindBestAxisVectors(XAxis, YAxis);
const FMatrix WorldToLightScaled = InitializerWorldToLight * FScaleMatrix(FVector(1.0f,1.0f / GVPLPlacementCameraRadius,1.0f / GVPLPlacementCameraRadius));
const FMatrix WorldToFace = WorldToLightScaled * FBasisVectorMatrix(-XAxis,YAxis,InitializerFaceDirection.GetSafeNormal(),FVector::ZeroVector);
static bool bSnapPosition = true;
if (bSnapPosition)
{
// Transform the shadow's position into shadowmap space
const FVector TransformedPosition = WorldToFace.TransformPosition(ShadowBounds.Center);
// Determine the distance necessary to snap the shadow's position to the nearest texel
const float SnapX = FMath::Fmod(TransformedPosition.X, 2.0f / GVPLGridDimension);
const float SnapY = FMath::Fmod(TransformedPosition.Y, 2.0f / GVPLGridDimension);
// Snap the shadow's position and transform it back into world space
// This snapping prevents sub-texel camera movements which removes view dependent aliasing from the final shadow result
// This only maintains stable shadows under camera translation and rotation
const FVector SnappedWorldPosition = WorldToFace.InverseFast().TransformPosition(TransformedPosition - FVector(SnapX, SnapY, 0.0f));
ShadowBounds.Center = SnappedWorldPosition;
}
const float MaxSubjectZ = WorldToFace.TransformPosition(SubjectBounds.Center).Z + SubjectBounds.W;
const float MinSubjectZ = FMath::Max(MaxSubjectZ - SubjectBounds.W * 2, (float)-HALF_WORLD_MAX);
//@todo - naming is wrong and maybe derived matrices
DirectionalLightShadowToWorld = FTranslationMatrix(-ShadowBounds.Center) * WorldToFace * FShadowProjectionMatrix(MinSubjectZ, MaxSubjectZ, FVector4(0,0,0,1));
GetViewFrustumBounds(FrustumVolume, DirectionalLightShadowToWorld, true);
NumPlanes = FrustumVolume.Planes.Num();
PlaneData = FrustumVolume.Planes.GetData();
}
CullDistanceFieldObjectsForLight(
RHICmdList,
View,
DirectionalLightProxy,
DirectionalLightShadowToWorld,
NumPlanes,
PlaneData,
ShadowBoundingSphereValue,
ShadowBounds.W,
GVPLPlacementTileIntersectionResources);
}
{
SCOPED_DRAW_EVENT(RHICmdList, PlaceVPLs);
TShaderMapRef<FVPLPlacementCS> ComputeShader(View.ShaderMap);
RHICmdList.SetComputeShader(ComputeShader->GetComputeShader());
ComputeShader->SetParameters(RHICmdList, View, DirectionalLightProxy, FVector2D(1.0f / GVPLGridDimension, 1.0f / GVPLGridDimension), DirectionalLightShadowToWorld, DirectionalLightShadowToWorld.InverseFast(), GVPLPlacementTileIntersectionResources);
DispatchComputeShader(RHICmdList, *ComputeShader, FMath::DivideAndRoundUp<int32>(GVPLGridDimension, GDistanceFieldAOTileSizeX), FMath::DivideAndRoundUp<int32>(GVPLGridDimension, GDistanceFieldAOTileSizeY), 1);
ComputeShader->UnsetParameters(RHICmdList);
}
if (GVPLViewCulling)
{
{
TShaderMapRef<FSetupVPLCullndirectArgumentsCS> ComputeShader(View.ShaderMap);
RHICmdList.SetComputeShader(ComputeShader->GetComputeShader());
ComputeShader->SetParameters(RHICmdList, View);
DispatchComputeShader(RHICmdList, *ComputeShader, 1, 1, 1);
ComputeShader->UnsetParameters(RHICmdList);
}
{
GCulledVPLResources.AllocateFor(GVPLGridDimension * GVPLGridDimension);
uint32 ClearValues[4] = { 0 };
RHICmdList.ClearUAV(GCulledVPLResources.VPLParameterBuffer.UAV, ClearValues);
TShaderMapRef<FCullVPLsForViewCS> ComputeShader(GetGlobalShaderMap(Scene->GetFeatureLevel()));
RHICmdList.SetComputeShader(ComputeShader->GetComputeShader());
ComputeShader->SetParameters(RHICmdList, Scene, View, Parameters);
DispatchIndirectComputeShader(RHICmdList, *ComputeShader, GVPLResources.VPLDispatchIndirectBuffer.Buffer, 0);
ComputeShader->UnsetParameters(RHICmdList);
}
}
}
}
const int32 LightVPLsThreadGroupSize = 64;
class FSetupLightVPLsIndirectArgumentsCS : public FGlobalShader
{
DECLARE_SHADER_TYPE(FSetupLightVPLsIndirectArgumentsCS,Global)
public:
static bool ShouldCache(EShaderPlatform Platform)
{
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM5) && DoesPlatformSupportDistanceFieldGI(Platform);
}
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Platform,OutEnvironment);
OutEnvironment.SetDefine(TEXT("LIGHT_VPLS_THREADGROUP_SIZE"), LightVPLsThreadGroupSize);
}
FSetupLightVPLsIndirectArgumentsCS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{
DispatchParameters.Bind(Initializer.ParameterMap, TEXT("DispatchParameters"));
ObjectParameters.Bind(Initializer.ParameterMap);
ObjectProcessStride.Bind(Initializer.ParameterMap, TEXT("ObjectProcessStride"));
}
FSetupLightVPLsIndirectArgumentsCS()
{
}
void SetParameters(FRHICommandList& RHICmdList, const FSceneView& View)
{
FComputeShaderRHIParamRef ShaderRHI = GetComputeShader();
FGlobalShader::SetParameters(RHICmdList, ShaderRHI, View);
DispatchParameters.SetBuffer(RHICmdList, ShaderRHI, GAOCulledObjectBuffers.Buffers.ObjectIndirectDispatch);
ObjectParameters.Set(RHICmdList, ShaderRHI, GAOCulledObjectBuffers.Buffers);
SetShaderValue(RHICmdList, ShaderRHI, ObjectProcessStride, GVPLSpreadUpdateOver);
}
void UnsetParameters(FRHICommandList& RHICmdList)
{
DispatchParameters.UnsetUAV(RHICmdList, GetComputeShader());
}
virtual bool Serialize(FArchive& Ar) override
{
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
Ar << DispatchParameters;
Ar << ObjectParameters;
Ar << ObjectProcessStride;
return bShaderHasOutdatedParameters;
}
private:
FRWShaderParameter DispatchParameters;
FDistanceFieldCulledObjectBufferParameters ObjectParameters;
FShaderParameter ObjectProcessStride;
};
IMPLEMENT_SHADER_TYPE(,FSetupLightVPLsIndirectArgumentsCS,TEXT("DistanceFieldGlobalIllumination"),TEXT("SetupLightVPLsIndirectArgumentsCS"),SF_Compute);
class FLightVPLsCS : public FGlobalShader
{
DECLARE_SHADER_TYPE(FLightVPLsCS, Global);
public:
static bool ShouldCache(EShaderPlatform Platform)
{
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM5) && DoesPlatformSupportDistanceFieldGI(Platform);
}
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
{
OutEnvironment.SetDefine(TEXT("LIGHT_VPLS_THREADGROUP_SIZE"), LightVPLsThreadGroupSize);
}
/** Default constructor. */
FLightVPLsCS() {}
/** Initialization constructor. */
FLightVPLsCS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{
AOParameters.Bind(Initializer.ParameterMap);
LightDirection.Bind(Initializer.ParameterMap, TEXT("LightDirection"));
LightSourceRadius.Bind(Initializer.ParameterMap, TEXT("LightSourceRadius"));
LightPositionAndInvRadius.Bind(Initializer.ParameterMap, TEXT("LightPositionAndInvRadius"));
TanLightAngleAndNormalThreshold.Bind(Initializer.ParameterMap, TEXT("TanLightAngleAndNormalThreshold"));
LightColor.Bind(Initializer.ParameterMap, TEXT("LightColor"));
ObjectParameters.Bind(Initializer.ParameterMap);
SurfelParameters.Bind(Initializer.ParameterMap);
ShadowTileHeadDataUnpacked.Bind(Initializer.ParameterMap, TEXT("ShadowTileHeadDataUnpacked"));
ShadowTileArrayData.Bind(Initializer.ParameterMap, TEXT("ShadowTileArrayData"));
ShadowTileListGroupSize.Bind(Initializer.ParameterMap, TEXT("ShadowTileListGroupSize"));
WorldToShadow.Bind(Initializer.ParameterMap, TEXT("WorldToShadow"));
ShadowObjectIndirectArguments.Bind(Initializer.ParameterMap, TEXT("ShadowObjectIndirectArguments"));
ShadowCulledObjectBounds.Bind(Initializer.ParameterMap, TEXT("ShadowCulledObjectBounds"));
ShadowCulledObjectData.Bind(Initializer.ParameterMap, TEXT("ShadowCulledObjectData"));
ObjectProcessStride.Bind(Initializer.ParameterMap, TEXT("ObjectProcessStride"));
ObjectProcessStartIndex.Bind(Initializer.ParameterMap, TEXT("ObjectProcessStartIndex"));
}
void SetParameters(
FRHICommandList& RHICmdList,
const FSceneView& View,
const FLightSceneProxy* LightSceneProxy,
const FMatrix& WorldToShadowMatrixValue,
const FDistanceFieldAOParameters& Parameters,
FLightTileIntersectionResources* TileIntersectionResources)
{
const FComputeShaderRHIParamRef ShaderRHI = GetComputeShader();
FGlobalShader::SetParameters(RHICmdList, ShaderRHI, View);
AOParameters.Set(RHICmdList, ShaderRHI, Parameters);
const FScene* Scene = (const FScene*)View.Family->Scene;
ObjectParameters.Set(RHICmdList, ShaderRHI, GAOCulledObjectBuffers.Buffers);
SurfelParameters.Set(RHICmdList, ShaderRHI, *Scene->DistanceFieldSceneData.SurfelBuffers, *Scene->DistanceFieldSceneData.InstancedSurfelBuffers);
FVector4 LightPositionAndInvRadiusValue;
FVector4 LightColorAndFalloffExponent;
FVector NormalizedLightDirection;
FVector2D SpotAngles;
float LightSourceRadiusValue;
float LightSourceLength;
float LightMinRoughness;
LightSceneProxy->GetParameters(LightPositionAndInvRadiusValue, LightColorAndFalloffExponent, NormalizedLightDirection, SpotAngles, LightSourceRadiusValue, LightSourceLength, LightMinRoughness);
SetShaderValue(RHICmdList, ShaderRHI, LightDirection, NormalizedLightDirection);
SetShaderValue(RHICmdList, ShaderRHI, LightPositionAndInvRadius, LightPositionAndInvRadiusValue);
// Default light source radius of 0 gives poor results
SetShaderValue(RHICmdList, ShaderRHI, LightSourceRadius, LightSourceRadiusValue == 0 ? 20 : FMath::Clamp(LightSourceRadiusValue, .001f, 1.0f / (4 * LightPositionAndInvRadiusValue.W)));
const float LightSourceAngle = FMath::Clamp(LightSceneProxy->GetLightSourceAngle(), 0.001f, 5.0f) * PI / 180.0f;
const FVector2D TanLightAngleAndNormalThresholdValue(FMath::Tan(LightSourceAngle), FMath::Cos(PI / 2 + LightSourceAngle));
SetShaderValue(RHICmdList, ShaderRHI, TanLightAngleAndNormalThreshold, TanLightAngleAndNormalThresholdValue);
SetShaderValue(RHICmdList, ShaderRHI, LightColor, LightSceneProxy->GetColor() * LightSceneProxy->GetIndirectLightingScale());
check(TileIntersectionResources || !ShadowTileHeadDataUnpacked.IsBound());
if (TileIntersectionResources)
{
SetSRVParameter(RHICmdList, ShaderRHI, ShadowTileHeadDataUnpacked, TileIntersectionResources->TileHeadDataUnpacked.SRV);
SetSRVParameter(RHICmdList, ShaderRHI, ShadowTileArrayData, TileIntersectionResources->TileArrayData.SRV);
SetShaderValue(RHICmdList, ShaderRHI, ShadowTileListGroupSize, TileIntersectionResources->TileDimensions);
}
SetShaderValue(RHICmdList, ShaderRHI, WorldToShadow, WorldToShadowMatrixValue);
SetSRVParameter(RHICmdList, ShaderRHI, ShadowObjectIndirectArguments, GShadowCulledObjectBuffers.Buffers.ObjectIndirectArguments.SRV);
SetSRVParameter(RHICmdList, ShaderRHI, ShadowCulledObjectBounds, GShadowCulledObjectBuffers.Buffers.Bounds.SRV);
SetSRVParameter(RHICmdList, ShaderRHI, ShadowCulledObjectData, GShadowCulledObjectBuffers.Buffers.Data.SRV);
SetShaderValue(RHICmdList, ShaderRHI, ObjectProcessStride, GVPLSpreadUpdateOver);
SetShaderValue(RHICmdList, ShaderRHI, ObjectProcessStartIndex, GFrameNumberRenderThread % GVPLSpreadUpdateOver);
}
void UnsetParameters(FRHICommandList& RHICmdList)
{
SurfelParameters.UnsetParameters(RHICmdList, GetComputeShader());
}
// FShader interface.
virtual bool Serialize(FArchive& Ar) override
{
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
Ar << AOParameters;
Ar << LightDirection;
Ar << LightPositionAndInvRadius;
Ar << LightSourceRadius;
Ar << TanLightAngleAndNormalThreshold;
Ar << LightColor;
Ar << ObjectParameters;
Ar << SurfelParameters;
Ar << ShadowTileHeadDataUnpacked;
Ar << ShadowTileArrayData;
Ar << ShadowTileListGroupSize;
Ar << WorldToShadow;
Ar << ShadowObjectIndirectArguments;
Ar << ShadowCulledObjectBounds;
Ar << ShadowCulledObjectData;
Ar << ObjectProcessStride;
Ar << ObjectProcessStartIndex;
return bShaderHasOutdatedParameters;
}
private:
FAOParameters AOParameters;
FShaderParameter LightDirection;
FShaderParameter LightPositionAndInvRadius;
FShaderParameter LightSourceRadius;
FShaderParameter TanLightAngleAndNormalThreshold;
FShaderParameter LightColor;
FDistanceFieldCulledObjectBufferParameters ObjectParameters;
FSurfelBufferParameters SurfelParameters;
FShaderResourceParameter ShadowTileHeadDataUnpacked;
FShaderResourceParameter ShadowTileArrayData;
FShaderParameter ShadowTileListGroupSize;
FShaderParameter WorldToShadow;
FShaderResourceParameter ShadowObjectIndirectArguments;
FShaderResourceParameter ShadowCulledObjectBounds;
FShaderResourceParameter ShadowCulledObjectData;
FShaderParameter ObjectProcessStride;
FShaderParameter ObjectProcessStartIndex;
};
IMPLEMENT_SHADER_TYPE(,FLightVPLsCS,TEXT("DistanceFieldGlobalIllumination"),TEXT("LightVPLsCS"),SF_Compute);
void UpdateVPLs(
FRHICommandListImmediate& RHICmdList,
const FViewInfo& View,
const FScene* Scene,
const FDistanceFieldAOParameters& Parameters)
{
if (GVPLMeshGlobalIllumination)
{
if (GVPLSurfelRepresentation)
{
SCOPED_DRAW_EVENT(RHICmdList, UpdateVPLs);
const FLightSceneProxy* DirectionalLightProxy = NULL;
for (TSparseArray<FLightSceneInfoCompact>::TConstIterator LightIt(Scene->Lights); LightIt; ++LightIt)
{
const FLightSceneInfoCompact& LightSceneInfoCompact = *LightIt;
const FLightSceneInfo* const LightSceneInfo = LightSceneInfoCompact.LightSceneInfo;
if (LightSceneInfo->ShouldRenderLightViewIndependent()
&& LightSceneInfo->Proxy->GetLightType() == LightType_Directional
&& LightSceneInfo->Proxy->CastsDynamicShadow())
{
DirectionalLightProxy = LightSceneInfo->Proxy;
break;
}
}
FMatrix DirectionalLightWorldToShadow = FMatrix::Identity;
if (DirectionalLightProxy)
{
{
int32 NumPlanes = 0;
const FPlane* PlaneData = NULL;
FVector4 ShadowBoundingSphereValue(0, 0, 0, 0);
FShadowCascadeSettings CascadeSettings;
FSphere ShadowBounds;
FConvexVolume FrustumVolume;
{
const float ConeExpandDistance = Parameters.OcclusionMaxDistance;
const float TanHalfFOV = 1.0f / View.ViewMatrices.ProjMatrix.M[0][0];
const float VertexPullbackLength = ConeExpandDistance / TanHalfFOV;
// Pull back cone vertex to contain VPLs outside of the view
const FVector ViewConeVertex = View.ViewMatrices.ViewOrigin - View.GetViewDirection() * VertexPullbackLength;
//@todo - expand by AOMaxDistance
ShadowBounds = DirectionalLightProxy->GetShadowSplitBoundsDepthRange(
View,
ViewConeVertex,
View.NearClippingDistance,
GetMaxAOViewDistance() + VertexPullbackLength + Parameters.OcclusionMaxDistance,
&CascadeSettings);
FSphere SubjectBounds(FVector::ZeroVector, ShadowBounds.W);
const FMatrix& WorldToLight = DirectionalLightProxy->GetWorldToLight();
const FMatrix InitializerWorldToLight = FInverseRotationMatrix(FVector(WorldToLight.M[0][0],WorldToLight.M[1][0],WorldToLight.M[2][0]).GetSafeNormal().Rotation());
const FVector InitializerFaceDirection = FVector(1,0,0);
FVector XAxis, YAxis;
InitializerFaceDirection.FindBestAxisVectors(XAxis, YAxis);
const FMatrix WorldToLightScaled = InitializerWorldToLight * FScaleMatrix(FVector(1.0f,1.0f / SubjectBounds.W,1.0f / SubjectBounds.W));
const FMatrix WorldToFace = WorldToLightScaled * FBasisVectorMatrix(-XAxis,YAxis,InitializerFaceDirection.GetSafeNormal(),FVector::ZeroVector);
NumPlanes = CascadeSettings.ShadowBoundsAccurate.Planes.Num();
PlaneData = CascadeSettings.ShadowBoundsAccurate.Planes.GetData();
DirectionalLightWorldToShadow = FTranslationMatrix(-ShadowBounds.Center)
* WorldToFace
* FShadowProjectionMatrix(-GVPLDirectionalLightTraceDistance / 2, GVPLDirectionalLightTraceDistance / 2, FVector4(0,0,0,1));
}
CullDistanceFieldObjectsForLight(
RHICmdList,
View,
DirectionalLightProxy,
DirectionalLightWorldToShadow,
NumPlanes,
PlaneData,
ShadowBoundingSphereValue,
ShadowBounds.W,
GVPLPlacementTileIntersectionResources);
}
SCOPED_DRAW_EVENT(RHICmdList, LightVPLs);
{
TShaderMapRef<FSetupLightVPLsIndirectArgumentsCS> ComputeShader(View.ShaderMap);
RHICmdList.SetComputeShader(ComputeShader->GetComputeShader());
ComputeShader->SetParameters(RHICmdList, View);
DispatchComputeShader(RHICmdList, *ComputeShader, 1, 1, 1);
ComputeShader->UnsetParameters(RHICmdList);
}
{
TShaderMapRef<FLightVPLsCS> ComputeShader(View.ShaderMap);
RHICmdList.SetComputeShader(ComputeShader->GetComputeShader());
ComputeShader->SetParameters(RHICmdList, View, DirectionalLightProxy, DirectionalLightWorldToShadow, Parameters, GVPLPlacementTileIntersectionResources);
DispatchIndirectComputeShader(RHICmdList, *ComputeShader, GAOCulledObjectBuffers.Buffers.ObjectIndirectDispatch.Buffer, 0);
ComputeShader->UnsetParameters(RHICmdList);
}
}
else
{
uint32 ClearValues[4] = { 0 };
RHICmdList.ClearUAV(Scene->DistanceFieldSceneData.InstancedSurfelBuffers->VPLFlux.UAV, ClearValues);
}
}
else
{
PlaceVPLs(RHICmdList, View, Scene, Parameters);
}
}
}
class FClearIrradianceSamplesCS : public FGlobalShader
{
DECLARE_SHADER_TYPE(FClearIrradianceSamplesCS,Global)
public:
static bool ShouldCache(EShaderPlatform Platform)
{
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM5) && DoesPlatformSupportDistanceFieldGI(Platform);
}
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Platform,OutEnvironment);
}
FClearIrradianceSamplesCS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{
SurfelIrradiance.Bind(Initializer.ParameterMap, TEXT("SurfelIrradiance"));
HeightfieldIrradiance.Bind(Initializer.ParameterMap, TEXT("HeightfieldIrradiance"));
ScatterDrawParameters.Bind(Initializer.ParameterMap, TEXT("ScatterDrawParameters"));
SavedStartIndex.Bind(Initializer.ParameterMap, TEXT("SavedStartIndex"));
}
FClearIrradianceSamplesCS()
{
}
void SetParameters(
FRHICommandList& RHICmdList,
const FSceneView& View,
int32 DepthLevel,
FTemporaryIrradianceCacheResources* TemporaryIrradianceCacheResources)
{
FComputeShaderRHIParamRef ShaderRHI = GetComputeShader();
FGlobalShader::SetParameters(RHICmdList, ShaderRHI, View);
const FScene* Scene = (const FScene*)View.Family->Scene;
FSurfaceCacheResources& SurfaceCacheResources = *Scene->SurfaceCacheResources;
SetSRVParameter(RHICmdList, ShaderRHI, ScatterDrawParameters, SurfaceCacheResources.Level[DepthLevel]->ScatterDrawParameters.SRV);
SetSRVParameter(RHICmdList, ShaderRHI, SavedStartIndex, SurfaceCacheResources.Level[DepthLevel]->SavedStartIndex.SRV);
SurfelIrradiance.SetBuffer(RHICmdList, ShaderRHI, TemporaryIrradianceCacheResources->SurfelIrradiance);
HeightfieldIrradiance.SetBuffer(RHICmdList, ShaderRHI, TemporaryIrradianceCacheResources->HeightfieldIrradiance);
}
void UnsetParameters(FRHICommandList& RHICmdList)
{
SurfelIrradiance.UnsetUAV(RHICmdList, GetComputeShader());
HeightfieldIrradiance.UnsetUAV(RHICmdList, GetComputeShader());
}
virtual bool Serialize(FArchive& Ar) override
{
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
Ar << SurfelIrradiance;
Ar << HeightfieldIrradiance;
Ar << ScatterDrawParameters;
Ar << SavedStartIndex;
return bShaderHasOutdatedParameters;
}
private:
FRWShaderParameter SurfelIrradiance;
FRWShaderParameter HeightfieldIrradiance;
FShaderResourceParameter ScatterDrawParameters;
FShaderResourceParameter SavedStartIndex;
};
IMPLEMENT_SHADER_TYPE(,FClearIrradianceSamplesCS,TEXT("DistanceFieldGlobalIllumination"),TEXT("ClearIrradianceSamplesCS"),SF_Compute);
class FComputeStepBentNormalCS : public FGlobalShader
{
DECLARE_SHADER_TYPE(FComputeStepBentNormalCS,Global)
public:
static bool ShouldCache(EShaderPlatform Platform)
{
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM5) && DoesPlatformSupportDistanceFieldGI(Platform);
}
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Platform,OutEnvironment);
OutEnvironment.SetDefine(TEXT("NUM_CONE_DIRECTIONS"), NumConeSampleDirections);
}
FComputeStepBentNormalCS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{
StepBentNormal.Bind(Initializer.ParameterMap, TEXT("StepBentNormal"));
IrradianceCacheNormal.Bind(Initializer.ParameterMap, TEXT("IrradianceCacheNormal"));
RecordConeData.Bind(Initializer.ParameterMap, TEXT("RecordConeData"));
ScatterDrawParameters.Bind(Initializer.ParameterMap, TEXT("ScatterDrawParameters"));
SavedStartIndex.Bind(Initializer.ParameterMap, TEXT("SavedStartIndex"));
BentNormalNormalizeFactor.Bind(Initializer.ParameterMap, TEXT("BentNormalNormalizeFactor"));
}
FComputeStepBentNormalCS()
{
}
void SetParameters(
FRHICommandList& RHICmdList,
const FSceneView& View,
int32 DepthLevel,
FTemporaryIrradianceCacheResources* TemporaryIrradianceCacheResources)
{
FComputeShaderRHIParamRef ShaderRHI = GetComputeShader();
FGlobalShader::SetParameters(RHICmdList, ShaderRHI, View);
const FScene* Scene = (const FScene*)View.Family->Scene;
FSurfaceCacheResources& SurfaceCacheResources = *Scene->SurfaceCacheResources;
SetSRVParameter(RHICmdList, ShaderRHI, IrradianceCacheNormal, SurfaceCacheResources.Level[DepthLevel]->Normal.SRV);
SetSRVParameter(RHICmdList, ShaderRHI, ScatterDrawParameters, SurfaceCacheResources.Level[DepthLevel]->ScatterDrawParameters.SRV);
SetSRVParameter(RHICmdList, ShaderRHI, SavedStartIndex, SurfaceCacheResources.Level[DepthLevel]->SavedStartIndex.SRV);
SetSRVParameter(RHICmdList, ShaderRHI, RecordConeData, TemporaryIrradianceCacheResources->ConeData.SRV);
StepBentNormal.SetBuffer(RHICmdList, ShaderRHI, TemporaryIrradianceCacheResources->StepBentNormal);
FAOSampleData2 AOSampleData;
TArray<FVector, TInlineAllocator<9> > SampleDirections;
GetSpacedVectors(SampleDirections);
for (int32 SampleIndex = 0; SampleIndex < NumConeSampleDirections; SampleIndex++)
{
AOSampleData.SampleDirections[SampleIndex] = FVector4(SampleDirections[SampleIndex]);
}
SetUniformBufferParameterImmediate(RHICmdList, ShaderRHI, GetUniformBufferParameter<FAOSampleData2>(), AOSampleData);
FVector UnoccludedVector(0);
for (int32 SampleIndex = 0; SampleIndex < NumConeSampleDirections; SampleIndex++)
{
UnoccludedVector += SampleDirections[SampleIndex];
}
float BentNormalNormalizeFactorValue = 1.0f / (UnoccludedVector / NumConeSampleDirections).Size();
SetShaderValue(RHICmdList, ShaderRHI, BentNormalNormalizeFactor, BentNormalNormalizeFactorValue);
}
void UnsetParameters(FRHICommandList& RHICmdList)
{
StepBentNormal.UnsetUAV(RHICmdList, GetComputeShader());
}
virtual bool Serialize(FArchive& Ar) override
{
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
Ar << StepBentNormal;
Ar << IrradianceCacheNormal;
Ar << RecordConeData;
Ar << ScatterDrawParameters;
Ar << SavedStartIndex;
Ar << BentNormalNormalizeFactor;
return bShaderHasOutdatedParameters;
}
private:
FRWShaderParameter StepBentNormal;
FShaderResourceParameter IrradianceCacheNormal;
FShaderResourceParameter RecordConeData;
FShaderResourceParameter ScatterDrawParameters;
FShaderResourceParameter SavedStartIndex;
FShaderParameter BentNormalNormalizeFactor;
};
IMPLEMENT_SHADER_TYPE(,FComputeStepBentNormalCS,TEXT("DistanceFieldGlobalIllumination"),TEXT("ComputeStepBentNormalCS"),SF_Compute);
enum EVPLMode
{
VPLMode_PlaceFromLight,
VPLMode_PlaceFromSurfels
};
template<EVPLMode VPLMode>
class TComputeIrradianceCS : public FGlobalShader
{
DECLARE_SHADER_TYPE(TComputeIrradianceCS,Global)
public:
static bool ShouldCache(EShaderPlatform Platform)
{
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM5) && DoesPlatformSupportDistanceFieldGI(Platform);
}
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Platform,OutEnvironment);
OutEnvironment.SetDefine(TEXT("NUM_CONE_DIRECTIONS"), NumConeSampleDirections);
OutEnvironment.SetDefine(TEXT("IRRADIANCE_FROM_SURFELS"), VPLMode == VPLMode_PlaceFromSurfels ? TEXT("1") : TEXT("0"));
// To reduce shader compile time of compute shaders with shared memory, doesn't have an impact on generated code with current compiler (June 2010 DX SDK)
OutEnvironment.CompilerFlags.Add(CFLAG_StandardOptimization);
}
TComputeIrradianceCS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{
AOParameters.Bind(Initializer.ParameterMap);
SurfelIrradiance.Bind(Initializer.ParameterMap, TEXT("SurfelIrradiance"));
IrradianceCachePositionRadius.Bind(Initializer.ParameterMap, TEXT("IrradianceCachePositionRadius"));
IrradianceCacheNormal.Bind(Initializer.ParameterMap, TEXT("IrradianceCacheNormal"));
IrradianceCacheTileCoordinate.Bind(Initializer.ParameterMap, TEXT("IrradianceCacheTileCoordinate"));
ScatterDrawParameters.Bind(Initializer.ParameterMap, TEXT("ScatterDrawParameters"));
SavedStartIndex.Bind(Initializer.ParameterMap, TEXT("SavedStartIndex"));
DistanceFieldNormalTexture.Bind(Initializer.ParameterMap, TEXT("DistanceFieldNormalTexture"));
DistanceFieldNormalSampler.Bind(Initializer.ParameterMap, TEXT("DistanceFieldNormalSampler"));
GlobalObjectParameters.Bind(Initializer.ParameterMap);
ObjectParameters.Bind(Initializer.ParameterMap);
SurfelParameters.Bind(Initializer.ParameterMap);
VPLParameterBuffer.Bind(Initializer.ParameterMap, TEXT("VPLParameterBuffer"));
VPLData.Bind(Initializer.ParameterMap, TEXT("VPLData"));
VPLGatherRadius.Bind(Initializer.ParameterMap, TEXT("VPLGatherRadius"));
TileListGroupSize.Bind(Initializer.ParameterMap, TEXT("TileListGroupSize"));
TileHeadDataUnpacked.Bind(Initializer.ParameterMap, TEXT("TileHeadDataUnpacked"));
TileArrayData.Bind(Initializer.ParameterMap, TEXT("TileArrayData"));
StepBentNormalBuffer.Bind(Initializer.ParameterMap, TEXT("StepBentNormalBuffer"));
}
TComputeIrradianceCS()
{
}
void SetParameters(
FRHICommandList& RHICmdList,
const FSceneView& View,
int32 DepthLevel,
const FDistanceFieldAOParameters& Parameters,
FTemporaryIrradianceCacheResources* TemporaryIrradianceCacheResources)
{
FComputeShaderRHIParamRef ShaderRHI = GetComputeShader();
FGlobalShader::SetParameters(RHICmdList, ShaderRHI, View);
AOParameters.Set(RHICmdList, ShaderRHI, Parameters);
const FScene* Scene = (const FScene*)View.Family->Scene;
FSurfaceCacheResources& SurfaceCacheResources = *Scene->SurfaceCacheResources;
SetSRVParameter(RHICmdList, ShaderRHI, IrradianceCachePositionRadius, SurfaceCacheResources.Level[DepthLevel]->PositionAndRadius.SRV);
SetSRVParameter(RHICmdList, ShaderRHI, IrradianceCacheNormal, SurfaceCacheResources.Level[DepthLevel]->Normal.SRV);
SetSRVParameter(RHICmdList, ShaderRHI, IrradianceCacheTileCoordinate, SurfaceCacheResources.Level[DepthLevel]->TileCoordinate.SRV);
SetSRVParameter(RHICmdList, ShaderRHI, ScatterDrawParameters, SurfaceCacheResources.Level[DepthLevel]->ScatterDrawParameters.SRV);
SetSRVParameter(RHICmdList, ShaderRHI, SavedStartIndex, SurfaceCacheResources.Level[DepthLevel]->SavedStartIndex.SRV);
SurfelIrradiance.SetBuffer(RHICmdList, ShaderRHI, TemporaryIrradianceCacheResources->SurfelIrradiance);
GlobalObjectParameters.Set(RHICmdList, ShaderRHI, *Scene->DistanceFieldSceneData.ObjectBuffers, Scene->DistanceFieldSceneData.NumObjectsInBuffer);
extern TGlobalResource<FDistanceFieldObjectBufferResource> GAOCulledObjectBuffers;
ObjectParameters.Set(RHICmdList, ShaderRHI, GAOCulledObjectBuffers.Buffers);
SurfelParameters.Set(RHICmdList, ShaderRHI, *Scene->DistanceFieldSceneData.SurfelBuffers, *Scene->DistanceFieldSceneData.InstancedSurfelBuffers);
FVPLResources& SourceVPLResources = GVPLViewCulling ? GCulledVPLResources : GVPLResources;
SetSRVParameter(RHICmdList, ShaderRHI, VPLParameterBuffer, SourceVPLResources.VPLParameterBuffer.SRV);
SetSRVParameter(RHICmdList, ShaderRHI, VPLData, SourceVPLResources.VPLData.SRV);
SetShaderValue(RHICmdList, ShaderRHI, VPLGatherRadius, Parameters.OcclusionMaxDistance);
FTileIntersectionResources* TileIntersectionResources = ((FSceneViewState*)View.State)->AOTileIntersectionResources;
SetSRVParameter(RHICmdList, ShaderRHI, TileHeadDataUnpacked, TileIntersectionResources->TileHeadDataUnpacked.SRV);
SetSRVParameter(RHICmdList, ShaderRHI, TileArrayData, TileIntersectionResources->TileArrayData.SRV);
SetShaderValue(RHICmdList, ShaderRHI, TileListGroupSize, TileIntersectionResources->TileDimensions);
SetSRVParameter(RHICmdList, ShaderRHI, StepBentNormalBuffer, TemporaryIrradianceCacheResources->StepBentNormal.SRV);
}
void UnsetParameters(FRHICommandList& RHICmdList)
{
SurfelIrradiance.UnsetUAV(RHICmdList, GetComputeShader());
}
virtual bool Serialize(FArchive& Ar) override
{
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
Ar << AOParameters;
Ar << SurfelIrradiance;
Ar << IrradianceCachePositionRadius;
Ar << IrradianceCacheNormal;
Ar << IrradianceCacheTileCoordinate;
Ar << ScatterDrawParameters;
Ar << SavedStartIndex;
Ar << DistanceFieldNormalTexture;
Ar << DistanceFieldNormalSampler;
Ar << GlobalObjectParameters;
Ar << ObjectParameters;
Ar << SurfelParameters;
Ar << VPLParameterBuffer;
Ar << VPLData;
Ar << VPLGatherRadius;
Ar << TileListGroupSize;
Ar << TileHeadDataUnpacked;
Ar << TileArrayData;
Ar << StepBentNormalBuffer;
return bShaderHasOutdatedParameters;
}
private:
FAOParameters AOParameters;
FRWShaderParameter SurfelIrradiance;
FShaderResourceParameter IrradianceCachePositionRadius;
FShaderResourceParameter IrradianceCacheNormal;
FShaderResourceParameter IrradianceCacheTileCoordinate;
FShaderResourceParameter ScatterDrawParameters;
FShaderResourceParameter SavedStartIndex;
FShaderResourceParameter DistanceFieldNormalTexture;
FShaderResourceParameter DistanceFieldNormalSampler;
FDistanceFieldObjectBufferParameters GlobalObjectParameters;
FDistanceFieldCulledObjectBufferParameters ObjectParameters;
FSurfelBufferParameters SurfelParameters;
FShaderResourceParameter VPLParameterBuffer;
FShaderResourceParameter VPLData;
FShaderParameter VPLGatherRadius;
FShaderParameter TileListGroupSize;
FShaderResourceParameter TileHeadDataUnpacked;
FShaderResourceParameter TileArrayData;
FShaderResourceParameter StepBentNormalBuffer;
};
IMPLEMENT_SHADER_TYPE(template<>,TComputeIrradianceCS<VPLMode_PlaceFromLight>,TEXT("DistanceFieldGlobalIllumination"),TEXT("ComputeIrradianceCS"),SF_Compute);
IMPLEMENT_SHADER_TYPE(template<>,TComputeIrradianceCS<VPLMode_PlaceFromSurfels>,TEXT("DistanceFieldGlobalIllumination"),TEXT("ComputeIrradianceCS"),SF_Compute);
class FCombineIrradianceSamplesCS : public FGlobalShader
{
DECLARE_SHADER_TYPE(FCombineIrradianceSamplesCS,Global)
public:
static bool ShouldCache(EShaderPlatform Platform)
{
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM5) && DoesPlatformSupportDistanceFieldGI(Platform);
}
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Platform,OutEnvironment);
}
FCombineIrradianceSamplesCS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{
IrradianceCacheIrradiance.Bind(Initializer.ParameterMap, TEXT("IrradianceCacheIrradiance"));
SurfelIrradiance.Bind(Initializer.ParameterMap, TEXT("SurfelIrradiance"));
HeightfieldIrradiance.Bind(Initializer.ParameterMap, TEXT("HeightfieldIrradiance"));
ScatterDrawParameters.Bind(Initializer.ParameterMap, TEXT("ScatterDrawParameters"));
SavedStartIndex.Bind(Initializer.ParameterMap, TEXT("SavedStartIndex"));
}
FCombineIrradianceSamplesCS()
{
}
void SetParameters(
FRHICommandList& RHICmdList,
const FSceneView& View,
int32 DepthLevel,
FTemporaryIrradianceCacheResources* TemporaryIrradianceCacheResources)
{
FComputeShaderRHIParamRef ShaderRHI = GetComputeShader();
FGlobalShader::SetParameters(RHICmdList, ShaderRHI, View);
const FScene* Scene = (const FScene*)View.Family->Scene;
FSurfaceCacheResources& SurfaceCacheResources = *Scene->SurfaceCacheResources;
SetSRVParameter(RHICmdList, ShaderRHI, SurfelIrradiance, TemporaryIrradianceCacheResources->SurfelIrradiance.SRV);
SetSRVParameter(RHICmdList, ShaderRHI, HeightfieldIrradiance,TemporaryIrradianceCacheResources->HeightfieldIrradiance.SRV);
SetSRVParameter(RHICmdList, ShaderRHI, ScatterDrawParameters, SurfaceCacheResources.Level[DepthLevel]->ScatterDrawParameters.SRV);
SetSRVParameter(RHICmdList, ShaderRHI, SavedStartIndex, SurfaceCacheResources.Level[DepthLevel]->SavedStartIndex.SRV);
IrradianceCacheIrradiance.SetBuffer(RHICmdList, ShaderRHI, SurfaceCacheResources.Level[DepthLevel]->Irradiance);
}
void UnsetParameters(FRHICommandList& RHICmdList)
{
IrradianceCacheIrradiance.UnsetUAV(RHICmdList, GetComputeShader());
}
virtual bool Serialize(FArchive& Ar) override
{
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
Ar << IrradianceCacheIrradiance;
Ar << SurfelIrradiance;
Ar << HeightfieldIrradiance;
Ar << ScatterDrawParameters;
Ar << SavedStartIndex;
return bShaderHasOutdatedParameters;
}
private:
FRWShaderParameter IrradianceCacheIrradiance;
FShaderResourceParameter SurfelIrradiance;
FShaderResourceParameter HeightfieldIrradiance;
FShaderResourceParameter ScatterDrawParameters;
FShaderResourceParameter SavedStartIndex;
};
IMPLEMENT_SHADER_TYPE(,FCombineIrradianceSamplesCS,TEXT("DistanceFieldGlobalIllumination"),TEXT("CombineIrradianceSamplesCS"),SF_Compute);
void ComputeIrradianceForSamples(
int32 DepthLevel,
FRHICommandListImmediate& RHICmdList,
const FViewInfo& View,
const FScene* Scene,
const FDistanceFieldAOParameters& Parameters,
FTemporaryIrradianceCacheResources* TemporaryIrradianceCacheResources)
{
FSurfaceCacheResources& SurfaceCacheResources = *Scene->SurfaceCacheResources;
{
SCOPED_DRAW_EVENT(RHICmdList, ComputeStepBentNormal);
{
TShaderMapRef<TSetupFinalGatherIndirectArgumentsCS<false> > ComputeShader(View.ShaderMap);
RHICmdList.SetComputeShader(ComputeShader->GetComputeShader());
ComputeShader->SetParameters(RHICmdList, View, DepthLevel);
DispatchComputeShader(RHICmdList, *ComputeShader, 1, 1, 1);
ComputeShader->UnsetParameters(RHICmdList);
}
{
TShaderMapRef<FComputeStepBentNormalCS> ComputeShader(View.ShaderMap);
RHICmdList.SetComputeShader(ComputeShader->GetComputeShader());
ComputeShader->SetParameters(RHICmdList, View, DepthLevel, TemporaryIrradianceCacheResources);
DispatchIndirectComputeShader(RHICmdList, *ComputeShader, SurfaceCacheResources.DispatchParameters.Buffer, 0);
ComputeShader->UnsetParameters(RHICmdList);
}
{
TShaderMapRef<FClearIrradianceSamplesCS> ComputeShader(View.ShaderMap);
RHICmdList.SetComputeShader(ComputeShader->GetComputeShader());
ComputeShader->SetParameters(RHICmdList, View, DepthLevel, TemporaryIrradianceCacheResources);
DispatchIndirectComputeShader(RHICmdList, *ComputeShader, SurfaceCacheResources.DispatchParameters.Buffer, 0);
ComputeShader->UnsetParameters(RHICmdList);
}
}
View.HeightfieldLightingViewInfo.ComputeIrradianceForSamples(View, RHICmdList, *TemporaryIrradianceCacheResources, DepthLevel, Parameters);
if (GVPLMeshGlobalIllumination)
{
SCOPED_DRAW_EVENT(RHICmdList, MeshIrradiance);
{
TShaderMapRef<TSetupFinalGatherIndirectArgumentsCS<true> > ComputeShader(View.ShaderMap);
RHICmdList.SetComputeShader(ComputeShader->GetComputeShader());
ComputeShader->SetParameters(RHICmdList, View, DepthLevel);
DispatchComputeShader(RHICmdList, *ComputeShader, 1, 1, 1);
ComputeShader->UnsetParameters(RHICmdList);
}
if (GVPLSurfelRepresentation)
{
TShaderMapRef<TComputeIrradianceCS<VPLMode_PlaceFromSurfels> > ComputeShader(View.ShaderMap);
RHICmdList.SetComputeShader(ComputeShader->GetComputeShader());
ComputeShader->SetParameters(RHICmdList, View, DepthLevel, Parameters, TemporaryIrradianceCacheResources);
DispatchIndirectComputeShader(RHICmdList, *ComputeShader, SurfaceCacheResources.DispatchParameters.Buffer, 0);
ComputeShader->UnsetParameters(RHICmdList);
}
else
{
TShaderMapRef<TComputeIrradianceCS<VPLMode_PlaceFromLight> > ComputeShader(View.ShaderMap);
RHICmdList.SetComputeShader(ComputeShader->GetComputeShader());
ComputeShader->SetParameters(RHICmdList, View, DepthLevel, Parameters, TemporaryIrradianceCacheResources);
DispatchIndirectComputeShader(RHICmdList, *ComputeShader, SurfaceCacheResources.DispatchParameters.Buffer, 0);
ComputeShader->UnsetParameters(RHICmdList);
}
}
{
TShaderMapRef<TSetupFinalGatherIndirectArgumentsCS<false> > ComputeShader(View.ShaderMap);
RHICmdList.SetComputeShader(ComputeShader->GetComputeShader());
ComputeShader->SetParameters(RHICmdList, View, DepthLevel);
DispatchComputeShader(RHICmdList, *ComputeShader, 1, 1, 1);
ComputeShader->UnsetParameters(RHICmdList);
}
{
TShaderMapRef<FCombineIrradianceSamplesCS> ComputeShader(View.ShaderMap);
RHICmdList.SetComputeShader(ComputeShader->GetComputeShader());
ComputeShader->SetParameters(RHICmdList, View, DepthLevel, TemporaryIrradianceCacheResources);
DispatchIndirectComputeShader(RHICmdList, *ComputeShader, SurfaceCacheResources.DispatchParameters.Buffer, 0);
ComputeShader->UnsetParameters(RHICmdList);
}
}
void ListDistanceFieldGIMemory(const FViewInfo& View)
{
const FScene* Scene = (const FScene*)View.Family->Scene;
if (GVPLPlacementTileIntersectionResources)
{
UE_LOG(LogTemp, Log, TEXT(" Shadow tile culled objects %.3fMb"), GVPLPlacementTileIntersectionResources->GetSizeBytes() / 1024.0f / 1024.0f);
}
}