Merge commit '2321afecfba5c1d83158cc22f0da7f1285d2199c' into puvvadar/gitflow_211118_o3de
This commit is contained in:
@@ -34,10 +34,6 @@
|
||||
}
|
||||
],
|
||||
"PassRequests": [
|
||||
{
|
||||
"Name": "ReflectionScreenSpaceBlurPass",
|
||||
"TemplateName": "ReflectionScreenSpaceBlurPassTemplate"
|
||||
},
|
||||
{
|
||||
"Name": "ReflectionScreenSpaceTracePass",
|
||||
"TemplateName": "ReflectionScreenSpaceTracePassTemplate",
|
||||
@@ -56,42 +52,65 @@
|
||||
"Attachment": "NormalInput"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "DepthStencilInput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "Parent",
|
||||
"Attachment": "DepthStencilInput"
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "SpecularF0Input",
|
||||
"AttachmentRef": {
|
||||
"Pass": "Parent",
|
||||
"Attachment": "SpecularF0Input"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "ReflectionInputOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "Parent",
|
||||
"Attachment": "ReflectionInputOutput"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "ReflectionScreenSpaceBlurPass",
|
||||
"TemplateName": "ReflectionScreenSpaceBlurPassTemplate",
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "DepthInput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "Parent",
|
||||
"Attachment": "DepthStencilInput"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "ScreenSpaceReflectionInputOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "ReflectionScreenSpaceTracePass",
|
||||
"Attachment": "ScreenSpaceReflectionOutput"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "DownsampledDepthInputOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "ReflectionScreenSpaceTracePass",
|
||||
"Attachment": "DownsampledDepthOutput"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "ReflectionScreenSpaceCompositePass",
|
||||
"TemplateName": "ReflectionScreenSpaceCompositePassTemplate",
|
||||
"ExecuteAfter": [
|
||||
"ReflectionScreenSpaceBlurPass"
|
||||
],
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "TraceInput",
|
||||
"LocalSlot": "ReflectionInput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "ReflectionScreenSpaceTracePass",
|
||||
"Attachment": "Output"
|
||||
"Pass": "ReflectionScreenSpaceBlurPass",
|
||||
"Attachment": "ScreenSpaceReflectionInputOutput"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "PreviousFrameBufferInput",
|
||||
"LocalSlot": "DownsampledDepthInput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "ReflectionScreenSpaceBlurPass",
|
||||
"Attachment": "PreviousFrameInputOutput"
|
||||
"Attachment": "DownsampledDepthInputOutput"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -115,6 +134,13 @@
|
||||
"Attachment": "DepthStencilInput"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "PreviousFrameInputOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "ReflectionScreenSpaceTracePass",
|
||||
"Attachment": "PreviousFrameInputOutput"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "DepthStencilInput",
|
||||
"AttachmentRef": {
|
||||
|
||||
@@ -8,34 +8,19 @@
|
||||
"PassClass": "ReflectionScreenSpaceBlurPass",
|
||||
"Slots": [
|
||||
{
|
||||
"Name": "PreviousFrameInputOutput",
|
||||
"Name": "DepthInput",
|
||||
"SlotType": "Input",
|
||||
"ScopeAttachmentUsage": "Shader"
|
||||
},
|
||||
{
|
||||
"Name": "ScreenSpaceReflectionInputOutput",
|
||||
"SlotType": "InputOutput",
|
||||
"ScopeAttachmentUsage": "Shader"
|
||||
}
|
||||
],
|
||||
"ImageAttachments": [
|
||||
},
|
||||
{
|
||||
"Name": "PreviousFrameImage",
|
||||
"SizeSource": {
|
||||
"Source": {
|
||||
"Pass": "Parent",
|
||||
"Attachment": "SpecularInput"
|
||||
}
|
||||
},
|
||||
"ImageDescriptor": {
|
||||
"Format": "R16G16B16A16_FLOAT",
|
||||
"SharedQueueMask": "Graphics"
|
||||
},
|
||||
"GenerateFullMipChain": true
|
||||
}
|
||||
],
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "PreviousFrameInputOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "This",
|
||||
"Attachment": "PreviousFrameImage"
|
||||
}
|
||||
"Name": "DownsampledDepthInputOutput",
|
||||
"SlotType": "InputOutput",
|
||||
"ScopeAttachmentUsage": "DepthStencil"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -7,6 +7,11 @@
|
||||
"Name": "ReflectionScreenSpaceBlurVerticalPassTemplate",
|
||||
"PassClass": "ReflectionScreenSpaceBlurChildPass",
|
||||
"Slots": [
|
||||
{
|
||||
"Name": "DepthInput",
|
||||
"SlotType": "Input",
|
||||
"ScopeAttachmentUsage": "Shader"
|
||||
},
|
||||
{
|
||||
"Name": "Input",
|
||||
"SlotType": "InputOutput",
|
||||
@@ -16,6 +21,20 @@
|
||||
"Name": "Output",
|
||||
"SlotType": "InputOutput",
|
||||
"ScopeAttachmentUsage": "RenderTarget"
|
||||
},
|
||||
{
|
||||
"Name": "DownsampledDepthOutput",
|
||||
"SlotType": "InputOutput",
|
||||
"ScopeAttachmentUsage": "DepthStencil"
|
||||
}
|
||||
],
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "DepthInput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "Parent",
|
||||
"Attachment": "DepthInput"
|
||||
}
|
||||
}
|
||||
],
|
||||
"PassData": {
|
||||
|
||||
@@ -8,12 +8,12 @@
|
||||
"PassClass": "ReflectionScreenSpaceCompositePass",
|
||||
"Slots": [
|
||||
{
|
||||
"Name": "TraceInput",
|
||||
"Name": "ReflectionInput",
|
||||
"SlotType": "Input",
|
||||
"ScopeAttachmentUsage": "Shader"
|
||||
},
|
||||
{
|
||||
"Name": "PreviousFrameBufferInput",
|
||||
"Name": "DownsampledDepthInput",
|
||||
"SlotType": "Input",
|
||||
"ScopeAttachmentUsage": "Shader"
|
||||
},
|
||||
@@ -37,6 +37,11 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "PreviousFrameInputOutput",
|
||||
"SlotType": "InputOutput",
|
||||
"ScopeAttachmentUsage": "Shader"
|
||||
},
|
||||
{
|
||||
"Name": "DepthStencilInput",
|
||||
"SlotType": "Input",
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"ClassData": {
|
||||
"PassTemplate": {
|
||||
"Name": "ReflectionScreenSpaceTracePassTemplate",
|
||||
"PassClass": "FullScreenTriangle",
|
||||
"PassClass": "ReflectionScreenSpaceTracePass",
|
||||
"Slots": [
|
||||
{
|
||||
"Name": "DepthStencilTextureInput",
|
||||
@@ -28,24 +28,52 @@
|
||||
"ScopeAttachmentUsage": "Shader"
|
||||
},
|
||||
{
|
||||
"Name": "DepthStencilInput",
|
||||
"Name": "ReflectionInputOutput",
|
||||
"SlotType": "Input",
|
||||
"ScopeAttachmentUsage": "DepthStencil",
|
||||
"ImageViewDesc": {
|
||||
"AspectFlags": [
|
||||
"Stencil"
|
||||
]
|
||||
"ScopeAttachmentUsage": "Shader"
|
||||
},
|
||||
{
|
||||
"Name": "PreviousFrameInputOutput",
|
||||
"SlotType": "Input",
|
||||
"ScopeAttachmentUsage": "Shader"
|
||||
},
|
||||
{
|
||||
"Name": "ScreenSpaceReflectionOutput",
|
||||
"SlotType": "Output",
|
||||
"ScopeAttachmentUsage": "RenderTarget",
|
||||
"LoadStoreAction": {
|
||||
"ClearValue": {
|
||||
"Value": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0
|
||||
]
|
||||
},
|
||||
"LoadAction": "Clear"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Output",
|
||||
"Name": "DownsampledDepthOutput",
|
||||
"SlotType": "Output",
|
||||
"ScopeAttachmentUsage": "RenderTarget"
|
||||
"ScopeAttachmentUsage": "DepthStencil",
|
||||
"LoadStoreAction": {
|
||||
"ClearValue": {
|
||||
"Type": "DepthStencil",
|
||||
"Value": [
|
||||
1.0,
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
]
|
||||
},
|
||||
"LoadAction": "Clear"
|
||||
}
|
||||
}
|
||||
],
|
||||
"ImageAttachments": [
|
||||
{
|
||||
"Name": "TraceImage",
|
||||
"Name": "ScreenSpaceReflectionImage",
|
||||
"SizeSource": {
|
||||
"Source": {
|
||||
"Pass": "This",
|
||||
@@ -56,9 +84,40 @@
|
||||
"HeightMultiplier": 0.5
|
||||
}
|
||||
},
|
||||
"MultisampleSource": {
|
||||
"Pass": "This",
|
||||
"Attachment": "SpecularF0Input"
|
||||
"ImageDescriptor": {
|
||||
"Format": "R16G16B16A16_FLOAT",
|
||||
"MipLevels": "5",
|
||||
"SharedQueueMask": "Graphics"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "DownsampledDepthImage",
|
||||
"SizeSource": {
|
||||
"Source": {
|
||||
"Pass": "Parent",
|
||||
"Attachment": "DepthStencilInput"
|
||||
},
|
||||
"Multipliers": {
|
||||
"WidthMultiplier": 0.5,
|
||||
"HeightMultiplier": 0.5
|
||||
}
|
||||
},
|
||||
"FormatSource": {
|
||||
"Pass": "Parent",
|
||||
"Attachment": "DepthStencilInput"
|
||||
},
|
||||
"ImageDescriptor": {
|
||||
"MipLevels": "5",
|
||||
"SharedQueueMask": "Graphics"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "PreviousFrameImage",
|
||||
"SizeSource": {
|
||||
"Source": {
|
||||
"Pass": "Parent",
|
||||
"Attachment": "SpecularInput"
|
||||
}
|
||||
},
|
||||
"ImageDescriptor": {
|
||||
"Format": "R16G16B16A16_FLOAT",
|
||||
@@ -68,15 +127,28 @@
|
||||
],
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "Output",
|
||||
"LocalSlot": "ScreenSpaceReflectionOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "This",
|
||||
"Attachment": "TraceImage"
|
||||
"Attachment": "ScreenSpaceReflectionImage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "DownsampledDepthOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "This",
|
||||
"Attachment": "DownsampledDepthImage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "PreviousFrameInputOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "This",
|
||||
"Attachment": "PreviousFrameImage"
|
||||
}
|
||||
}
|
||||
],
|
||||
"PassData":
|
||||
{
|
||||
"PassData": {
|
||||
"$type": "FullscreenTrianglePassData",
|
||||
"ShaderAsset": {
|
||||
"FilePath": "Shaders/Reflections/ReflectionScreenSpaceTrace.shader"
|
||||
|
||||
+25
-5
@@ -6,11 +6,31 @@
|
||||
*
|
||||
*/
|
||||
|
||||
// 7-tap Gaussian Kernel (Sigma 1.1)
|
||||
static const uint GaussianKernelSize = 7;
|
||||
static const int2 TexelOffsetsV[GaussianKernelSize] = {{0, -3}, {0, -2}, {0, -1}, {0, 0}, {0, 1}, {0, 2}, {0, 3}};
|
||||
static const int2 TexelOffsetsH[GaussianKernelSize] = {{-3, 0}, {-2, 0}, {-1, 0}, {0, 0}, {1, 0}, {2, 0}, {3, 0}};
|
||||
static const float TexelWeights[GaussianKernelSize] = {0.010805f, 0.074929f, 0.238727f, 0.351078f, 0.238727f, 0.074929f, 0.010805f};
|
||||
// Gaussian Kernel Radius 9, Sigma 1.8
|
||||
static const uint GaussianKernelSize = 19;
|
||||
static const int2 TexelOffsetsV[GaussianKernelSize] = {{0, -9}, {0, -8}, {0, -7}, {0, -6}, {0, -5}, {0, -4}, {0, -3}, {0, -2}, {0, -1}, {0, 0}, {0, 1}, {0, 2}, {0, 3}, {0, 4}, {0, 5}, {0, 6}, {0, 7}, {0, 8}, {0, 9}};
|
||||
static const int2 TexelOffsetsH[GaussianKernelSize] = {{-9, 0}, {-8, 0}, {-7, 0}, {-6, 0}, {-5, 0}, {-4, 0}, {-3, 0}, {-2, 0}, {-1, 0}, {0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0}, {6, 0}, {7, 0}, {8, 0}, {9, 0}};
|
||||
static const float TexelWeights[GaussianKernelSize] = {
|
||||
0.0000011022801820635918f,
|
||||
0.000014295732881160677f,
|
||||
0.0001370168487067367f,
|
||||
0.0009708086495991633f,
|
||||
0.005086391900047703f,
|
||||
0.019711193240183777f,
|
||||
0.056512463228943335f,
|
||||
0.11989501853796679f,
|
||||
0.18826323520204147f,
|
||||
0.21881694875889543f,
|
||||
0.18826323520204147f,
|
||||
0.11989501853796679f,
|
||||
0.056512463228943335f,
|
||||
0.019711193240183777f,
|
||||
0.005086391900047703f,
|
||||
0.0009708086495991633f,
|
||||
0.0001370168487067367f,
|
||||
0.000014295732881160677f,
|
||||
0.0000011022801820635918f
|
||||
};
|
||||
|
||||
float3 GaussianFilter(uint2 screenCoords, int2 texelOffsets[GaussianKernelSize], RWTexture2D<float4> inputImage)
|
||||
{
|
||||
|
||||
+30
-3
@@ -10,12 +10,13 @@
|
||||
#include <viewsrg.srgi>
|
||||
|
||||
#include <Atom/Features/PostProcessing/FullscreenVertex.azsli>
|
||||
#include <Atom/Features/PostProcessing/FullscreenPixelInfo.azsli>
|
||||
#include <Atom/Features/SrgSemantics.azsli>
|
||||
#include <Atom/RPI/Math.azsli>
|
||||
#include "ReflectionScreenSpaceBlurCommon.azsli"
|
||||
|
||||
ShaderResourceGroup PassSrg : SRG_PerPass
|
||||
{
|
||||
Texture2DMS<float> m_depth;
|
||||
RWTexture2D<float4> m_input;
|
||||
RWTexture2D<float4> m_output;
|
||||
uint m_imageWidth;
|
||||
@@ -26,13 +27,39 @@ ShaderResourceGroup PassSrg : SRG_PerPass
|
||||
#include <Atom/RPI/ShaderResourceGroups/DefaultDrawSrg.azsli>
|
||||
|
||||
// Pixel Shader
|
||||
struct PSOutput
|
||||
{
|
||||
float4 m_color : SV_Target0;
|
||||
float m_depth : SV_Depth;
|
||||
};
|
||||
|
||||
PSOutput MainPS(VSOutput IN)
|
||||
{
|
||||
// vertical blur uses coordinates from the mip0 input image
|
||||
uint2 coords = IN.m_position.xy * PassSrg::m_outputScale;
|
||||
float3 result = GaussianFilter(coords, TexelOffsetsV, PassSrg::m_input);
|
||||
uint2 halfResCoords = IN.m_position.xy * PassSrg::m_outputScale;
|
||||
float3 result = GaussianFilter(halfResCoords, TexelOffsetsV, PassSrg::m_input);
|
||||
|
||||
// downsample depth, using fullscreen image coordinates
|
||||
float downsampledDepth = 0;
|
||||
if (PassSrg::m_input[halfResCoords].w > 0.0f)
|
||||
{
|
||||
uint2 fullScreenCoords = halfResCoords * 2;
|
||||
|
||||
for (int y = -2; y < 2; ++y)
|
||||
{
|
||||
for (int x = -2; x < 2; ++x)
|
||||
{
|
||||
float depth = PassSrg::m_depth.Load(fullScreenCoords + int2(x, y), 0).r;
|
||||
if (depth > downsampledDepth)
|
||||
{
|
||||
downsampledDepth = depth;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PSOutput OUT;
|
||||
OUT.m_color = float4(result, 1.0f);
|
||||
OUT.m_depth = downsampledDepth;
|
||||
return OUT;
|
||||
}
|
||||
|
||||
+2
-1
@@ -10,7 +10,8 @@
|
||||
{
|
||||
"Depth" :
|
||||
{
|
||||
"Enable" : false
|
||||
"Enable" : true, // required to bind the depth buffer SRV
|
||||
"CompareFunc" : "Always"
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
+69
-39
@@ -12,17 +12,19 @@
|
||||
#include <Atom/RPI/Math.azsli>
|
||||
#include <Atom/Features/PostProcessing/FullscreenVertex.azsli>
|
||||
#include <Atom/Features/PostProcessing/FullscreenPixelInfo.azsli>
|
||||
#include <Atom/Features/PostProcessing/PostProcessUtil.azsli>
|
||||
#include <Atom/Features/MatrixUtility.azsli>
|
||||
#include <Atom/Features/PBR/LightingUtils.azsli>
|
||||
#include <Atom/Features/PBR/Microfacet/Fresnel.azsli>
|
||||
|
||||
ShaderResourceGroup PassSrg : SRG_PerPass
|
||||
{
|
||||
Texture2DMS<float4> m_trace;
|
||||
Texture2D<float4> m_previousFrame;
|
||||
Texture2D<float4> m_reflection;
|
||||
Texture2D<float> m_downsampledDepth;
|
||||
Texture2DMS<float4> m_normal; // RGB10 = Normal (Encoded), A2 = Flags
|
||||
Texture2DMS<float4> m_specularF0; // RGB8 = SpecularF0, A8 = Roughness
|
||||
Texture2DMS<float> m_depth;
|
||||
Texture2D<float4> m_previousFrame;
|
||||
|
||||
Sampler LinearSampler
|
||||
{
|
||||
@@ -40,6 +42,49 @@ ShaderResourceGroup PassSrg : SRG_PerPass
|
||||
|
||||
#include <Atom/RPI/ShaderResourceGroups/DefaultDrawSrg.azsli>
|
||||
|
||||
float3 SampleReflection(float2 reflectionUV, float mip, float depth, float3 normal, uint2 invDimensions)
|
||||
{
|
||||
const float DepthTolerance = 0.001f;
|
||||
|
||||
// attempt to trivially accept the downsampled reflection texel
|
||||
float downsampledDepth = PassSrg::m_downsampledDepth.SampleLevel(PassSrg::LinearSampler, reflectionUV, floor(mip)).r;
|
||||
if (abs(depth - downsampledDepth) <= DepthTolerance)
|
||||
{
|
||||
// use this reflection sample
|
||||
float3 reflection = PassSrg::m_reflection.SampleLevel(PassSrg::LinearSampler, reflectionUV, mip).rgb;
|
||||
return reflection;
|
||||
}
|
||||
|
||||
// neighborhood search surrounding the downsampled texel, searching for the closest matching depth
|
||||
float closestDepthDelta = 1.0f;
|
||||
int2 closestOffsetUV = float2(0.0f, 0.0f);
|
||||
for (int y = -4; y <= 4; ++y)
|
||||
{
|
||||
for (int x = -4; x <= 4; ++x)
|
||||
{
|
||||
float2 offsetUV = float2(x * invDimensions.x, y * invDimensions.y);
|
||||
float downsampledDepth = PassSrg::m_downsampledDepth.SampleLevel(PassSrg::LinearSampler, reflectionUV + offsetUV, floor(mip)).r;
|
||||
float depthDelta = abs(depth - downsampledDepth);
|
||||
|
||||
if (depthDelta <= DepthTolerance)
|
||||
{
|
||||
// depth is within tolerance, use this texel
|
||||
float3 reflection = PassSrg::m_reflection.SampleLevel(PassSrg::LinearSampler, reflectionUV + offsetUV, mip).rgb;
|
||||
return reflection;
|
||||
}
|
||||
|
||||
if (closestDepthDelta > depthDelta)
|
||||
{
|
||||
closestDepthDelta = depthDelta;
|
||||
closestOffsetUV = offsetUV;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float3 reflection = PassSrg::m_reflection.SampleLevel(PassSrg::LinearSampler, reflectionUV + closestOffsetUV, mip).rgb;
|
||||
return reflection;
|
||||
}
|
||||
|
||||
// Pixel Shader
|
||||
PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex)
|
||||
{
|
||||
@@ -52,11 +97,21 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex)
|
||||
// compute trace image coordinates for the half-res image
|
||||
float2 traceCoords = screenCoords * 0.5f;
|
||||
|
||||
// load trace data and check w-component to see if there was a hit
|
||||
float4 traceData = PassSrg::m_trace.Load(traceCoords, sampleIndex);
|
||||
if (traceData.w <= 0.0f)
|
||||
// check reflection data mip0 to see if there was a hit
|
||||
float4 reflectionData = PassSrg::m_reflection.Load(uint3(traceCoords, 0));
|
||||
if (reflectionData.w <= 0.0f)
|
||||
{
|
||||
// no hit, fallback to the cubemap reflections currently in the reflection buffer
|
||||
// fallback to the cubemap reflections currently in the reflection buffer
|
||||
discard;
|
||||
}
|
||||
|
||||
// load specular and roughness
|
||||
float4 specularF0 = PassSrg::m_specularF0.Load(screenCoords, sampleIndex);
|
||||
float roughness = specularF0.a;
|
||||
const float MaxRoughness = 0.5f;
|
||||
if (roughness > MaxRoughness)
|
||||
{
|
||||
// fallback to the cubemap reflections currently in the reflection buffer
|
||||
discard;
|
||||
}
|
||||
|
||||
@@ -65,8 +120,9 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex)
|
||||
float depth = PassSrg::m_depth.Load(screenCoords, sampleIndex).r;
|
||||
float2 ndcPos = float2(UV.x, 1.0f - UV.y) * 2.0f - 1.0f;
|
||||
float4 projectedPos = float4(ndcPos, depth, 1.0f);
|
||||
float4 positionWS = mul(ViewSrg::m_viewProjectionInverseMatrix, projectedPos);
|
||||
positionWS /= positionWS.w;
|
||||
float4 positionVS = mul(ViewSrg::m_projectionMatrixInverse, projectedPos);
|
||||
positionVS /= positionVS.w;
|
||||
float3 positionWS = mul(ViewSrg::m_viewMatrixInverse, positionVS).xyz;
|
||||
|
||||
// compute ray from camera to surface position
|
||||
float3 cameraToPositionWS = normalize(positionWS.xyz - ViewSrg::m_worldPosition);
|
||||
@@ -74,42 +130,16 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex)
|
||||
// retrieve surface normal
|
||||
float4 encodedNormal = PassSrg::m_normal.Load(screenCoords, sampleIndex);
|
||||
float3 normalWS = DecodeNormalSignedOctahedron(encodedNormal.rgb);
|
||||
|
||||
// compute surface specular
|
||||
float4 specularF0 = PassSrg::m_specularF0.Load(screenCoords, sampleIndex);
|
||||
float roughness = specularF0.a;
|
||||
float NdotV = dot(normalWS, -cameraToPositionWS);
|
||||
float3 specular = FresnelSchlickWithRoughness(NdotV, specularF0.rgb, roughness);
|
||||
|
||||
// reconstruct the world space position of the trace coordinates
|
||||
float2 traceUV = saturate(traceData.xy / dimensions);
|
||||
float traceDepth = PassSrg::m_depth.Load(traceData.xy, sampleIndex).r;
|
||||
float2 traceNDC = float2(traceUV.x, 1.0f - traceUV.y) * 2.0f - 1.0f;
|
||||
float4 traceProjectedPos = float4(traceNDC, traceDepth, 1.0f);
|
||||
float4 tracePositionVS = mul(ViewSrg::m_projectionMatrixInverse, traceProjectedPos);
|
||||
tracePositionVS /= tracePositionVS.w;
|
||||
float4 tracePositionWS = mul(ViewSrg::m_viewMatrixInverse, tracePositionVS);
|
||||
|
||||
// reproject to the previous frame image coordinates
|
||||
float4 tracePrevNDC = mul(ViewSrg::m_viewProjectionPrevMatrix, tracePositionWS);
|
||||
tracePrevNDC /= tracePrevNDC.w;
|
||||
float2 tracePrevUV = float2(tracePrevNDC.x, -1.0f * tracePrevNDC.y) * 0.5f + 0.5f;
|
||||
|
||||
// compute the roughness mip to use in the previous frame image
|
||||
// compute the roughness mip to use in the reflection image
|
||||
// remap the roughness mip into a lower range to more closely match the material roughness values
|
||||
const float MaxRoughness = 0.5f;
|
||||
float mip = saturate(roughness / MaxRoughness) * PassSrg::m_maxMipLevel;
|
||||
|
||||
// sample reflection value from the roughness mip
|
||||
float4 reflectionColor = float4(PassSrg::m_previousFrame.SampleLevel(PassSrg::LinearSampler, tracePrevUV, mip).rgb, 1.0f);
|
||||
|
||||
// fade rays close to screen edge
|
||||
const float ScreenFadeDistance = 0.95f;
|
||||
float2 fadeAmount = max(max(0.0f, traceUV - ScreenFadeDistance), max(0.0f, 1.0f - traceUV - ScreenFadeDistance));
|
||||
fadeAmount /= (1.0f - ScreenFadeDistance);
|
||||
float alpha = 1.0f - max(fadeAmount.x, fadeAmount.y);
|
||||
|
||||
// sample reflection color from the mip chain
|
||||
float3 reflectionColor = SampleReflection(IN.m_texCoord, mip, depth, normalWS, 1.0f / dimensions);
|
||||
|
||||
PSOutput OUT;
|
||||
OUT.m_color = float4(reflectionColor.rgb * specular, alpha);
|
||||
OUT.m_color = float4(reflectionColor, reflectionData.w);
|
||||
return OUT;
|
||||
}
|
||||
|
||||
+88
-3
@@ -10,7 +10,7 @@
|
||||
#include <viewsrg.srgi>
|
||||
|
||||
#include <Atom/Features/PostProcessing/FullscreenVertexUtil.azsli>
|
||||
#include <Atom/Features/PostProcessing/FullscreenPixelInfo.azsli>
|
||||
#include <Atom/Features/PostProcessing/PostProcessUtil.azsli>
|
||||
#include <Atom/Features/MatrixUtility.azsli>
|
||||
#include <Atom/Features/PBR/LightingUtils.azsli>
|
||||
#include <Atom/Features/PBR/Microfacet/Fresnel.azsli>
|
||||
@@ -20,6 +20,18 @@ ShaderResourceGroup PassSrg : SRG_PerPass
|
||||
Texture2DMS<float> m_depth;
|
||||
Texture2DMS<float4> m_normal; // RGB10 = Normal (Encoded), A2 = Flags
|
||||
Texture2DMS<float4> m_specularF0; // RGB8 = SpecularF0, A8 = Roughness
|
||||
Texture2DMS<float4> m_reflection;
|
||||
Texture2D<float4> m_previousFrame;
|
||||
|
||||
Sampler LinearSampler
|
||||
{
|
||||
MinFilter = Linear;
|
||||
MagFilter = Linear;
|
||||
MipFilter = Linear;
|
||||
AddressU = Clamp;
|
||||
AddressV = Clamp;
|
||||
AddressW = Clamp;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Atom/RPI/ShaderResourceGroups/DefaultDrawSrg.azsli>
|
||||
@@ -49,6 +61,12 @@ VSOutput MainVS(VSInput input)
|
||||
}
|
||||
|
||||
// Pixel Shader
|
||||
struct PSOutput
|
||||
{
|
||||
float4 m_color : SV_Target0;
|
||||
float m_depth : SV_Depth;
|
||||
};
|
||||
|
||||
PSOutput MainPS(VSOutput IN)
|
||||
{
|
||||
// compute screen coords based on a half-res render target
|
||||
@@ -83,16 +101,83 @@ PSOutput MainPS(VSOutput IN)
|
||||
// reflect view ray around surface normal
|
||||
float3 reflectDirVS = normalize(reflect(cameraToPositionVS, normalVS));
|
||||
|
||||
// check to see if the reflected direction is approaching the camera
|
||||
float rdotv = dot(reflectDirVS, -cameraToPositionVS);
|
||||
bool fallbackEdge = false;
|
||||
if (rdotv >= -0.05f)
|
||||
{
|
||||
if (rdotv >= 0.0f)
|
||||
{
|
||||
// ray points back to camera, fallback to cubemaps
|
||||
discard;
|
||||
}
|
||||
|
||||
// ray is approaching the camera direction, but not there yet - trace the reflection and set this
|
||||
// as a non-reflected pixel, which will prevent artifacts at the boundary
|
||||
fallbackEdge = true;
|
||||
}
|
||||
|
||||
// trace screenspace rays against the depth buffer to find the screenspace intersection coordinates
|
||||
float4 result = float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
float2 hitCoords = float2(0.0f, 0.0f);
|
||||
if (TraceRayScreenSpace(positionVS, reflectDirVS, dimensions, hitCoords))
|
||||
{
|
||||
float rdotv = dot(reflectDirVS, cameraToPositionVS);
|
||||
result = float4(hitCoords, 0.0f, rdotv);
|
||||
// reconstruct the world space position of the trace coordinates
|
||||
float2 traceUV = saturate(hitCoords / dimensions);
|
||||
float traceDepth = PassSrg::m_depth.Load(hitCoords, 0).r;
|
||||
float2 traceNDC = float2(traceUV.x, 1.0f - traceUV.y) * 2.0f - 1.0f;
|
||||
float4 traceProjectedPos = float4(traceNDC, traceDepth, 1.0f);
|
||||
float4 tracePositionVS = mul(ViewSrg::m_projectionMatrixInverse, traceProjectedPos);
|
||||
tracePositionVS /= tracePositionVS.w;
|
||||
float4 tracePositionWS = mul(ViewSrg::m_viewMatrixInverse, tracePositionVS);
|
||||
|
||||
// reproject to the previous frame image coordinates
|
||||
float4 tracePrevNDC = mul(ViewSrg::m_viewProjectionPrevMatrix, tracePositionWS);
|
||||
tracePrevNDC /= tracePrevNDC.w;
|
||||
float2 tracePrevUV = float2(tracePrevNDC.x, -1.0f * tracePrevNDC.y) * 0.5f + 0.5f;
|
||||
|
||||
// sample the previous frame image
|
||||
result.rgb = PassSrg::m_previousFrame.SampleLevel(PassSrg::LinearSampler, tracePrevUV, 0).rgb;
|
||||
|
||||
// apply surface specular
|
||||
float3 specularF0 = PassSrg::m_specularF0.Load(screenCoords, 0).rgb;
|
||||
result.rgb *= specularF0;
|
||||
|
||||
// fade rays close to screen edge
|
||||
const float ScreenFadeDistance = 0.95f;
|
||||
float2 fadeAmount = max(max(0.0f, traceUV - ScreenFadeDistance), max(0.0f, 1.0f - traceUV - ScreenFadeDistance));
|
||||
fadeAmount /= (1.0f - ScreenFadeDistance);
|
||||
result.a = fallbackEdge ? 0.0f : 1.0f - max(fadeAmount.x, fadeAmount.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ray miss, add in the IBL/probe reflections from the specular pass
|
||||
float4 positionWS = mul(ViewSrg::m_viewMatrixInverse, positionVS);
|
||||
float3 cameraToPositionWS = normalize(positionWS - ViewSrg::m_worldPosition);
|
||||
float3 reflectDirWS = normalize(reflect(cameraToPositionWS, normalWS));
|
||||
|
||||
result.rgb += PassSrg::m_reflection.Load(screenCoords, 0).rgb;
|
||||
result.a = fallbackEdge ? 0.0f : 1.0f;
|
||||
}
|
||||
|
||||
// downsample depth
|
||||
float downsampledDepth = 0.0f;
|
||||
for (int y = -2; y < 2; ++y)
|
||||
{
|
||||
for (int x = -2; x < 2; ++x)
|
||||
{
|
||||
float depth = PassSrg::m_depth.Load(screenCoords + int2(x, y), 0).r;
|
||||
|
||||
// take the closest depth sample (larger depth value due to reverse depth)
|
||||
if (depth > downsampledDepth)
|
||||
{
|
||||
downsampledDepth = depth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PSOutput OUT;
|
||||
OUT.m_color = result;
|
||||
OUT.m_depth = downsampledDepth;
|
||||
return OUT;
|
||||
}
|
||||
|
||||
+2
-1
@@ -10,7 +10,8 @@
|
||||
{
|
||||
"Depth" :
|
||||
{
|
||||
"Enable" : false
|
||||
"Enable" : true, // required to bind the depth buffer SRV
|
||||
"CompareFunc" : "Always"
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -100,6 +100,7 @@
|
||||
#include <DiffuseGlobalIllumination/DiffuseProbeGridRenderPass.h>
|
||||
#include <DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.h>
|
||||
#include <DiffuseGlobalIllumination/DiffuseGlobalIlluminationFeatureProcessor.h>
|
||||
#include <ReflectionScreenSpace/ReflectionScreenSpaceTracePass.h>
|
||||
#include <ReflectionScreenSpace/ReflectionScreenSpaceBlurPass.h>
|
||||
#include <ReflectionScreenSpace/ReflectionScreenSpaceBlurChildPass.h>
|
||||
#include <ReflectionScreenSpace/ReflectionScreenSpaceCompositePass.h>
|
||||
@@ -292,6 +293,7 @@ namespace AZ
|
||||
passSystem->AddPassCreator(Name("DeferredFogPass"), &DeferredFogPass::Create);
|
||||
|
||||
// Add Reflection passes
|
||||
passSystem->AddPassCreator(Name("ReflectionScreenSpaceTracePass"), &Render::ReflectionScreenSpaceTracePass::Create);
|
||||
passSystem->AddPassCreator(Name("ReflectionScreenSpaceBlurPass"), &Render::ReflectionScreenSpaceBlurPass::Create);
|
||||
passSystem->AddPassCreator(Name("ReflectionScreenSpaceBlurChildPass"), &Render::ReflectionScreenSpaceBlurChildPass::Create);
|
||||
passSystem->AddPassCreator(Name("ReflectionScreenSpaceCompositePass"), &Render::ReflectionScreenSpaceCompositePass::Create);
|
||||
|
||||
+5
-5
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
#include "ReflectionCopyFrameBufferPass.h"
|
||||
#include "ReflectionScreenSpaceBlurPass.h"
|
||||
#include "ReflectionScreenSpaceTracePass.h"
|
||||
#include <Atom/RPI.Public/Pass/PassSystemInterface.h>
|
||||
#include <Atom/RPI.Public/Pass/PassFilter.h>
|
||||
|
||||
@@ -28,16 +28,16 @@ namespace AZ
|
||||
|
||||
void ReflectionCopyFrameBufferPass::BuildInternal()
|
||||
{
|
||||
RPI::PassFilter passFilter = RPI::PassFilter::CreateWithPassName(AZ::Name("ReflectionScreenSpaceBlurPass"), GetRenderPipeline());
|
||||
RPI::PassFilter passFilter = RPI::PassFilter::CreateWithPassName(AZ::Name("ReflectionScreenSpaceTracePass"), GetRenderPipeline());
|
||||
RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [this](RPI::Pass* pass) -> RPI::PassFilterExecutionFlow
|
||||
{
|
||||
Render::ReflectionScreenSpaceBlurPass* blurPass = azrtti_cast<ReflectionScreenSpaceBlurPass*>(pass);
|
||||
Data::Instance<RPI::AttachmentImage>& frameBufferAttachment = blurPass->GetFrameBufferImageAttachment();
|
||||
Render::ReflectionScreenSpaceTracePass* tracePass = azrtti_cast<ReflectionScreenSpaceTracePass*>(pass);
|
||||
Data::Instance<RPI::AttachmentImage>& frameBufferAttachment = tracePass->GetPreviousFrameImageAttachment();
|
||||
|
||||
RPI::PassAttachmentBinding& outputBinding = GetOutputBinding(0);
|
||||
AttachImageToSlot(outputBinding.m_name, frameBufferAttachment);
|
||||
|
||||
return RPI::PassFilterExecutionFlow::StopVisitingPasses;
|
||||
return RPI::PassFilterExecutionFlow::StopVisitingPasses;
|
||||
});
|
||||
|
||||
FullscreenTrianglePass::BuildInternal();
|
||||
|
||||
+21
-28
@@ -12,6 +12,7 @@
|
||||
#include <Atom/RHI/FrameGraphAttachmentInterface.h>
|
||||
#include <Atom/RHI.Reflect/ImageViewDescriptor.h>
|
||||
#include <Atom/RPI.Reflect/Pass/FullscreenTrianglePassData.h>
|
||||
#include <Atom/RPI.Reflect/Pass/PassName.h>
|
||||
#include <Atom/RPI.Public/Pass/PassDefines.h>
|
||||
#include <Atom/RPI.Public/Pass/PassFactory.h>
|
||||
#include <Atom/RPI.Public/Pass/PassSystemInterface.h>
|
||||
@@ -79,7 +80,7 @@ namespace AZ
|
||||
horizontalBlurChildDesc.m_passTemplate = blurHorizontalPassTemplate;
|
||||
|
||||
// add child passes to perform the vertical and horizontal Gaussian blur for each roughness mip level
|
||||
for (uint32_t mip = 0; mip < m_numBlurMips; ++mip)
|
||||
for (uint32_t mip = 0; mip < NumMipLevels - 1; ++mip)
|
||||
{
|
||||
// create Vertical blur child passes
|
||||
{
|
||||
@@ -114,35 +115,15 @@ namespace AZ
|
||||
RemoveChildren();
|
||||
m_flags.m_createChildren = true;
|
||||
|
||||
Data::Instance<RPI::AttachmentImagePool> pool = RPI::ImageSystemInterface::Get()->GetSystemAttachmentPool();
|
||||
|
||||
// retrieve the image attachment from the pass
|
||||
AZ_Assert(m_ownedAttachments.size() == 1, "ReflectionScreenSpaceBlurPass must have exactly one ImageAttachment defined");
|
||||
RPI::Ptr<RPI::PassAttachment> reflectionImageAttachment = m_ownedAttachments[0];
|
||||
|
||||
// update the image attachment descriptor to sync up size and format
|
||||
reflectionImageAttachment->Update();
|
||||
|
||||
// change the lifetime since we want it to live between frames
|
||||
reflectionImageAttachment->m_lifetime = RHI::AttachmentLifetimeType::Imported;
|
||||
|
||||
// set the bind flags
|
||||
RHI::ImageDescriptor& imageDesc = reflectionImageAttachment->m_descriptor.m_image;
|
||||
imageDesc.m_bindFlags |= RHI::ImageBindFlags::Color | RHI::ImageBindFlags::ShaderReadWrite;
|
||||
|
||||
// create the image attachment
|
||||
RHI::ClearValue clearValue = RHI::ClearValue::CreateVector4Float(0, 0, 0, 0);
|
||||
m_frameBufferImageAttachment = RPI::AttachmentImage::Create(*pool.get(), imageDesc, Name(reflectionImageAttachment->m_path.GetCStr()), &clearValue, nullptr);
|
||||
|
||||
reflectionImageAttachment->m_path = m_frameBufferImageAttachment->GetAttachmentId();
|
||||
reflectionImageAttachment->m_importedResource = m_frameBufferImageAttachment;
|
||||
|
||||
uint32_t mipLevels = reflectionImageAttachment->m_descriptor.m_image.m_mipLevels;
|
||||
// retrieve the reflection, downsampled normal, and downsampled depth attachments
|
||||
RPI::PassAttachment* reflectionImageAttachment = GetInputOutputBinding(0).m_attachment.get();
|
||||
RHI::Size imageSize = reflectionImageAttachment->m_descriptor.m_image.m_size;
|
||||
|
||||
RPI::PassAttachment* downsampledDepthImageAttachment = GetInputOutputBinding(1).m_attachment.get();
|
||||
|
||||
// create transient attachments, one for each blur mip level
|
||||
AZStd::vector<RPI::PassAttachment*> transientPassAttachments;
|
||||
for (uint32_t mip = 1; mip <= mipLevels - 1; ++mip)
|
||||
for (uint32_t mip = 1; mip <= NumMipLevels - 1; ++mip)
|
||||
{
|
||||
RHI::Size mipSize = imageSize.GetReducedMip(mip);
|
||||
|
||||
@@ -160,8 +141,6 @@ namespace AZ
|
||||
m_ownedAttachments.push_back(transientPassAttachment);
|
||||
}
|
||||
|
||||
m_numBlurMips = mipLevels - 1;
|
||||
|
||||
// call ParentPass::BuildInternal() first to configure the slots and auto-add the empty bindings,
|
||||
// then we will assign attachments to the bindings
|
||||
ParentPass::BuildInternal();
|
||||
@@ -170,13 +149,27 @@ namespace AZ
|
||||
uint32_t attachmentIndex = 0;
|
||||
for (auto& verticalBlurChildPass : m_verticalBlurChildPasses)
|
||||
{
|
||||
// mip0 source input
|
||||
RPI::PassAttachmentBinding& inputAttachmentBinding = verticalBlurChildPass->GetInputOutputBinding(0);
|
||||
inputAttachmentBinding.SetAttachment(reflectionImageAttachment);
|
||||
inputAttachmentBinding.m_connectedBinding = &GetInputOutputBinding(0);
|
||||
|
||||
// mipN transient output
|
||||
RPI::PassAttachmentBinding& outputAttachmentBinding = verticalBlurChildPass->GetInputOutputBinding(1);
|
||||
outputAttachmentBinding.SetAttachment(transientPassAttachments[attachmentIndex]);
|
||||
|
||||
// setup downsampled depth output
|
||||
// Note: this is a vertical pass output only, and each vertical child pass writes a specific mip level
|
||||
uint32_t mipLevel = attachmentIndex + 1;
|
||||
|
||||
// downsampled depth output
|
||||
RPI::PassAttachmentBinding& downsampledDepthAttachmentBinding = verticalBlurChildPass->GetInputOutputBinding(2);
|
||||
RHI::ImageViewDescriptor downsampledDepthOutputViewDesc;
|
||||
downsampledDepthOutputViewDesc.m_mipSliceMin = static_cast<int16_t>(mipLevel);
|
||||
downsampledDepthOutputViewDesc.m_mipSliceMax = static_cast<int16_t>(mipLevel);
|
||||
downsampledDepthAttachmentBinding.m_unifiedScopeDesc.SetAsImage(downsampledDepthOutputViewDesc);
|
||||
downsampledDepthAttachmentBinding.SetAttachment(downsampledDepthImageAttachment);
|
||||
|
||||
attachmentIndex++;
|
||||
}
|
||||
|
||||
|
||||
+2
-9
@@ -29,12 +29,8 @@ namespace AZ
|
||||
//! Creates a new pass without a PassTemplate
|
||||
static RPI::Ptr<ReflectionScreenSpaceBlurPass> Create(const RPI::PassDescriptor& descriptor);
|
||||
|
||||
//! Returns the frame buffer image attachment used by the ReflectionFrameBufferCopy pass
|
||||
//! to store the previous frame image
|
||||
Data::Instance<RPI::AttachmentImage>& GetFrameBufferImageAttachment() { return m_frameBufferImageAttachment; }
|
||||
|
||||
//! Returns the number of mip levels in the blur
|
||||
uint32_t GetNumBlurMips() const { return m_numBlurMips; }
|
||||
//! The total number of mip levels in the blur (including mip0)
|
||||
static const uint32_t NumMipLevels = 5;
|
||||
|
||||
private:
|
||||
explicit ReflectionScreenSpaceBlurPass(const RPI::PassDescriptor& descriptor);
|
||||
@@ -47,9 +43,6 @@ namespace AZ
|
||||
|
||||
AZStd::vector<RPI::Ptr<RPI::FullscreenTrianglePass>> m_verticalBlurChildPasses;
|
||||
AZStd::vector<RPI::Ptr<RPI::FullscreenTrianglePass>> m_horizontalBlurChildPasses;
|
||||
|
||||
Data::Instance<RPI::AttachmentImage> m_frameBufferImageAttachment;
|
||||
uint32_t m_numBlurMips = 0;
|
||||
};
|
||||
} // namespace RPI
|
||||
} // namespace AZ
|
||||
|
||||
+15
-16
@@ -26,6 +26,19 @@ namespace AZ
|
||||
{
|
||||
}
|
||||
|
||||
bool ReflectionScreenSpaceCompositePass::IsEnabled() const
|
||||
{
|
||||
// delay for a few frames to ensure that the previous frame texture is populated
|
||||
static const uint32_t FrameDelay = 10;
|
||||
if (m_frameDelayCount < FrameDelay)
|
||||
{
|
||||
m_frameDelayCount++;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ReflectionScreenSpaceCompositePass::CompileResources([[maybe_unused]] const RHI::FrameGraphCompileContext& context)
|
||||
{
|
||||
if (!m_shaderResourceGroup)
|
||||
@@ -33,22 +46,8 @@ namespace AZ
|
||||
return;
|
||||
}
|
||||
|
||||
RPI::PassFilter passFilter = RPI::PassFilter::CreateWithPassName(AZ::Name("ReflectionScreenSpaceBlurPass"), GetRenderPipeline());
|
||||
|
||||
RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [this](RPI::Pass* pass) -> RPI::PassFilterExecutionFlow
|
||||
{
|
||||
Render::ReflectionScreenSpaceBlurPass* blurPass = azrtti_cast<ReflectionScreenSpaceBlurPass*>(pass);
|
||||
|
||||
// compute the max mip level based on the available mips in the previous frame image, and capping it
|
||||
// to stay within a range that has reasonable data
|
||||
const uint32_t MaxNumRoughnessMips = 8;
|
||||
uint32_t maxMipLevel = AZStd::min(MaxNumRoughnessMips, blurPass->GetNumBlurMips()) - 1;
|
||||
|
||||
auto constantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_maxMipLevel"));
|
||||
m_shaderResourceGroup->SetConstant(constantIndex, maxMipLevel);
|
||||
|
||||
return RPI::PassFilterExecutionFlow::StopVisitingPasses;
|
||||
});
|
||||
auto constantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_maxMipLevel"));
|
||||
m_shaderResourceGroup->SetConstant(constantIndex, ReflectionScreenSpaceBlurPass::NumMipLevels - 1);
|
||||
|
||||
FullscreenTrianglePass::CompileResources(context);
|
||||
}
|
||||
|
||||
+3
@@ -34,6 +34,9 @@ namespace AZ
|
||||
|
||||
// Pass Overrides...
|
||||
void CompileResources(const RHI::FrameGraphCompileContext& context) override;
|
||||
bool IsEnabled() const override;
|
||||
|
||||
mutable uint32_t m_frameDelayCount = 0;
|
||||
};
|
||||
} // namespace RPI
|
||||
} // namespace AZ
|
||||
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ReflectionScreenSpaceTracePass.h"
|
||||
#include <Atom/RPI.Public/Pass/PassSystemInterface.h>
|
||||
#include <Atom/RPI.Public/Pass/PassFilter.h>
|
||||
#include <Atom/RPI.Public/RenderPipeline.h>
|
||||
#include <Atom/RPI.Public/Image/ImageSystemInterface.h>
|
||||
#include <Atom/RPI.Public/Image/AttachmentImagePool.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
RPI::Ptr<ReflectionScreenSpaceTracePass> ReflectionScreenSpaceTracePass::Create(const RPI::PassDescriptor& descriptor)
|
||||
{
|
||||
RPI::Ptr<ReflectionScreenSpaceTracePass> pass = aznew ReflectionScreenSpaceTracePass(descriptor);
|
||||
return AZStd::move(pass);
|
||||
}
|
||||
|
||||
ReflectionScreenSpaceTracePass::ReflectionScreenSpaceTracePass(const RPI::PassDescriptor& descriptor)
|
||||
: RPI::FullscreenTrianglePass(descriptor)
|
||||
{
|
||||
}
|
||||
|
||||
void ReflectionScreenSpaceTracePass::BuildInternal()
|
||||
{
|
||||
Data::Instance<RPI::AttachmentImagePool> pool = RPI::ImageSystemInterface::Get()->GetSystemAttachmentPool();
|
||||
|
||||
// retrieve the previous frame image attachment from the pass
|
||||
AZ_Assert(m_ownedAttachments.size() == 3, "ReflectionScreenSpaceTracePass must have the following attachment images defined: ReflectionImage, DownSampledDepthImage, and PreviousFrameImage");
|
||||
RPI::Ptr<RPI::PassAttachment> previousFrameImageAttachment = m_ownedAttachments[2];
|
||||
|
||||
// update the image attachment descriptor to sync up size and format
|
||||
previousFrameImageAttachment->Update();
|
||||
|
||||
// change the lifetime since we want it to live between frames
|
||||
previousFrameImageAttachment->m_lifetime = RHI::AttachmentLifetimeType::Imported;
|
||||
|
||||
// set the bind flags
|
||||
RHI::ImageDescriptor& imageDesc = previousFrameImageAttachment->m_descriptor.m_image;
|
||||
imageDesc.m_bindFlags |= RHI::ImageBindFlags::Color | RHI::ImageBindFlags::ShaderReadWrite;
|
||||
|
||||
// create the image attachment
|
||||
RHI::ClearValue clearValue = RHI::ClearValue::CreateVector4Float(0, 0, 0, 0);
|
||||
m_previousFrameImageAttachment = RPI::AttachmentImage::Create(*pool.get(), imageDesc, Name(previousFrameImageAttachment->m_path.GetCStr()), &clearValue, nullptr);
|
||||
|
||||
previousFrameImageAttachment->m_path = m_previousFrameImageAttachment->GetAttachmentId();
|
||||
previousFrameImageAttachment->m_importedResource = m_previousFrameImageAttachment;
|
||||
}
|
||||
|
||||
} // namespace RPI
|
||||
} // namespace AZ
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <Atom/RPI.Public/Pass/Pass.h>
|
||||
#include <Atom/RPI.Public/Pass/FullscreenTrianglePass.h>
|
||||
#include <Atom/RPI.Public/Shader/ShaderResourceGroup.h>
|
||||
#include <Atom/RPI.Public/Shader/Shader.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
//! This pass traces screenspace reflections from the previous frame image.
|
||||
class ReflectionScreenSpaceTracePass
|
||||
: public RPI::FullscreenTrianglePass
|
||||
{
|
||||
AZ_RPI_PASS(DiffuseProbeGridDownsamplePass);
|
||||
|
||||
public:
|
||||
AZ_RTTI(Render::ReflectionScreenSpaceTracePass, "{70FD45E9-8363-4AA1-A514-3C24AC975E53}", FullscreenTrianglePass);
|
||||
AZ_CLASS_ALLOCATOR(Render::ReflectionScreenSpaceTracePass, SystemAllocator, 0);
|
||||
|
||||
//! Creates a new pass without a PassTemplate
|
||||
static RPI::Ptr<ReflectionScreenSpaceTracePass> Create(const RPI::PassDescriptor& descriptor);
|
||||
|
||||
Data::Instance<RPI::AttachmentImage>& GetPreviousFrameImageAttachment() { return m_previousFrameImageAttachment; }
|
||||
|
||||
private:
|
||||
explicit ReflectionScreenSpaceTracePass(const RPI::PassDescriptor& descriptor);
|
||||
|
||||
// Pass behavior overrides...
|
||||
virtual void BuildInternal() override;
|
||||
|
||||
Data::Instance<RPI::AttachmentImage> m_previousFrameImageAttachment;
|
||||
};
|
||||
} // namespace RPI
|
||||
} // namespace AZ
|
||||
@@ -275,6 +275,8 @@ set(FILES
|
||||
Source/RayTracing/RayTracingPassData.h
|
||||
Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp
|
||||
Source/ReflectionProbe/ReflectionProbe.cpp
|
||||
Source/ReflectionScreenSpace/ReflectionScreenSpaceTracePass.cpp
|
||||
Source/ReflectionScreenSpace/ReflectionScreenSpaceTracePass.h
|
||||
Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurPass.cpp
|
||||
Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurPass.h
|
||||
Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurChildPass.cpp
|
||||
|
||||
Reference in New Issue
Block a user