Fix GlobalSDF sampling in materials to properly read far cascades

This commit is contained in:
Wojtek Figat
2024-06-06 12:10:44 +02:00
parent 96303e57ec
commit a232dac196
7 changed files with 14 additions and 23 deletions

View File

@@ -463,6 +463,7 @@ void MaterialParameter::Bind(BindMeta& meta) const
if (GlobalSignDistanceFieldPass::Instance()->Get(meta.Buffers, bindingData)) if (GlobalSignDistanceFieldPass::Instance()->Get(meta.Buffers, bindingData))
Platform::MemoryClear(&bindingData, sizeof(bindingData)); Platform::MemoryClear(&bindingData, sizeof(bindingData));
meta.Context->BindSR(_registerIndex, bindingData.Texture ? bindingData.Texture->ViewVolume() : nullptr); meta.Context->BindSR(_registerIndex, bindingData.Texture ? bindingData.Texture->ViewVolume() : nullptr);
meta.Context->BindSR(_registerIndex + 1, bindingData.TextureMip ? bindingData.TextureMip->ViewVolume() : nullptr);
*((GlobalSignDistanceFieldPass::ConstantsData*)(meta.Constants.Get() + _offset)) = bindingData.Constants; *((GlobalSignDistanceFieldPass::ConstantsData*)(meta.Constants.Get() + _offset)) = bindingData.Constants;
break; break;
} }

View File

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

View File

@@ -917,6 +917,7 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
} }
result.Constants.Resolution = (float)resolution; result.Constants.Resolution = (float)resolution;
result.Constants.CascadesCount = cascadesCount; result.Constants.CascadesCount = cascadesCount;
result.Constants.Padding = Float2::Zero;
sdfData.Result = result; sdfData.Result = result;
return false; return false;
} }

View File

@@ -665,7 +665,7 @@ void MaterialGenerator::ProcessGroupTextures(Box* box, Node* node, Value& value)
{ {
auto param = findOrAddGlobalSDF(); auto param = findOrAddGlobalSDF();
Value worldPosition = tryGetValue(node->GetBox(1), Value(VariantType::Float3, TEXT("input.WorldPosition.xyz"))).Cast(VariantType::Float3); Value worldPosition = tryGetValue(node->GetBox(1), Value(VariantType::Float3, TEXT("input.WorldPosition.xyz"))).Cast(VariantType::Float3);
value = writeLocal(VariantType::Float, String::Format(TEXT("SampleGlobalSDF({0}, {0}_Tex, {1})"), param.ShaderName, worldPosition.Value), node); value = writeLocal(VariantType::Float, String::Format(TEXT("SampleGlobalSDF({0}, {0}_Tex, {0}_Mip, {1})"), param.ShaderName, worldPosition.Value), node);
_includes.Add(TEXT("./Flax/GlobalSignDistanceField.hlsl")); _includes.Add(TEXT("./Flax/GlobalSignDistanceField.hlsl"));
break; break;
} }
@@ -677,7 +677,7 @@ void MaterialGenerator::ProcessGroupTextures(Box* box, Node* node, Value& value)
auto param = findOrAddGlobalSDF(); auto param = findOrAddGlobalSDF();
Value worldPosition = tryGetValue(node->GetBox(1), Value(VariantType::Float3, TEXT("input.WorldPosition.xyz"))).Cast(VariantType::Float3); Value worldPosition = tryGetValue(node->GetBox(1), Value(VariantType::Float3, TEXT("input.WorldPosition.xyz"))).Cast(VariantType::Float3);
auto distance = writeLocal(VariantType::Float, node); auto distance = writeLocal(VariantType::Float, node);
auto gradient = writeLocal(VariantType::Float3, String::Format(TEXT("SampleGlobalSDFGradient({0}, {0}_Tex, {1}, {2})"), param.ShaderName, worldPosition.Value, distance.Value), node); auto gradient = writeLocal(VariantType::Float3, String::Format(TEXT("SampleGlobalSDFGradient({0}, {0}_Tex, {0}_Mip, {1}, {2})"), param.ShaderName, worldPosition.Value, distance.Value), node);
_includes.Add(TEXT("./Flax/GlobalSignDistanceField.hlsl")); _includes.Add(TEXT("./Flax/GlobalSignDistanceField.hlsl"));
gradientBox->Cache = gradient; gradientBox->Cache = gradient;
distanceBox->Cache = distance; distanceBox->Cache = distance;

