UENUM()
enum EAutoExposureMethod
{
// 略
};
UENUM()
enum EDiffusionQuality
{
DFQ_None UMETA(DisplayName = "None"),
DFQ_Low UMETA(DisplayName = "Low"),
DFQ_Middle UMETA(DisplayName = "Middle"),
DFQ_High UMETA(DisplayName = "High"),
DFQ_MAX,
};
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Overrides, meta=(PinHiddenByDefault, InlineEditConditionToggle))
uint32 bOverride_ScreenSpaceReflectionRoughnessScale:1;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Overrides, meta=(PinHiddenByDefault, InlineEditConditionToggle))
uint32 bOverride_DiffusionQuality:1;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Overrides, meta=(PinHiddenByDefault, InlineEditConditionToggle))
uint32 bOverride_DiffusionScale:1;
/** Until what roughness we fade the screen space reflections, 0.8 works well, smaller can run faster */
UPROPERTY(interp, BlueprintReadWrite, Category=ScreenSpaceReflections, meta=(ClampMin = "0.01", ClampMax = "1.0", editcondition = "bOverride_ScreenSpaceReflectionMaxRoughness", DisplayName = "Max Roughness"))
float ScreenSpaceReflectionMaxRoughness;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Diffusion, meta=(editcondition = "bOverride_DiffusionQuality", DisplayName = "Quality"))
TEnumAsByte<enum EDiffusionQuality> DiffusionQuality;
UPROPERTY(interp, BlueprintReadWrite, Category=Diffusion, meta=(ClampMin = "1.0", UIMax = "8.0", editcondition = "bOverride_DiffusionScale", DisplayName = "Scale"))
float DiffusionScale;
LERP_PP(ScreenSpaceReflectionIntensity);
LERP_PP(ScreenSpaceReflectionMaxRoughness);
LERP_PP(DiffusionScale);
if (Src.bOverride_AmbientOcclusionRadiusInWS)
{
Dest.AmbientOcclusionRadiusInWS = Src.AmbientOcclusionRadiusInWS;
}
if (Src.bOverride_DiffusionQuality)
{
Dest.DiffusionQuality = Src.DiffusionQuality;
}
#include "Common.usf"
#include "PostProcessCommon.usf"
void MainVS(
in float4 InPosition : ATTRIBUTE0,
in float2 UV : ATTRIBUTE1,
out noperspective float2 OutUV : TEXCOORD0,
out float4 OutPosition : SV_POSITION
)
{
DrawRectangle(InPosition, UV, OutPosition, OutUV);
}
void MainPow2PS(noperspective float2 InUV : TEXCOORD0, out float4 OutColor : SV_Target0)
{
OutColor = Texture2DSample(PostprocessInput0, PostprocessInput0Sampler, InUV);
OutColor.rgb *= OutColor.rgb;
}
void MainPS(noperspective float2 InUV : TEXCOORD0, out float4 OutColor : SV_Target0)
{
float4 baseColor = Texture2DSample(PostprocessInput0, PostprocessInput0Sampler, InUV);
float4 pow2Color = baseColor * baseColor;
float4 blurColor = Texture2DSample(PostprocessInput1, PostprocessInput1Sampler, InUV);
#if QUALITY == 1
#elif QUALITY == 2
#else // QUALITY == 0
#endif
float4 screenColor = (1.0f - ((1.0f - pow2Color) * (1.0f - blurColor)));
OutColor.rgb = max(baseColor.rgb, screenColor.rgb);
OutColor.a = baseColor.a;
}
#pragma once
#include "RenderingCompositionGraph.h"
#include "PostProcessing.h"
/**
* ePId_Input0: main input texture
*/
class FRCPassPostProcessDiffusionPow2 : public TRenderingCompositePassBase<1, 1>
{
public:
// constructor
FRCPassPostProcessDiffusionPow2(const TCHAR* InDebugName = TEXT("DiffusionPow2"));
// interface FRenderingCompositePass ---------
virtual void Process(FRenderingCompositePassContext& Context) override;
virtual void Release() override { delete this; }
virtual FPooledRenderTargetDesc ComputeOutputDesc(EPassOutputId InPassOutputId) const override;
private:
const TCHAR* DebugName;
};
/**
* ePId_Input0: main input texture
* ePId_Input1: blur texture
*/
class FRCPassPostProcessDiffusion : public TRenderingCompositePassBase<2, 1>
{
public:
// constructor
FRCPassPostProcessDiffusion(const TCHAR* InDebugName = TEXT("Diffusion"), int32 quality = 0);
// interface FRenderingCompositePass ---------
virtual void Process(FRenderingCompositePassContext& Context) override;
virtual void Release() override { delete this; }
virtual FPooledRenderTargetDesc ComputeOutputDesc(EPassOutputId InPassOutputId) const override;
private:
template <uint32 Quality> static void SetShader(const FRenderingCompositePassContext& Context, const FPooledRenderTargetDesc* InputDesc0, const FPooledRenderTargetDesc* InputDesc1);
const TCHAR* DebugName;
int32 Quality;
};
#include "RendererPrivate.h"
#include "ScenePrivate.h"
#include "SceneFilterRendering.h"
#include "PostProcessDiffusion.h"
#include "SceneUtils.h"
class FPostProcessDiffusionPow2PS : public FGlobalShader
{
DECLARE_SHADER_TYPE(FPostProcessDiffusionPow2PS, Global);
static bool ShouldCache(EShaderPlatform Platform)
{
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM4);
}
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Platform, OutEnvironment);
}
FPostProcessDiffusionPow2PS() {}
public:
FPostProcessPassParameters PostprocessParameter;
FPostProcessDiffusionPow2PS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{
PostprocessParameter.Bind(Initializer.ParameterMap);
}
virtual bool Serialize(FArchive& Ar) override
{
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
Ar << PostprocessParameter;
return bShaderHasOutdatedParameters;
}
void SetParameters(const FRenderingCompositePassContext& Context, const FPooledRenderTargetDesc* InputDesc)
{
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
// filter only if needed for better performance
FSamplerStateRHIParamRef Filter = TStaticSamplerState<SF_Bilinear, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();
PostprocessParameter.SetPS(ShaderRHI, Context, Filter);
}
static const TCHAR* GetSourceFilename()
{
return TEXT("PostProcessDiffusion");
}
static const TCHAR* GetFunctionName()
{
return TEXT("MainPow2PS");
}
};
template <uint32 Quality>
class FPostProcessDiffusionPS : public FGlobalShader
{
DECLARE_SHADER_TYPE(FPostProcessDiffusionPS, Global);
static bool ShouldCache(EShaderPlatform Platform)
{
return IsFeatureLevelSupported(Platform, ERHIFeatureLevel::SM4);
}
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Platform, OutEnvironment);
OutEnvironment.SetDefine(TEXT("QUALITY"), Quality);
}
FPostProcessDiffusionPS() {}
public:
FPostProcessPassParameters PostprocessParameter;
FPostProcessDiffusionPS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{
PostprocessParameter.Bind(Initializer.ParameterMap);
}
virtual bool Serialize(FArchive& Ar) override
{
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
Ar << PostprocessParameter;
return bShaderHasOutdatedParameters;
}
void SetParameters(const FRenderingCompositePassContext& Context, const FPooledRenderTargetDesc* InputDesc)
{
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
FSamplerStateRHIParamRef Filter = TStaticSamplerState<SF_Bilinear, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();
PostprocessParameter.SetPS(ShaderRHI, Context, Filter);
}
static const TCHAR* GetSourceFilename()
{
return TEXT("PostProcessDiffusion");
}
static const TCHAR* GetFunctionName()
{
return TEXT("MainPS");
}
};
IMPLEMENT_SHADER_TYPE(, FPostProcessDiffusionPow2PS, TEXT("PostProcessDiffusion"), TEXT("MainPow2PS"), SF_Pixel);
#define VARIATION1(A) typedef FPostProcessDiffusionPS<A> FPostProcessDiffusionPS##A; \
IMPLEMENT_SHADER_TYPE2(FPostProcessDiffusionPS##A, SF_Pixel);
VARIATION1(0) VARIATION1(1) VARIATION1(2)
#undef VARIATION1
class FPostProcessDiffusionVS : public FGlobalShader
{
DECLARE_SHADER_TYPE(FPostProcessDiffusionVS, Global);
public:
static bool ShouldCache(EShaderPlatform Platform)
{
return true;
}
/** Default constructor. */
FPostProcessDiffusionVS() {}
/** Initialization constructor. */
FPostProcessDiffusionVS(const ShaderMetaType::CompiledShaderInitializerType& Initializer) :
FGlobalShader(Initializer)
{
}
/** Serializer */
virtual bool Serialize(FArchive& Ar) override
{
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
return bShaderHasOutdatedParameters;
}
void SetParameters(const FRenderingCompositePassContext& Context)
{
const FVertexShaderRHIParamRef ShaderRHI = GetVertexShader();
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
const FPooledRenderTargetDesc* InputDesc = Context.Pass->GetInputDesc(ePId_Input0);
if (!InputDesc)
{
return;
}
}
};
IMPLEMENT_SHADER_TYPE(, FPostProcessDiffusionVS, TEXT("PostProcessDiffusion"), TEXT("MainVS"), SF_Vertex);
FRCPassPostProcessDiffusionPow2::FRCPassPostProcessDiffusionPow2(const TCHAR *InDebugName)
: DebugName(InDebugName)
{
}
void FRCPassPostProcessDiffusionPow2::Process(FRenderingCompositePassContext& Context)
{
const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0);
if (!InputDesc)
{
return;
}
const FSceneView& View = Context.View;
const FSceneViewFamily& ViewFamily = *(View.Family);
FIntPoint SrcSize = InputDesc->Extent;
FIntPoint DestSize = PassOutputs[0].RenderTargetDesc.Extent;
uint32 ScaleFactor = FMath::DivideAndRoundUp(FSceneRenderTargets::Get(Context.RHICmdList).GetBufferSizeXY().Y, SrcSize.Y);
FIntRect SrcRect = View.ViewRect / ScaleFactor;
FIntRect DestRect = FIntRect::DivideAndRoundUp(SrcRect, 2);
SrcRect = DestRect * 2;
SCOPED_DRAW_EVENTF(Context.RHICmdList, DiffusionPow2, TEXT("DiffusionPow2"));
const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context);
auto FeatureLevel = Context.View.GetFeatureLevel();
if (FeatureLevel == ERHIFeatureLevel::ES2 || FeatureLevel == ERHIFeatureLevel::ES3_1)
{
SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef(), ESimpleRenderTargetMode::EClearColorAndDepth);
Context.SetViewportAndCallRHI(0, 0, 0.0f, DestSize.X, DestSize.Y, 1.0f);
}
else
{
SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef(), ESimpleRenderTargetMode::EExistingColorAndDepth);
Context.SetViewportAndCallRHI(0, 0, 0.0f, DestSize.X, DestSize.Y, 1.0f);
DrawClearQuad(Context.RHICmdList, Context.GetFeatureLevel(), true, FLinearColor(0, 0, 0, 0), false, 1.0f, false, 0, DestSize, DestRect);
}
Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI());
Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI());
Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI());
{
auto ShaderMap = Context.GetShaderMap();
TShaderMapRef<FPostProcessDiffusionVS> VertexShader(ShaderMap);
TShaderMapRef<FPostProcessDiffusionPow2PS> PixelShader(ShaderMap);
static FGlobalBoundShaderState BoundShaderState;
SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader);
PixelShader->SetParameters(Context, InputDesc);
VertexShader->SetParameters(Context);
}
TShaderMapRef<FPostProcessDiffusionVS> VertexShader(Context.GetShaderMap());
DrawPostProcessPass(
Context.RHICmdList,
DestRect.Min.X, DestRect.Min.Y,
DestRect.Width(), DestRect.Height(),
SrcRect.Min.X, SrcRect.Min.Y,
SrcRect.Width(), SrcRect.Height(),
DestSize,
SrcSize,
*VertexShader,
View.StereoPass,
false,
EDRF_UseTriangleOptimization);
Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams());
}
FPooledRenderTargetDesc FRCPassPostProcessDiffusionPow2::ComputeOutputDesc(EPassOutputId InPassOutputId) const
{
FPooledRenderTargetDesc Ret = GetInput(ePId_Input0)->GetOutput()->RenderTargetDesc;
Ret.Reset();
Ret.Extent = FIntPoint::DivideAndRoundUp(Ret.Extent, 2);
Ret.Extent.X = FMath::Max(1, Ret.Extent.X);
Ret.Extent.Y = FMath::Max(1, Ret.Extent.Y);
Ret.TargetableFlags &= ~TexCreate_UAV;
Ret.TargetableFlags |= TexCreate_RenderTargetable;
Ret.AutoWritable = false;
Ret.DebugName = DebugName;
Ret.ClearValue = FClearValueBinding(FLinearColor(0, 0, 0, 0));
return Ret;
}
FRCPassPostProcessDiffusion::FRCPassPostProcessDiffusion(const TCHAR *InDebugName, int32 quality)
: DebugName(InDebugName)
, Quality(quality)
{
}
template <uint32 Quality>
void FRCPassPostProcessDiffusion::SetShader(const FRenderingCompositePassContext& Context, const FPooledRenderTargetDesc* InputDesc0, const FPooledRenderTargetDesc* InputDesc1)
{
auto ShaderMap = Context.GetShaderMap();
TShaderMapRef<FPostProcessDiffusionVS> VertexShader(ShaderMap);
TShaderMapRef<FPostProcessDiffusionPS<Quality> > PixelShader(ShaderMap);
static FGlobalBoundShaderState BoundShaderState;
SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader);
PixelShader->SetParameters(Context, InputDesc0);
PixelShader->SetParameters(Context, InputDesc1);
VertexShader->SetParameters(Context);
}
void FRCPassPostProcessDiffusion::Process(FRenderingCompositePassContext& Context)
{
const FPooledRenderTargetDesc* InputDesc0 = GetInputDesc(ePId_Input0);
const FPooledRenderTargetDesc* InputDesc1 = GetInputDesc(ePId_Input1);
if (!InputDesc0 || !InputDesc1)
{
return;
}
const FSceneView& View = Context.View;
const FSceneViewFamily& ViewFamily = *(View.Family);
FIntPoint SrcSize = InputDesc0->Extent;
FIntPoint DestSize = PassOutputs[0].RenderTargetDesc.Extent;
uint32 ScaleFactor = FMath::DivideAndRoundUp(FSceneRenderTargets::Get(Context.RHICmdList).GetBufferSizeXY().Y, SrcSize.Y);
FIntRect SrcRect = View.ViewRect / ScaleFactor;
FIntRect DestRect = SrcRect;
SCOPED_DRAW_EVENTF(Context.RHICmdList, Diffusion, TEXT("Diffusion"));
const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context);
auto FeatureLevel = Context.View.GetFeatureLevel();
if (FeatureLevel == ERHIFeatureLevel::ES2 || FeatureLevel == ERHIFeatureLevel::ES3_1)
{
SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef(), ESimpleRenderTargetMode::EClearColorAndDepth);
Context.SetViewportAndCallRHI(0, 0, 0.0f, DestSize.X, DestSize.Y, 1.0f);
}
else
{
SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef(), ESimpleRenderTargetMode::EExistingColorAndDepth);
Context.SetViewportAndCallRHI(0, 0, 0.0f, DestSize.X, DestSize.Y, 1.0f);
DrawClearQuad(Context.RHICmdList, Context.GetFeatureLevel(), true, FLinearColor(0, 0, 0, 0), false, 1.0f, false, 0, DestSize, DestRect);
}
Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI());
Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI());
Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI());
if (Quality == DFQ_Low)
{
SetShader<0>(Context, InputDesc0, InputDesc1);
}
else if (Quality == DFQ_Middle)
{
SetShader<1>(Context, InputDesc0, InputDesc1);
}
else
{
SetShader<2>(Context, InputDesc0, InputDesc1);
}
TShaderMapRef<FPostProcessDiffusionVS> VertexShader(Context.GetShaderMap());
DrawPostProcessPass(
Context.RHICmdList,
DestRect.Min.X, DestRect.Min.Y,
DestRect.Width(), DestRect.Height(),
SrcRect.Min.X, SrcRect.Min.Y,
SrcRect.Width(), SrcRect.Height(),
DestSize,
SrcSize,
*VertexShader,
View.StereoPass,
false,
EDRF_UseTriangleOptimization);
Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams());
}
FPooledRenderTargetDesc FRCPassPostProcessDiffusion::ComputeOutputDesc(EPassOutputId InPassOutputId) const
{
FPooledRenderTargetDesc Ret = GetInput(ePId_Input0)->GetOutput()->RenderTargetDesc;
Ret.Reset();
Ret.TargetableFlags &= ~TexCreate_UAV;
Ret.TargetableFlags |= TexCreate_RenderTargetable;
Ret.AutoWritable = false;
Ret.DebugName = DebugName;
Ret.ClearValue = FClearValueBinding(FLinearColor(0, 0, 0, 0));
return Ret;
}
#include "PostProcessStreamingAccuracyLegend.h"
#include "PostProcessDiffusion.h"
if(bAllowTonemapper)
{
// 中略
// Add a pass-through as tonemapper will be forced LDR if final pass in chain
if (bHDRTonemapperOutput)
{
FRenderingCompositePass* PassthroughNode = Context.Graph.RegisterPass(new(FMemStack::Get()) FRCPassPostProcessPassThrough(nullptr));
PassthroughNode->SetInput(ePId_Input0, FRenderingCompositeOutputRef(Context.FinalOutput));
Context.FinalOutput = FRenderingCompositeOutputRef(PassthroughNode);
}
}
EDiffusionQuality diffusionQuality = View.FinalPostProcessSettings.DiffusionQuality;
if (diffusionQuality != DFQ_None)
{
FRCPassPostProcessDiffusionPow2* DiffusionPow2 = Context.Graph.RegisterPass(new(FMemStack::Get()) FRCPassPostProcessDiffusionPow2(TEXT("DiffusionPow2")));
DiffusionPow2->SetInput(ePId_Input0, Context.FinalOutput);
FRenderingCompositeOutputRef BlurOutput = RenderGaussianBlur(Context, TEXT("DiffusionBlurX1"), TEXT("DiffusionBlurY1"), FRenderingCompositeOutputRef(DiffusionPow2), View.FinalPostProcessSettings.DiffusionScale);
if (diffusionQuality != DFQ_Low)
{
FRCPassPostProcessDownsample* downSample = Context.Graph.RegisterPass(new(FMemStack::Get()) FRCPassPostProcessDownsample());
downSample->SetInput(ePId_Input0, BlurOutput);
BlurOutput = RenderGaussianBlur(Context, TEXT("DiffusionBlurX2"), TEXT("DiffusionBlurY2"), FRenderingCompositeOutputRef(downSample), View.FinalPostProcessSettings.DiffusionScale);
if (diffusionQuality != DFQ_Middle)
{
downSample = Context.Graph.RegisterPass(new(FMemStack::Get()) FRCPassPostProcessDownsample());
downSample->SetInput(ePId_Input0, BlurOutput);
BlurOutput = RenderGaussianBlur(Context, TEXT("DiffusionBlurX3"), TEXT("DiffusionBlurY3"), FRenderingCompositeOutputRef(downSample), View.FinalPostProcessSettings.DiffusionScale);
}
}
FRCPassPostProcessDiffusion* Diffusion = Context.Graph.RegisterPass(new(FMemStack::Get()) FRCPassPostProcessDiffusion(TEXT("Diffusion"), diffusionQuality));
Diffusion->SetInput(ePId_Input0, Context.FinalOutput);
Diffusion->SetInput(ePId_Input1, BlurOutput);
Context.FinalOutput = FRenderingCompositeOutputRef(Diffusion);
}
Author:monsho
ゲームプログラマ?