From 5f939430eed2cac4c6466794fe589f94ba56da97 Mon Sep 17 00:00:00 2001 From: ExMatics HydrogenC <33123710+HydrogenC@users.noreply.github.com> Date: Mon, 17 Jun 2024 23:00:48 +0800 Subject: [PATCH] Initial commit for forward software reflection --- .../Features/ForwardShading.hlsl | 42 +++++++++++++++++++ .../Materials/ForwardMaterialShader.cpp | 1 + .../Materials/MaterialShaderFeatures.cpp | 12 ++++++ Source/Shaders/SSR.shader | 11 +++-- 4 files changed, 62 insertions(+), 4 deletions(-) diff --git a/Content/Editor/MaterialTemplates/Features/ForwardShading.hlsl b/Content/Editor/MaterialTemplates/Features/ForwardShading.hlsl index 9dbc19369..0df9abe9e 100644 --- a/Content/Editor/MaterialTemplates/Features/ForwardShading.hlsl +++ b/Content/Editor/MaterialTemplates/Features/ForwardShading.hlsl @@ -9,6 +9,10 @@ #define MATERIAL_REFLECTIONS_SSR 1 #if MATERIAL_REFLECTIONS == MATERIAL_REFLECTIONS_SSR #include "./Flax/SSR.hlsl" +#if USE_GLOBAL_SURFACE_ATLAS +#include "./Flax/GlobalSignDistanceField.hlsl" +#include "./Flax/GI/GlobalSurfaceAtlas.hlsl" +#endif #endif #endif #include "./Flax/Lighting.hlsl" @@ -27,12 +31,23 @@ LightData LocalLights[MAX_LOCAL_LIGHTS]; TextureCube EnvProbe : register(t__SRV__); TextureCube SkyLightTexture : register(t__SRV__); Texture2DArray DirectionalLightShadowMap : register(t__SRV__); +#if USE_GLOBAL_SURFACE_ATLAS +Texture3D GlobalSDFTex : register(t__SRV__); +Texture3D GlobalSDFMip : register(t__SRV__); +ByteAddressBuffer GlobalSurfaceAtlasChunks : register(t__SRV__); +ByteAddressBuffer RWGlobalSurfaceAtlasCulledObjects : register(t__SRV__); +Buffer GlobalSurfaceAtlasObjects : register(t__SRV__); +Texture2D GlobalSurfaceAtlasDepth : register(t__SRV__); +Texture2D GlobalSurfaceAtlasTex : register(t__SRV__); +#endif @4// Forward Shading: Utilities DECLARE_LIGHTSHADOWDATA_ACCESS(DirectionalLightShadow); @5// Forward Shading: Shaders // Pixel Shader function for Forward Pass META_PS(USE_FORWARD, FEATURE_LEVEL_ES2) +META_PERMUTATION_1(USE_GLOBAL_SURFACE_ATLAS=0) +META_PERMUTATION_1(USE_GLOBAL_SURFACE_ATLAS=1) void PS_Forward( in PixelInput input ,out float4 output : SV_Target0 @@ -125,6 +140,33 @@ void PS_Forward( float3 screenColor = sceneColorTexture.SampleLevel(SamplerPointClamp, hit.xy, 0).rgb; reflections = lerp(reflections, screenColor, hit.z); } + + // Fallback to software tracing if possible +#if USE_GLOBAL_SURFACE_ATLAS && CAN_USE_GLOBAL_SURFACE_ATLAS + + // If hit.z >= 0.9f then skip sdf tracing + if (hit.z < 0.9f) + { + // Don't use temporal effect in forward pass + float3 reflectWS = ScreenSpaceReflectionDirection(screenUV, gBuffer, gBufferData.ViewPos); + + GlobalSDFTrace sdfTrace; + float maxDistance = 100000; + float selfOcclusionBias = GlobalSDF.CascadeVoxelSize[0]; + sdfTrace.Init(gBuffer.WorldPos + gBuffer.Normal * selfOcclusionBias, reflectWS, 0.0f, maxDistance); + GlobalSDFHit sdfHit = RayTraceGlobalSDF(GlobalSDF, GlobalSDFTex, GlobalSDFMip, sdfTrace); + if (sdfHit.IsHit()) + { + float3 hitPosition = sdfHit.GetHitPosition(sdfTrace); + float surfaceThreshold = GetGlobalSurfaceAtlasThreshold(GlobalSDF, sdfHit); + float4 surfaceAtlas = SampleGlobalSurfaceAtlas(GlobalSurfaceAtlas, GlobalSurfaceAtlasChunks, RWGlobalSurfaceAtlasCulledObjects, GlobalSurfaceAtlasObjects, GlobalSurfaceAtlasDepth, GlobalSurfaceAtlasTex, hitPosition, -reflectWS, surfaceThreshold); + + float3 screenColor = sceneColorTexture.SampleLevel(SamplerPointClamp, hit.xy, 0).rgb; + reflections = lerp(surfaceAtlas, float4(screenColor, 1), hit.z); + } + } + +#endif #endif light.rgb += reflections * GetReflectionSpecularLighting(ViewPos, gBuffer) * light.a; diff --git a/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp b/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp index af2b30348..31c2f8166 100644 --- a/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp @@ -178,6 +178,7 @@ bool ForwardMaterialShader::Load() psDesc.VS = _shader->GetVS("VS"); if (psDesc.VS == nullptr) return true; + psDesc.PS = _shader->GetPS("PS_Forward"); psDesc.DepthWriteEnable = false; psDesc.BlendMode = BlendingMode::AlphaBlend; diff --git a/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp b/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp index 43646cc0e..d385ec24f 100644 --- a/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp +++ b/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp @@ -5,6 +5,7 @@ #include "Engine/Graphics/Textures/GPUTexture.h" #include "Engine/Renderer/RenderList.h" #include "Engine/Renderer/ShadowsPass.h" +#include "Engine/Renderer/GlobalSignDistanceFieldPass.h" #if USE_EDITOR #include "Engine/Renderer/Lightmaps.h" #endif @@ -22,6 +23,8 @@ void ForwardShadingFeature::Bind(MaterialShader::BindParameters& params, SpanUnBindSR(envProbeShaderRegisterIndex); } + // Bind sdf resources if using software reflections + if (!GlobalSignDistanceFieldPass::Instance()->Render(params.RenderContext, params.GPUContext, bindingDataSDF) && + !GlobalSurfaceAtlasPass::Instance()->Render(params.RenderContext, params.GPUContext, bindingDataSurfaceAtlas)) + { + useGlobalSurfaceAtlas = true; + data.GlobalSDF = bindingDataSDF.Constants; + data.GlobalSurfaceAtlas = bindingDataSurfaceAtlas.Constants; + } + // Set local lights data.LocalLightsCount = 0; const BoundingSphere objectBounds(drawCall.ObjectPosition, drawCall.ObjectRadius); diff --git a/Source/Shaders/SSR.shader b/Source/Shaders/SSR.shader index a813bdf36..ca177ff09 100644 --- a/Source/Shaders/SSR.shader +++ b/Source/Shaders/SSR.shader @@ -133,11 +133,12 @@ float4 PS_RayTracePass(Quad_VS2PS input) : SV_Target0 return result; } - // Calculate reflection direction (the same TraceScreenSpaceReflection) - float3 reflectWS = ScreenSpaceReflectionDirection(input.TexCoord, gBuffer, gBufferData.ViewPos, TemporalEffect, TemporalTime, BRDFBias); - // Fallback to Global SDF and Global Surface Atlas tracing #if USE_GLOBAL_SURFACE_ATLAS && CAN_USE_GLOBAL_SURFACE_ATLAS + + // Calculate reflection direction (the same TraceScreenSpaceReflection) + float3 reflectWS = ScreenSpaceReflectionDirection(input.TexCoord, gBuffer, gBufferData.ViewPos, TemporalEffect, TemporalTime, BRDFBias); + GlobalSDFTrace sdfTrace; float maxDistance = 100000; float selfOcclusionBias = GlobalSDF.CascadeVoxelSize[0]; @@ -148,7 +149,9 @@ float4 PS_RayTracePass(Quad_VS2PS input) : SV_Target0 float3 hitPosition = sdfHit.GetHitPosition(sdfTrace); float surfaceThreshold = GetGlobalSurfaceAtlasThreshold(GlobalSDF, sdfHit); float4 surfaceAtlas = SampleGlobalSurfaceAtlas(GlobalSurfaceAtlas, GlobalSurfaceAtlasChunks, RWGlobalSurfaceAtlasCulledObjects, GlobalSurfaceAtlasObjects, GlobalSurfaceAtlasDepth, GlobalSurfaceAtlasTex, hitPosition, -reflectWS, surfaceThreshold); - result = lerp(surfaceAtlas, float4(result.rgb, 1), result.a); + // Now the sdf reflection part is significantly darker than the screen space part + // TODO: Maybe multiply surfaceAtlas by a constant to make it brighter + result = lerp(surfaceAtlas, float4(result.rgb, 1), result.a); } #endif