View File

@@ -1206,11 +1206,8 @@ SerializedMaterialParam* ShaderGenerator::findParam(const String& shaderName)
{ {
SerializedMaterialParam& param = _parameters[i]; SerializedMaterialParam& param = _parameters[i];
if (param.ShaderName == shaderName) if (param.ShaderName == shaderName)
{
return &param; return &param;
} }
}
return nullptr; return nullptr;
} }
@@ -1235,10 +1232,8 @@ SerializedMaterialParam ShaderGenerator::findOrAddTexture(const Guid& id)
{ {
SerializedMaterialParam& param = _parameters[i]; SerializedMaterialParam& param = _parameters[i];
if (!param.IsPublic && param.Type == MaterialParameterType::Texture && param.AsGuid == id) if (!param.IsPublic && param.Type == MaterialParameterType::Texture && param.AsGuid == id)
{
return param; return param;
} }
}
// Create // Create
SerializedMaterialParam& param = _parameters.AddOne(); SerializedMaterialParam& param = _parameters.AddOne();
@@ -1259,10 +1254,8 @@ SerializedMaterialParam ShaderGenerator::findOrAddNormalMap(const Guid& id)
{ {
SerializedMaterialParam& param = _parameters[i]; SerializedMaterialParam& param = _parameters[i];
if (!param.IsPublic && param.Type == MaterialParameterType::NormalMap && param.AsGuid == id) if (!param.IsPublic && param.Type == MaterialParameterType::NormalMap && param.AsGuid == id)
{
return param; return param;
} }
}
// Create // Create
SerializedMaterialParam& param = _parameters.AddOne(); SerializedMaterialParam& param = _parameters.AddOne();
@@ -1283,10 +1276,8 @@ SerializedMaterialParam ShaderGenerator::findOrAddCubeTexture(const Guid& id)
{ {
SerializedMaterialParam& param = _parameters[i]; SerializedMaterialParam& param = _parameters[i];
if (!param.IsPublic && param.Type == MaterialParameterType::CubeTexture && param.AsGuid == id) if (!param.IsPublic && param.Type == MaterialParameterType::CubeTexture && param.AsGuid == id)
{
return param; return param;
} }
}
// Create // Create
SerializedMaterialParam& param = _parameters.AddOne(); SerializedMaterialParam& param = _parameters.AddOne();
@@ -1309,10 +1300,8 @@ SerializedMaterialParam ShaderGenerator::findOrAddSceneTexture(MaterialSceneText
{ {
SerializedMaterialParam& param = _parameters[i]; SerializedMaterialParam& param = _parameters[i];
if (!param.IsPublic && param.Type == MaterialParameterType::SceneTexture && param.AsInteger == asInt) if (!param.IsPublic && param.Type == MaterialParameterType::SceneTexture && param.AsInteger == asInt)
{
return param; return param;
} }
}
// Create // Create
SerializedMaterialParam& param = _parameters.AddOne(); SerializedMaterialParam& param = _parameters.AddOne();
@@ -1333,10 +1322,8 @@ SerializedMaterialParam& ShaderGenerator::findOrAddTextureGroupSampler(int32 ind
{ {
SerializedMaterialParam& param = _parameters[i]; SerializedMaterialParam& param = _parameters[i];
if (!param.IsPublic && param.Type == MaterialParameterType::TextureGroupSampler && param.AsInteger == index) if (!param.IsPublic && param.Type == MaterialParameterType::TextureGroupSampler && param.AsInteger == index)
{
return param; return param;
} }
}
// Create // Create
SerializedMaterialParam& param = _parameters.AddOne(); SerializedMaterialParam& param = _parameters.AddOne();

View File

@@ -170,8 +170,9 @@ const Char* ShaderGraphUtilities::GenerateShaderResources(TextWriterUnicode& wri
format = TEXT("Texture3D {0} : register(t{1});"); format = TEXT("Texture3D {0} : register(t{1});");
break; break;
case MaterialParameterType::GlobalSDF: case MaterialParameterType::GlobalSDF:
format = TEXT("Texture3D<float> {0}_Tex : register(t{1});"); format = TEXT("Texture3D<float> {0}_Tex : register(t{1});\nTexture3D<float> {0}_Mip : register(t{2});");
zeroOffset = false; zeroOffset = false;
registers = 2;
break; break;
} }
if (format) if (format)
@@ -179,7 +180,7 @@ const Char* ShaderGraphUtilities::GenerateShaderResources(TextWriterUnicode& wri
if (zeroOffset) if (zeroOffset)
param.Offset = 0; param.Offset = 0;
param.RegisterIndex = (byte)startRegister; param.RegisterIndex = (byte)startRegister;
writer.WriteLine(format, param.ShaderName, startRegister); writer.WriteLine(format, param.ShaderName, startRegister, startRegister + 1);
startRegister += registers; startRegister += registers;
if (param.RegisterIndex >= GPU_MAX_SR_BINDED) if (param.RegisterIndex >= GPU_MAX_SR_BINDED)
{ {

View File

@@ -7,6 +7,7 @@
#define GLOBAL_SDF_RASTERIZE_CHUNK_MARGIN 4 #define GLOBAL_SDF_RASTERIZE_CHUNK_MARGIN 4
#define GLOBAL_SDF_MIP_FLOODS 5 #define GLOBAL_SDF_MIP_FLOODS 5
#define GLOBAL_SDF_WORLD_SIZE 60000.0f #define GLOBAL_SDF_WORLD_SIZE 60000.0f
#define GLOBAL_SDF_MIN_VALID 0.9f
// Global SDF data for a constant buffer // Global SDF data for a constant buffer
struct GlobalSDFData struct GlobalSDFData
@@ -90,7 +91,7 @@ float SampleGlobalSDFCascade(const GlobalSDFData data, Texture3D<float> tex, flo
float3 cascadeUV, textureUV; float3 cascadeUV, textureUV;
GetGlobalSDFCascadeUV(data, cascade, worldPosition, cascadeMaxDistance, cascadeUV, textureUV); GetGlobalSDFCascadeUV(data, cascade, worldPosition, cascadeMaxDistance, cascadeUV, textureUV);
float cascadeDistance = tex.SampleLevel(SamplerLinearClamp, textureUV, 0); float cascadeDistance = tex.SampleLevel(SamplerLinearClamp, textureUV, 0);
if (cascadeDistance < 1.0f && !any(cascadeUV < 0) && !any(cascadeUV > 1)) if (cascadeDistance < GLOBAL_SDF_MIN_VALID && all(cascadeUV > 0) && all(cascadeUV < 1))
distance = cascadeDistance * cascadeMaxDistance; distance = cascadeDistance * cascadeMaxDistance;
return distance; return distance;
} }
@@ -107,7 +108,7 @@ float SampleGlobalSDF(const GlobalSDFData data, Texture3D<float> tex, float3 wor
float3 cascadeUV, textureUV; float3 cascadeUV, textureUV;
GetGlobalSDFCascadeUV(data, cascade, worldPosition, cascadeMaxDistance, cascadeUV, textureUV); GetGlobalSDFCascadeUV(data, cascade, worldPosition, cascadeMaxDistance, cascadeUV, textureUV);
float cascadeDistance = tex.SampleLevel(SamplerLinearClamp, textureUV, 0); float cascadeDistance = tex.SampleLevel(SamplerLinearClamp, textureUV, 0);
if (cascadeDistance < 0.9f && !any(cascadeUV < 0) && !any(cascadeUV > 1)) if (cascadeDistance < GLOBAL_SDF_MIN_VALID && all(cascadeUV > 0) && all(cascadeUV < 1))
{ {
distance = cascadeDistance * cascadeMaxDistance; distance = cascadeDistance * cascadeMaxDistance;
break; break;
@@ -130,7 +131,7 @@ float SampleGlobalSDF(const GlobalSDFData data, Texture3D<float> tex, Texture3D<
float3 cascadeUV, textureUV; float3 cascadeUV, textureUV;
GetGlobalSDFCascadeUV(data, cascade, worldPosition, cascadeMaxDistance, cascadeUV, textureUV); GetGlobalSDFCascadeUV(data, cascade, worldPosition, cascadeMaxDistance, cascadeUV, textureUV);
float cascadeDistance = mip.SampleLevel(SamplerLinearClamp, textureUV, 0); float cascadeDistance = mip.SampleLevel(SamplerLinearClamp, textureUV, 0);
if (cascadeDistance < chunkSizeDistance && !any(cascadeUV < 0) && !any(cascadeUV > 1)) if (cascadeDistance < chunkSizeDistance && all(cascadeUV > 0) && all(cascadeUV < 1))
{ {
float cascadeDistanceTex = tex.SampleLevel(SamplerLinearClamp, textureUV, 0); float cascadeDistanceTex = tex.SampleLevel(SamplerLinearClamp, textureUV, 0);
if (cascadeDistanceTex < chunkMarginDistance * 2) if (cascadeDistanceTex < chunkMarginDistance * 2)
@@ -155,7 +156,7 @@ float3 SampleGlobalSDFGradient(const GlobalSDFData data, Texture3D<float> tex, f
float3 cascadeUV, textureUV; float3 cascadeUV, textureUV;
GetGlobalSDFCascadeUV(data, cascade, worldPosition, cascadeMaxDistance, cascadeUV, textureUV); GetGlobalSDFCascadeUV(data, cascade, worldPosition, cascadeMaxDistance, cascadeUV, textureUV);
float cascadeDistance = tex.SampleLevel(SamplerLinearClamp, textureUV, 0); float cascadeDistance = tex.SampleLevel(SamplerLinearClamp, textureUV, 0);
if (cascadeDistance < 0.9f && !any(cascadeUV < 0) && !any(cascadeUV > 1)) if (cascadeDistance < GLOBAL_SDF_MIN_VALID && all(cascadeUV > 0) && all(cascadeUV < 1))
{ {
float texelOffset = 1.0f / data.Resolution; float texelOffset = 1.0f / data.Resolution;
float xp = tex.SampleLevel(SamplerLinearClamp, float3(textureUV.x + texelOffset, textureUV.y, textureUV.z), 0).x; float xp = tex.SampleLevel(SamplerLinearClamp, float3(textureUV.x + texelOffset, textureUV.y, textureUV.z), 0).x;
@@ -187,7 +188,7 @@ float3 SampleGlobalSDFGradient(const GlobalSDFData data, Texture3D<float> tex, T
float3 cascadeUV, textureUV; float3 cascadeUV, textureUV;
GetGlobalSDFCascadeUV(data, cascade, worldPosition, cascadeMaxDistance, cascadeUV, textureUV); GetGlobalSDFCascadeUV(data, cascade, worldPosition, cascadeMaxDistance, cascadeUV, textureUV);
float cascadeDistance = mip.SampleLevel(SamplerLinearClamp, textureUV, 0); float cascadeDistance = mip.SampleLevel(SamplerLinearClamp, textureUV, 0);
if (cascadeDistance < chunkSizeDistance && !any(cascadeUV < 0) && !any(cascadeUV > 1)) if (cascadeDistance < chunkSizeDistance && all(cascadeUV > 0) && all(cascadeUV < 1))
{ {
float cascadeDistanceTex = tex.SampleLevel(SamplerLinearClamp, textureUV, 0); float cascadeDistanceTex = tex.SampleLevel(SamplerLinearClamp, textureUV, 0);
if (cascadeDistanceTex < chunkMarginDistance * 2) if (cascadeDistanceTex < chunkMarginDistance * 2)