From b6204ceb76ef3b4c935478e6b00680e8fd14136c Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 21 Jul 2026 13:25:09 +0200 Subject: [PATCH] Add DDGI reflections to transparent materials --- .../Features/ForwardShading.hlsl | 16 ++++++++++------ .../Features/GlobalIllumination.hlsl | 12 ++++++++++-- Flax.flaxproj | 2 +- .../Engine/Graphics/Materials/MaterialShader.h | 2 +- .../Materials/MaterialShaderFeatures.cpp | 2 ++ .../Graphics/Materials/MaterialShaderFeatures.h | 2 +- .../GI/DynamicDiffuseGlobalIllumination.cpp | 1 + .../GI/DynamicDiffuseGlobalIllumination.h | 2 +- Source/Shaders/GI/DDGI.hlsl | 2 +- 9 files changed, 28 insertions(+), 13 deletions(-) diff --git a/Content/Editor/MaterialTemplates/Features/ForwardShading.hlsl b/Content/Editor/MaterialTemplates/Features/ForwardShading.hlsl index 230c454f4..8e03a2056 100644 --- a/Content/Editor/MaterialTemplates/Features/ForwardShading.hlsl +++ b/Content/Editor/MaterialTemplates/Features/ForwardShading.hlsl @@ -112,12 +112,17 @@ void PS_Forward( // Calculate lighting from Global Illumination #if USE_GI light += GetGlobalIlluminationLighting(gBuffer); + // TODO: when using both indirect and specular lighting from DDGI, merge cascade selection and probes visibility resolving to be done once #endif // Calculate reflections #if USE_REFLECTIONS - float4 reflections = SampleReflectionProbe(ViewPos, EnvProbe, EnvironmentProbe, gBuffer.WorldPos, gBuffer.Normal, gBuffer.Roughness); - reflections.rgb *= reflections.a; + float4 reflectionsProbe = SampleReflectionProbe(ViewPos, EnvProbe, EnvironmentProbe, gBuffer.WorldPos, gBuffer.Normal, gBuffer.Roughness); + float3 reflections = reflectionsProbe.rgb * reflectionsProbe.a; +#if USE_GI + float4 reflectionsGI = GetGlobalIlluminationSpecular(gBuffer); + reflections = lerp(reflections, reflectionsGI.rgb, reflectionsGI.a); +#endif #if MATERIAL_REFLECTIONS == MATERIAL_REFLECTIONS_SSR // Screen Space Reflections @@ -133,7 +138,7 @@ void PS_Forward( if (hit.z > 0) { float3 screenColor = sceneColorTexture.SampleLevel(SamplerPointClamp, hit.xy, 0).rgb; - reflections.rgb = lerp(reflections.rgb, screenColor, hit.z); + reflections = lerp(reflections, screenColor, hit.z); } // Fallback to software tracing if possible @@ -145,18 +150,17 @@ void PS_Forward( if (TraceSDFSoftwareReflections(gBuffer, reflectWS, surfaceAtlas)) { float3 screenColor = sceneColorTexture.SampleLevel(SamplerPointClamp, hit.xy, 0).rgb; - reflections.rgb = lerp(surfaceAtlas, float4(screenColor, 1), hit.z); + reflections = lerp(surfaceAtlas, float4(screenColor, 1), hit.z); } } #endif #endif - light.rgb += reflections.rgb * GetReflectionSpecularLighting(PreIntegratedGF, ViewPos, gBuffer); + light.rgb += reflections * GetReflectionSpecularLighting(PreIntegratedGF, ViewPos, gBuffer); #endif // Add lighting output.rgb += light.rgb; - #endif #if USE_FOG && MATERIAL_SHADING_MODEL != SHADING_MODEL_UNLIT diff --git a/Content/Editor/MaterialTemplates/Features/GlobalIllumination.hlsl b/Content/Editor/MaterialTemplates/Features/GlobalIllumination.hlsl index 0a8f75a50..a0d84ba01 100644 --- a/Content/Editor/MaterialTemplates/Features/GlobalIllumination.hlsl +++ b/Content/Editor/MaterialTemplates/Features/GlobalIllumination.hlsl @@ -8,16 +8,24 @@ @2// Global Illumination: Constants DDGIData DDGI; @3// Global Illumination: Resources -Texture2D ProbesState : register(t__SRV__); +Texture2D ProbesData : register(t__SRV__); Texture2D ProbesDistance : register(t__SRV__); Texture2D ProbesIrradiance : register(t__SRV__); +Texture2D ProbesRadiance : register(t__SRV__); @4// Global Illumination: Utilities float4 GetGlobalIlluminationLighting(GBufferSample gBuffer) { - float3 irradiance = SampleDDGIIrradiance(DDGI, ProbesState, ProbesDistance, ProbesIrradiance, gBuffer.WorldPos, gBuffer.Normal); + float3 irradiance = SampleDDGIIrradiance(DDGI, ProbesData, ProbesDistance, ProbesIrradiance, gBuffer.WorldPos, gBuffer.Normal); float3 diffuseColor = GetDiffuseColor(gBuffer); float3 diffuse = Diffuse_Lambert(diffuseColor); return float4(diffuse * irradiance, saturate(length(irradiance))); } +float4 GetGlobalIlluminationSpecular(GBufferSample gBuffer) +{ + float3 specular = SampleDDGISpecular(DDGI, ProbesData, ProbesDistance, ProbesRadiance, gBuffer.WorldPos, gBuffer.Normal, gBuffer.Roughness); + float useRadiance = DDGI.BlendOrigin[0].w; // 1 or 0 + return float4(specular, useRadiance); +} + @5// Global Illumination: Shaders diff --git a/Flax.flaxproj b/Flax.flaxproj index 65aad0f7f..13b0f0b9d 100644 --- a/Flax.flaxproj +++ b/Flax.flaxproj @@ -4,7 +4,7 @@ "Major": 1, "Minor": 13, "Revision": 0, - "Build": 7007 + "Build": 7008 }, "Company": "Flax", "Copyright": "Copyright (c) 2012-2026 Wojciech Figat. All rights reserved.", diff --git a/Source/Engine/Graphics/Materials/MaterialShader.h b/Source/Engine/Graphics/Materials/MaterialShader.h index fc3e6cd6c..c14c54851 100644 --- a/Source/Engine/Graphics/Materials/MaterialShader.h +++ b/Source/Engine/Graphics/Materials/MaterialShader.h @@ -10,7 +10,7 @@ /// /// Current materials shader version. /// -#define MATERIAL_GRAPH_VERSION 184 +#define MATERIAL_GRAPH_VERSION 185 class Material; class GPUShader; diff --git a/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp b/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp index 85e823360..2e3ca90b4 100644 --- a/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp +++ b/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp @@ -172,6 +172,7 @@ bool GlobalIlluminationFeature::Bind(MaterialShader::BindParameters& params, Spa params.GPUContext->BindSR(srv + 0, bindingDataDDGI.ProbesData); params.GPUContext->BindSR(srv + 1, bindingDataDDGI.ProbesDistance); params.GPUContext->BindSR(srv + 2, bindingDataDDGI.ProbesIrradiance); + params.GPUContext->BindSR(srv + 3, bindingDataDDGI.ProbesRadiance); } break; } @@ -185,6 +186,7 @@ bool GlobalIlluminationFeature::Bind(MaterialShader::BindParameters& params, Spa params.GPUContext->UnBindSR(srv + 0); params.GPUContext->UnBindSR(srv + 1); params.GPUContext->UnBindSR(srv + 2); + params.GPUContext->UnBindSR(srv + 3); } cb = cb.Slice(sizeof(Data)); diff --git a/Source/Engine/Graphics/Materials/MaterialShaderFeatures.h b/Source/Engine/Graphics/Materials/MaterialShaderFeatures.h index 6cfb28e88..a7abb465d 100644 --- a/Source/Engine/Graphics/Materials/MaterialShaderFeatures.h +++ b/Source/Engine/Graphics/Materials/MaterialShaderFeatures.h @@ -73,7 +73,7 @@ struct LightmapFeature : MaterialShaderFeature // Material shader feature that adds Global Illumination sampling feature (light probes). struct GlobalIlluminationFeature : MaterialShaderFeature { - enum { SRVs = 3 }; + enum { SRVs = 4 }; PACK_STRUCT(struct Data { DynamicDiffuseGlobalIlluminationPass::ConstantsData DDGI; diff --git a/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp b/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp index 082a20861..2ec6336ee 100644 --- a/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp +++ b/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp @@ -648,6 +648,7 @@ bool DynamicDiffuseGlobalIlluminationPass::RenderInner(RenderContext& renderCont ddgiData.Result.Constants.BlendOrigin[cascadeIndex] = Float4(blendOrigins[cascadeIndex], 0.0f); ddgiData.Result.Constants.ProbesScrollOffsets[cascadeIndex] = Int4(cascade.ProbeScrollOffsets, 0); } + ddgiData.Result.Constants.BlendOrigin[0].W = ddgiData.ProbesRadiance ? 1.0f : 0.0f; // Use radiance flag ddgiData.Result.Constants.RayMaxDistance = distance; ddgiData.Result.Constants.ViewPos = renderContext.View.Position; ddgiData.Result.Constants.RaysCount = probeRaysCount; diff --git a/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.h b/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.h index 130af0468..2f6ebdc6f 100644 --- a/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.h +++ b/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.h @@ -15,7 +15,7 @@ public: // Constant buffer data for DDGI access on a GPU. GPU_CB_STRUCT(ConstantsData { Float4 ProbesOriginAndSpacing[4]; - Float4 BlendOrigin[4]; // w is unused + Float4 BlendOrigin[4]; // [0] w is flag for specular usage, [1-3] w is unused Int4 ProbesScrollOffsets[4]; // w is unused uint32 ProbesCounts[3]; uint32 CascadesCount; diff --git a/Source/Shaders/GI/DDGI.hlsl b/Source/Shaders/GI/DDGI.hlsl index 454b5e9cb..7a5a96048 100644 --- a/Source/Shaders/GI/DDGI.hlsl +++ b/Source/Shaders/GI/DDGI.hlsl @@ -38,7 +38,7 @@ struct DDGIData { float4 ProbesOriginAndSpacing[4]; - float4 BlendOrigin[4]; // w is unused + float4 BlendOrigin[4]; // [0] w is flag for specular usage, [1-3] w is unused int4 ProbesScrollOffsets[4]; // w is unused uint3 ProbesCounts; uint CascadesCount;