Merge branch 'HydrogenC-forward-software-refl'

This commit is contained in:
Wojtek Figat
2024-08-05 19:44:51 +02:00
42 changed files with 224 additions and 62 deletions

BIN
Content/Editor/Camera/M_Camera.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Content/Editor/DefaultFontMaterial.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

BIN
Content/Editor/Gizmo/Material.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/Gizmo/MaterialWire.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Content/Editor/Highlight Material.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/Icons/IconsMaterial.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

View File

@@ -125,6 +125,20 @@ 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 < REFLECTIONS_HIT_THRESHOLD)
{
float3 reflectWS = ScreenSpaceReflectionDirection(screenUV, gBuffer, ViewPos);
float4 surfaceAtlas;
if (TraceSDFSoftwareReflections(gBuffer, reflectWS, surfaceAtlas))
{
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;

View File

@@ -0,0 +1,37 @@
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
@0// SDF Reflections: Defines
#define USE_GLOBAL_SURFACE_ATLAS 1
@1// SDF Reflections: Includes
#include "./Flax/GlobalSignDistanceField.hlsl"
#include "./Flax/GI/GlobalSurfaceAtlas.hlsl"
@2// SDF Reflections: Constants
GlobalSDFData GlobalSDF;
GlobalSurfaceAtlasData GlobalSurfaceAtlas;
@3// SDF Reflections: Resources
Texture3D<float> GlobalSDFTex : register(t__SRV__);
Texture3D<float> GlobalSDFMip : register(t__SRV__);
ByteAddressBuffer GlobalSurfaceAtlasChunks : register(t__SRV__);
ByteAddressBuffer RWGlobalSurfaceAtlasCulledObjects : register(t__SRV__);
Buffer<float4> GlobalSurfaceAtlasObjects : register(t__SRV__);
Texture2D GlobalSurfaceAtlasDepth : register(t__SRV__);
Texture2D GlobalSurfaceAtlasTex : register(t__SRV__);
@4// SDF Reflections: Utilities
bool TraceSDFSoftwareReflections(GBufferSample gBuffer, float3 reflectWS, out float4 surfaceAtlas)
{
GlobalSDFTrace sdfTrace;
float maxDistance = GLOBAL_SDF_WORLD_SIZE;
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);
surfaceAtlas = SampleGlobalSurfaceAtlas(GlobalSurfaceAtlas, GlobalSurfaceAtlasChunks, RWGlobalSurfaceAtlasCulledObjects, GlobalSurfaceAtlasObjects, GlobalSurfaceAtlasDepth, GlobalSurfaceAtlasTex, hitPosition, -reflectWS, surfaceThreshold);
return true;
}
return false;
}
@5// SDF Reflections: Shaders

Binary file not shown.

Binary file not shown.

BIN
Content/Editor/SpriteMaterial.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Content/Editor/TexturePreviewMaterial.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/Wires Debug Material.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

BIN
Content/Engine/DefaultMaterial.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Engine/DefaultRadialMenu.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Engine/DefaultTerrainMaterial.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Engine/SingleColorMaterial.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Engine/SkyboxMaterial.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Shaders/SSR.flax (Stored with Git LFS)

Binary file not shown.

View File

@@ -52,7 +52,11 @@ void ForwardMaterialShader::Bind(BindParameters& params)
// Setup features
if ((_info.FeaturesFlags & MaterialFeaturesFlags::GlobalIllumination) != MaterialFeaturesFlags::None)
{
GlobalIlluminationFeature::Bind(params, cb, srv);
if ((_info.FeaturesFlags & MaterialFeaturesFlags::ScreenSpaceReflections) != MaterialFeaturesFlags::None)
SDFReflectionsFeature::Bind(params, cb, srv);
}
ForwardShadingFeature::Bind(params, cb, srv);
// Setup parameters

View File

