diff --git a/Source/Editor/Surface/Archetypes/Textures.cs b/Source/Editor/Surface/Archetypes/Textures.cs
index a3974c740..b1a39bcb6 100644
--- a/Source/Editor/Surface/Archetypes/Textures.cs
+++ b/Source/Editor/Surface/Archetypes/Textures.cs
@@ -358,6 +358,19 @@ namespace FlaxEditor.Surface.Archetypes
NodeElementArchetype.Factory.Input(1, "Location", true, null, 2),
}
},
+ new NodeArchetype
+ {
+ TypeID = 14,
+ Title = "Sample Global SDF",
+ Description = "Samples the Global SDF to get the distance to the closest surface (in world-space). Requires models SDF to be generated and checking `Enable Global SDF` in Graphics Settings.",
+ Flags = NodeFlags.MaterialGraph,
+ Size = new Vector2(200, 20),
+ Elements = new[]
+ {
+ NodeElementArchetype.Factory.Output(0, "Distance", typeof(float), 0),
+ NodeElementArchetype.Factory.Input(0, "World Position", true, typeof(Vector3), 1),
+ }
+ },
};
}
}
diff --git a/Source/Engine/Graphics/Materials/DecalMaterialShader.cpp b/Source/Engine/Graphics/Materials/DecalMaterialShader.cpp
index f0ac5300b..a8fefdbca 100644
--- a/Source/Engine/Graphics/Materials/DecalMaterialShader.cpp
+++ b/Source/Engine/Graphics/Materials/DecalMaterialShader.cpp
@@ -48,7 +48,7 @@ void DecalMaterialShader::Bind(BindParameters& params)
bindMeta.Context = context;
bindMeta.Constants = cb;
bindMeta.Input = nullptr;
- bindMeta.Buffers = nullptr;
+ bindMeta.Buffers = params.RenderContext.Buffers;
bindMeta.CanSampleDepth = true;
bindMeta.CanSampleGBuffer = false;
MaterialParams::Bind(params.ParamsLink, bindMeta);
diff --git a/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp b/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp
index 29ef818e0..50780743b 100644
--- a/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp
+++ b/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp
@@ -74,7 +74,7 @@ void DeferredMaterialShader::Bind(BindParameters& params)
bindMeta.Context = context;
bindMeta.Constants = cb;
bindMeta.Input = nullptr;
- bindMeta.Buffers = nullptr;
+ bindMeta.Buffers = params.RenderContext.Buffers;
bindMeta.CanSampleDepth = false;
bindMeta.CanSampleGBuffer = false;
MaterialParams::Bind(params.ParamsLink, bindMeta);
diff --git a/Source/Engine/Graphics/Materials/DeformableMaterialShader.cpp b/Source/Engine/Graphics/Materials/DeformableMaterialShader.cpp
index 61d6fb42a..f491ee700 100644
--- a/Source/Engine/Graphics/Materials/DeformableMaterialShader.cpp
+++ b/Source/Engine/Graphics/Materials/DeformableMaterialShader.cpp
@@ -62,7 +62,7 @@ void DeformableMaterialShader::Bind(BindParameters& params)
bindMeta.Context = context;
bindMeta.Constants = cb;
bindMeta.Input = nullptr;
- bindMeta.Buffers = nullptr;
+ bindMeta.Buffers = params.RenderContext.Buffers;
bindMeta.CanSampleDepth = false;
bindMeta.CanSampleGBuffer = false;
MaterialParams::Bind(params.ParamsLink, bindMeta);
diff --git a/Source/Engine/Graphics/Materials/MaterialParams.cpp b/Source/Engine/Graphics/Materials/MaterialParams.cpp
index 7386343b5..e7dfe88e0 100644
--- a/Source/Engine/Graphics/Materials/MaterialParams.cpp
+++ b/Source/Engine/Graphics/Materials/MaterialParams.cpp
@@ -11,6 +11,8 @@
#include "Engine/Graphics/RenderBuffers.h"
#include "Engine/Graphics/GPUDevice.h"
#include "Engine/Graphics/GPULimits.h"
+#include "Engine/Graphics/RenderTask.h"
+#include "Engine/Renderer/GlobalSignDistanceFieldPass.h"
#include "Engine/Streaming/Streaming.h"
bool MaterialInfo8::operator==(const MaterialInfo8& other) const
@@ -157,6 +159,9 @@ const Char* ToString(MaterialParameterType value)
case MaterialParameterType::TextureGroupSampler:
result = TEXT("TextureGroupSampler");
break;
+ case MaterialParameterType::GlobalSDF:
+ result = TEXT("GlobalSDF");
+ break;
default:
result = TEXT("");
break;
@@ -198,7 +203,6 @@ Variant MaterialParameter::GetValue() const
case MaterialParameterType::GPUTexture:
return _asGPUTexture.Get();
default:
- CRASH;
return Variant::Zero;
}
}
@@ -303,6 +307,8 @@ void MaterialParameter::SetValue(const Variant& value)
invalidType = true;
}
break;
+ case MaterialParameterType::GlobalSDF:
+ break;
default:
invalidType = true;
}
@@ -475,6 +481,16 @@ void MaterialParameter::Bind(BindMeta& meta) const
case MaterialParameterType::TextureGroupSampler:
meta.Context->BindSampler(_registerIndex, Streaming::GetTextureGroupSampler(_asInteger));
break;
+ case MaterialParameterType::GlobalSDF:
+ {
+ GlobalSignDistanceFieldPass::BindingData bindingData;
+ if (GlobalSignDistanceFieldPass::Instance()->Get(meta.Buffers, bindingData))
+ Platform::MemoryClear(&bindingData, sizeof(bindingData));
+ for (int32 i = 0; i < 4; i++)
+ meta.Context->BindSR(_registerIndex + i, bindingData.Cascades[i] ? bindingData.Cascades[i]->ViewVolume() : nullptr);
+ *((GlobalSignDistanceFieldPass::GlobalSDFData*)(meta.Constants.Get() + _offset)) = bindingData.GlobalSDF;
+ break;
+ }
default:
break;
}
diff --git a/Source/Engine/Graphics/Materials/MaterialParams.h b/Source/Engine/Graphics/Materials/MaterialParams.h
index 664da2b19..a367114c2 100644
--- a/Source/Engine/Graphics/Materials/MaterialParams.h
+++ b/Source/Engine/Graphics/Materials/MaterialParams.h
@@ -128,6 +128,11 @@ enum class MaterialParameterType : byte
/// The texture sampler derived from texture group settings.
///
TextureGroupSampler = 19,
+
+ ///
+ /// The Global SDF (textures and constants).
+ ///
+ GlobalSDF = 20,
};
const Char* ToString(MaterialParameterType value);
diff --git a/Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp b/Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp
index 808278c04..b93298d7a 100644
--- a/Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp
+++ b/Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp
@@ -67,7 +67,7 @@ void TerrainMaterialShader::Bind(BindParameters& params)
bindMeta.Context = context;
bindMeta.Constants = cb;
bindMeta.Input = nullptr;
- bindMeta.Buffers = nullptr;
+ bindMeta.Buffers = params.RenderContext.Buffers;
bindMeta.CanSampleDepth = false;
bindMeta.CanSampleGBuffer = false;
MaterialParams::Bind(params.ParamsLink, bindMeta);
diff --git a/Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp b/Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp
index 2fe47bc48..e5b39d685 100644
--- a/Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp
+++ b/Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp
@@ -215,7 +215,7 @@ void GlobalSignDistanceFieldPass::Dispose()
bool GlobalSignDistanceFieldPass::Get(const RenderBuffers* buffers, BindingData& result)
{
- auto* sdfData = buffers->FindCustomBuffer(TEXT("GlobalSignDistanceField"));
+ auto* sdfData = buffers ? buffers->FindCustomBuffer(TEXT("GlobalSignDistanceField")) : nullptr;
if (sdfData && sdfData->LastFrameUsed == Engine::FrameCount)
{
result = sdfData->Result;
diff --git a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Textures.cpp b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Textures.cpp
index bb940b610..a5e03f124 100644
--- a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Textures.cpp
+++ b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Textures.cpp
@@ -420,6 +420,16 @@ void MaterialGenerator::ProcessGroupTextures(Box* box, Node* node, Value& value)
value = writeLocal(VariantType::Vector2, String::Format(TEXT("({3} + float2({0}, {1})) * {2}"), frameX.Value, frameY.Value, framesXYInv.Value, uv.Value), node);
break;
}
+ // Sample Global SDF
+ case 14:
+ {
+ auto param = findOrAddGlobalSDF();
+ Value worldPosition = tryGetValue(node->GetBox(1), Value(VariantType::Vector3, TEXT("input.WorldPosition.xyz"))).Cast(VariantType::Vector3);
+ value = writeLocal(VariantType::Float, String::Format(TEXT("SampleGlobalSDF({0}, {0}_Tex, {1})"), param.ShaderName, worldPosition.Value), node);
+ _includes.Add(TEXT("./Flax/GlobalSignDistanceField.hlsl"));
+ //float SampleGlobalSDF(const GlobalSDFData data, Texture3D tex[4], float3 worldPosition, uint minCascade = 0)
+ break;
+ }
default:
break;
}
diff --git a/Source/Engine/Visject/ShaderGraph.cpp b/Source/Engine/Visject/ShaderGraph.cpp
index 7cf2f01b5..d06a00977 100644
--- a/Source/Engine/Visject/ShaderGraph.cpp
+++ b/Source/Engine/Visject/ShaderGraph.cpp
@@ -1298,6 +1298,27 @@ SerializedMaterialParam& ShaderGenerator::findOrAddTextureGroupSampler(int32 ind
return param;
}
+SerializedMaterialParam& ShaderGenerator::findOrAddGlobalSDF()
+{
+ // Find
+ for (int32 i = 0; i < _parameters.Count(); i++)
+ {
+ SerializedMaterialParam& param = _parameters[i];
+ if (!param.IsPublic && param.Type == MaterialParameterType::GlobalSDF)
+ return param;
+ }
+
+ // Create
+ SerializedMaterialParam& param = _parameters.AddOne();
+ param.Type = MaterialParameterType::GlobalSDF;
+ param.IsPublic = false;
+ param.Override = true;
+ param.Name = TEXT("Global SDF");
+ param.ShaderName = getParamName(_parameters.Count());
+ param.ID = Guid(_parameters.Count(), 0, 0, 3); // Assign temporary id
+ return param;
+}
+
String ShaderGenerator::getLocalName(int32 index)
{
return TEXT("local") + StringUtils::ToString(index);
diff --git a/Source/Engine/Visject/ShaderGraph.h b/Source/Engine/Visject/ShaderGraph.h
index 1ae7cab7f..38205f743 100644
--- a/Source/Engine/Visject/ShaderGraph.h
+++ b/Source/Engine/Visject/ShaderGraph.h
@@ -286,6 +286,7 @@ protected:
SerializedMaterialParam findOrAddCubeTexture(const Guid& id);
SerializedMaterialParam findOrAddSceneTexture(MaterialSceneTextures type);
SerializedMaterialParam& findOrAddTextureGroupSampler(int32 index);
+ SerializedMaterialParam& findOrAddGlobalSDF();
static String getLocalName(int32 index);
static String getParamName(int32 index);
diff --git a/Source/Engine/Visject/ShaderGraphUtilities.cpp b/Source/Engine/Visject/ShaderGraphUtilities.cpp
index 0944685e9..bfe86fcef 100644
--- a/Source/Engine/Visject/ShaderGraphUtilities.cpp
+++ b/Source/Engine/Visject/ShaderGraphUtilities.cpp
@@ -9,19 +9,19 @@
#include "Engine/Content/Content.h"
#include "Engine/Engine/GameplayGlobals.h"
#include "Engine/Graphics/Config.h"
+#include "Engine/Renderer/GlobalSignDistanceFieldPass.h"
void ShaderGraphUtilities::GenerateShaderConstantBuffer(TextWriterUnicode& writer, Array& parameters)
{
int32 constantsOffset = 0;
int32 paddingIndex = 0;
-
for (int32 i = 0; i < parameters.Count(); i++)
{
auto& param = parameters[i];
-
const Char* format = nullptr;
int32 size;
int32 alignment;
+ bool zeroRegister = true;
switch (param.Type)
{
case MaterialParameterType::Bool:
@@ -107,11 +107,15 @@ void ShaderGraphUtilities::GenerateShaderConstantBuffer(TextWriterUnicode& write
alignment = 16;
format = TEXT("float4 {0};");
break;
- default: ;
}
break;
}
- default: ;
+ case MaterialParameterType::GlobalSDF:
+ zeroRegister = false;
+ size = sizeof(GlobalSignDistanceFieldPass::GlobalSDFData);
+ alignment = 16;
+ format = TEXT("GlobalSDFData {0};");
+ break;
}
if (format)
{
@@ -126,7 +130,8 @@ void ShaderGraphUtilities::GenerateShaderConstantBuffer(TextWriterUnicode& write
}
}
- param.RegisterIndex = 0;
+ if (zeroRegister)
+ param.RegisterIndex = 0;
param.Offset = constantsOffset;
writer.WriteLine(format, param.ShaderName);
constantsOffset += size;
@@ -139,7 +144,9 @@ const Char* ShaderGraphUtilities::GenerateShaderResources(TextWriterUnicode& wri
for (int32 i = 0; i < parameters.Count(); i++)
{
auto& param = parameters[i];
- const Char* format;
+ const Char* format = nullptr;
+ bool zeroOffset = true;
+ int32 registers = 1;
switch (param.Type)
{
case MaterialParameterType::NormalMap:
@@ -158,16 +165,19 @@ const Char* ShaderGraphUtilities::GenerateShaderResources(TextWriterUnicode& wri
case MaterialParameterType::GPUTextureVolume:
format = TEXT("Texture3D {0} : register(t{1});");
break;
- default:
- format = nullptr;
+ case MaterialParameterType::GlobalSDF:
+ format = TEXT("Texture3D {0}_Tex[4] : register(t{1});");
+ registers = 4;
+ zeroOffset = false;
break;
}
if (format)
{
- param.Offset = 0;
+ if (zeroOffset)
+ param.Offset = 0;
param.RegisterIndex = (byte)startRegister;
writer.WriteLine(format, param.ShaderName, startRegister);
- startRegister++;
+ startRegister += registers;
if (param.RegisterIndex >= GPU_MAX_SR_BINDED)
{
return TEXT("Too many textures used. The maximum supported amount is " MACRO_TO_STR(GPU_MAX_SR_BINDED) " (including lightmaps and utility textures for lighting).");
diff --git a/Source/Shaders/GlobalSignDistanceField.hlsl b/Source/Shaders/GlobalSignDistanceField.hlsl
index 83a98ae00..2e3f5ddd0 100644
--- a/Source/Shaders/GlobalSignDistanceField.hlsl
+++ b/Source/Shaders/GlobalSignDistanceField.hlsl
@@ -57,17 +57,15 @@ struct GlobalSDFHit
float SampleGlobalSDF(const GlobalSDFData data, Texture3D tex[4], float3 worldPosition, uint minCascade = 0)
{
float distance = data.CascadePosDistance[3].w * 2.0f;
+ UNROLL
for (uint cascade = minCascade; cascade < 4; cascade++)
{
float4 cascadePosDistance = data.CascadePosDistance[cascade];
float cascadeMaxDistance = cascadePosDistance.w * 2;
float3 posInCascade = worldPosition - cascadePosDistance.xyz;
float3 cascadeUV = posInCascade / cascadeMaxDistance + 0.5f;
- if (any(cascadeUV < 0) || any(cascadeUV > 1))
- continue;
- // TODO: sample mip first
float cascadeDistance = tex[cascade].SampleLevel(SamplerLinearClamp, cascadeUV, 0);
- if (cascadeDistance < 1.0f)
+ if (cascadeDistance < 1.0f && !any(cascadeUV < 0) && !any(cascadeUV > 1))
{
distance = cascadeDistance * cascadeMaxDistance;
break;