@@ -10,7 +10,7 @@
/// <summary>
/// Current materials shader version.
/// </summary>
#define MATERIAL_GRAPH_VERSION 162
#define MATERIAL_GRAPH_VERSION 163
class Material;
class GPUShader;

View File

@@ -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
@@ -195,6 +196,58 @@ bool GlobalIlluminationFeature::Bind(MaterialShader::BindParameters& params, Spa
return useGI;
}
bool SDFReflectionsFeature::Bind(MaterialShader::BindParameters& params, Span<byte>& cb, int32& srv)
{
auto& data = *(Data*)cb.Get();
ASSERT_LOW_LAYER(cb.Length() >= sizeof(Data));
bool useSDFReflections = false;
if (EnumHasAnyFlags(params.RenderContext.View.Flags, ViewFlags::Reflections))
{
switch (params.RenderContext.List->Settings.ScreenSpaceReflections.TraceMode)
{
case ReflectionsTraceMode::SoftwareTracing:
{
GlobalSignDistanceFieldPass::BindingData bindingDataSDF;
GlobalSurfaceAtlasPass::BindingData bindingDataSurfaceAtlas;
if (!GlobalSignDistanceFieldPass::Instance()->Get(params.RenderContext.Buffers, bindingDataSDF) &&
!GlobalSurfaceAtlasPass::Instance()->Get(params.RenderContext.Buffers, bindingDataSurfaceAtlas))
{
useSDFReflections = true;
// Bind SDF and Surface Atlas data
data.GlobalSDF = bindingDataSDF.Constants;
data.GlobalSurfaceAtlas = bindingDataSurfaceAtlas.Constants;
params.GPUContext->BindSR(srv + 0, bindingDataSDF.Texture ? bindingDataSDF.Texture->ViewVolume() : nullptr);
params.GPUContext->BindSR(srv + 1, bindingDataSDF.TextureMip ? bindingDataSDF.TextureMip->ViewVolume() : nullptr);
params.GPUContext->BindSR(srv + 2, bindingDataSurfaceAtlas.Chunks ? bindingDataSurfaceAtlas.Chunks->View() : nullptr);
params.GPUContext->BindSR(srv + 3, bindingDataSurfaceAtlas.CulledObjects ? bindingDataSurfaceAtlas.CulledObjects->View() : nullptr);
params.GPUContext->BindSR(srv + 4, bindingDataSurfaceAtlas.Objects ? bindingDataSurfaceAtlas.Objects->View() : nullptr);
params.GPUContext->BindSR(srv + 5, bindingDataSurfaceAtlas.AtlasDepth->View());
params.GPUContext->BindSR(srv + 6, bindingDataSurfaceAtlas.AtlasLighting->View());
}
break;
}
}
}
if (!useSDFReflections)
{
// Unbind SRVs to prevent issues
data.GlobalSDF.CascadesCount = 0;
params.GPUContext->UnBindSR(srv + 0);
params.GPUContext->UnBindSR(srv + 1);
params.GPUContext->UnBindSR(srv + 2);
params.GPUContext->UnBindSR(srv + 3);
params.GPUContext->UnBindSR(srv + 4);
params.GPUContext->UnBindSR(srv + 5);
params.GPUContext->UnBindSR(srv + 6);
}
cb = Span<byte>(cb.Get() + sizeof(Data), cb.Length() - sizeof(Data));
srv += SRVs;
return useSDFReflections;
}
#if USE_EDITOR
void ForwardShadingFeature::Generate(GeneratorData& data)
@@ -222,6 +275,11 @@ void GlobalIlluminationFeature::Generate(GeneratorData& data)
data.Template = TEXT("Features/GlobalIllumination.hlsl");
}
void SDFReflectionsFeature::Generate(GeneratorData& data)
{
data.Template = TEXT("Features/SDFReflections.hlsl");
}
void DistortionFeature::Generate(GeneratorData& data)
{
data.Template = TEXT("Features/Distortion.hlsl");

View File

@@ -6,6 +6,8 @@
#include "Engine/Core/Math/Rectangle.h"
#include "Engine/Core/Types/Span.h"
#include "Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.h"
#include "Engine/Renderer/GlobalSignDistanceFieldPass.h"
#include "Engine/Renderer/GI/GlobalSurfaceAtlasPass.h"
// Material shader features are plugin-based functionalities that are reusable between different material domains.
struct MaterialShaderFeature
@@ -91,6 +93,25 @@ struct GlobalIlluminationFeature : MaterialShaderFeature
#endif
};
// Material shader feature that adds SDF Reflections feature (software reflections).
struct SDFReflectionsFeature : MaterialShaderFeature
{
enum { SRVs = 7 };
PACK_STRUCT(struct Data
{
GlobalSignDistanceFieldPass::ConstantsData GlobalSDF;
GlobalSurfaceAtlasPass::ConstantsData GlobalSurfaceAtlas;
});
static bool Bind(MaterialShader::BindParameters& params, Span<byte>& cb, int32& srv);
#if USE_EDITOR
static void Generate(GeneratorData& data);
#endif
};
// Material shader feature that adds distortion vectors rendering pass.
struct DistortionFeature : MaterialShaderFeature
{

View File

@@ -360,6 +360,17 @@ void GlobalSurfaceAtlasPass::Dispose()
_shader = nullptr;
}
bool GlobalSurfaceAtlasPass::Get(const RenderBuffers* buffers, BindingData& result)
{
auto* surfaceAtlasData = buffers ? buffers->FindCustomBuffer<GlobalSurfaceAtlasCustomBuffer>(TEXT("GlobalSurfaceAtlas")) : nullptr;
if (surfaceAtlasData && surfaceAtlasData->LastFrameUsed + 1 >= Engine::FrameCount) // Allow to use Surface Atlas from the previous frame (not used currently)
{
result = surfaceAtlasData->Result;
return false;
}
return true;
}
bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* context, BindingData& result)
{
// Skip if not supported

View File

@@ -65,6 +65,14 @@ private:
void* _currentActorObject;
public:
/// <summary>
/// Gets the Global Surface Atlas (only if enabled in Graphics Settings).
/// </summary>
/// <param name="buffers">The rendering context buffers.</param>
/// <param name="result">The result Global Surface Atlas data for binding to the shaders.</param>
/// <returns>True if there is no valid Global Surface Atlas rendered during this frame, otherwise false.</returns>
bool Get(const RenderBuffers* buffers, BindingData& result);
/// <summary>
/// Renders the Global Surface Atlas.
/// </summary>

View File

@@ -188,40 +188,46 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo
{
case MaterialDomain::Surface:
if (materialInfo.TessellationMode != TessellationMethod::None)
ADD_FEATURE(TessellationFeature);
ADD_FEATURE(TessellationFeature);
if (materialInfo.BlendMode == MaterialBlendMode::Opaque)
ADD_FEATURE(MotionVectorsFeature);
ADD_FEATURE(MotionVectorsFeature);
if (materialInfo.BlendMode == MaterialBlendMode::Opaque)
ADD_FEATURE(LightmapFeature);
ADD_FEATURE(LightmapFeature);
if (materialInfo.BlendMode == MaterialBlendMode::Opaque)
ADD_FEATURE(DeferredShadingFeature);
ADD_FEATURE(DeferredShadingFeature);
if (materialInfo.BlendMode != MaterialBlendMode::Opaque && (materialInfo.FeaturesFlags & MaterialFeaturesFlags::DisableDistortion) == MaterialFeaturesFlags::None)
ADD_FEATURE(DistortionFeature);
ADD_FEATURE(DistortionFeature);
if (materialInfo.BlendMode != MaterialBlendMode::Opaque && EnumHasAnyFlags(materialInfo.FeaturesFlags, MaterialFeaturesFlags::GlobalIllumination))
ADD_FEATURE(GlobalIlluminationFeature);
{
ADD_FEATURE(GlobalIlluminationFeature);
// SDF Reflections is only valid when both GI and SSR is enabled
if (materialInfo.BlendMode != MaterialBlendMode::Opaque && EnumHasAnyFlags(materialInfo.FeaturesFlags, MaterialFeaturesFlags::ScreenSpaceReflections))
ADD_FEATURE(SDFReflectionsFeature);
}
if (materialInfo.BlendMode != MaterialBlendMode::Opaque)
ADD_FEATURE(ForwardShadingFeature);
ADD_FEATURE(ForwardShadingFeature);
break;
case MaterialDomain::Terrain:
if (materialInfo.TessellationMode != TessellationMethod::None)
ADD_FEATURE(TessellationFeature);
ADD_FEATURE(TessellationFeature);
ADD_FEATURE(LightmapFeature);
ADD_FEATURE(DeferredShadingFeature);
break;
case MaterialDomain::Particle:
if (materialInfo.BlendMode != MaterialBlendMode::Opaque && (materialInfo.FeaturesFlags & MaterialFeaturesFlags::DisableDistortion) == MaterialFeaturesFlags::None)
ADD_FEATURE(DistortionFeature);
ADD_FEATURE(DistortionFeature);
if (materialInfo.BlendMode != MaterialBlendMode::Opaque && EnumHasAnyFlags(materialInfo.FeaturesFlags, MaterialFeaturesFlags::GlobalIllumination))
ADD_FEATURE(GlobalIlluminationFeature);
ADD_FEATURE(GlobalIlluminationFeature);
ADD_FEATURE(ForwardShadingFeature);
break;
case MaterialDomain::Deformable:
if (materialInfo.TessellationMode != TessellationMethod::None)
ADD_FEATURE(TessellationFeature);
ADD_FEATURE(TessellationFeature);
if (materialInfo.BlendMode == MaterialBlendMode::Opaque)
ADD_FEATURE(DeferredShadingFeature);
ADD_FEATURE(DeferredShadingFeature);
if (materialInfo.BlendMode != MaterialBlendMode::Opaque)
ADD_FEATURE(ForwardShadingFeature);
ADD_FEATURE(ForwardShadingFeature);
break;
default:
break;
@@ -708,7 +714,7 @@ void MaterialGenerator::ProcessGroupMath(Box* box, Node* node, Value& value)
{
switch (node->TypeID)
{
// Vector Transform
// Vector Transform
case 30:
{
// Get input vector

View File

@@ -5,6 +5,9 @@
#include "./Flax/GBufferCommon.hlsl"
// Hit depth (view space) threshold to detect if sky was hit (value above it where 1.0f is default)
#define REFLECTIONS_HIT_THRESHOLD 0.9f
float GetSpecularOcclusion(float NoV, float roughnessSq, float ao)
{
return saturate(pow(NoV + ao, roughnessSq) - 1 + ao);

View File

@@ -129,17 +129,17 @@ float4 PS_RayTracePass(Quad_VS2PS input) : SV_Target0
float mip = clamp(log2(intersectionCircleRadius * TraceSizeMax), 0.0, MaxColorMiplevel);
float3 sampleColor = Texture0.SampleLevel(SamplerLinearClamp, screenHit.xy, mip).rgb;
result = float4(sampleColor, screenHit.z);
if (screenHit.z >= 0.9f)
if (screenHit.z >= REFLECTIONS_HIT_THRESHOLD)
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 maxDistance = GLOBAL_SDF_WORLD_SIZE;
float selfOcclusionBias = GlobalSDF.CascadeVoxelSize[0];
sdfTrace.Init(gBuffer.WorldPos + gBuffer.Normal * selfOcclusionBias, reflectWS, 0.0f, maxDistance);
GlobalSDFHit sdfHit = RayTraceGlobalSDF(GlobalSDF, GlobalSDFTex, GlobalSDFMip, sdfTrace);