From f326fa611f8d4f188544332e0cde60bbc691a9cd Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 24 May 2024 12:41:39 +0200 Subject: [PATCH] Minor sdf imporvements --- Source/Engine/Tools/ModelTool/ModelTool.cpp | 29 ++++++++++----------- Source/Shaders/GI/DDGI.hlsl | 2 +- Source/Shaders/GlobalSignDistanceField.hlsl | 5 ++-- 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/Source/Engine/Tools/ModelTool/ModelTool.cpp b/Source/Engine/Tools/ModelTool/ModelTool.cpp index bfbd9421b..0e217b82b 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.cpp @@ -18,6 +18,7 @@ #include "Engine/Content/Assets/Model.h" #include "Engine/Content/Content.h" #include "Engine/Serialization/MemoryWriteStream.h" +#include "Engine/Engine/Units.h" #if USE_EDITOR #include "Engine/Core/Utilities.h" #include "Engine/Core/Types/StringView.h" @@ -85,7 +86,7 @@ bool ModelTool::GenerateModelSDF(Model* inputModel, ModelData* modelData, float return true; Float3 size = bounds.GetSize(); ModelBase::SDFData sdf; - sdf.WorldUnitsPerVoxel = 10 / Math::Max(resolutionScale, 0.0001f); + sdf.WorldUnitsPerVoxel = METERS_TO_UNITS(0.1f) / Math::Max(resolutionScale, 0.0001f); // 1 voxel per 10 centimeters Int3 resolution(Float3::Ceil(Float3::Clamp(size / sdf.WorldUnitsPerVoxel, 4, 256))); Float3 uvwToLocalMul = size; Float3 uvwToLocalAdd = bounds.Minimum; @@ -96,7 +97,6 @@ bool ModelTool::GenerateModelSDF(Model* inputModel, ModelData* modelData, float sdf.LocalBoundsMax = bounds.Maximum; sdf.ResolutionScale = resolutionScale; sdf.LOD = lodIndex; - // TODO: maybe apply 1 voxel margin around the geometry? const int32 maxMips = 3; const int32 mipCount = Math::Min(MipLevelsCount(resolution.X, resolution.Y, resolution.Z, true), maxMips); PixelFormat format = PixelFormat::R16_UNorm; @@ -169,21 +169,20 @@ bool ModelTool::GenerateModelSDF(Model* inputModel, ModelData* modelData, float // https://www.cse.chalmers.se/~uffe/HighResolutionSparseVoxelDAGs.pdf // Brute-force for each voxel to calculate distance to the closest triangle with point query and distance sign by raycasting around the voxel - const int32 sampleCount = 12; - Array sampleDirections; - sampleDirections.Resize(sampleCount); + constexpr int32 sampleCount = 12; + Float3 sampleDirections[sampleCount]; { RandomStream rand; - sampleDirections.Get()[0] = Float3::Up; - sampleDirections.Get()[1] = Float3::Down; - sampleDirections.Get()[2] = Float3::Left; - sampleDirections.Get()[3] = Float3::Right; - sampleDirections.Get()[4] = Float3::Forward; - sampleDirections.Get()[5] = Float3::Backward; + sampleDirections[0] = Float3::Up; + sampleDirections[1] = Float3::Down; + sampleDirections[2] = Float3::Left; + sampleDirections[3] = Float3::Right; + sampleDirections[4] = Float3::Forward; + sampleDirections[5] = Float3::Backward; for (int32 i = 6; i < sampleCount; i++) - sampleDirections.Get()[i] = rand.GetUnitVector(); + sampleDirections[i] = rand.GetUnitVector(); } - Function sdfJob = [&sdf, &resolution, &backfacesThreshold, &sampleDirections, &scene, &voxels, &xyzToLocalMul, &xyzToLocalAdd, &encodeMAD, &formatStride, &formatWrite](int32 z) + Function sdfJob = [&sdf, &resolution, &backfacesThreshold, sampleDirections, &sampleCount, &scene, &voxels, &xyzToLocalMul, &xyzToLocalAdd, &encodeMAD, &formatStride, &formatWrite](int32 z) { PROFILE_CPU_NAMED("Model SDF Job"); Real hitDistance; @@ -203,7 +202,7 @@ bool ModelTool::GenerateModelSDF(Model* inputModel, ModelData* modelData, float // Raycast samples around voxel to count triangle backfaces hit int32 hitBackCount = 0, hitCount = 0; - for (int32 sample = 0; sample < sampleDirections.Count(); sample++) + for (int32 sample = 0; sample < sampleCount; sample++) { Ray sampleRay(voxelPos, sampleDirections[sample]); if (scene.RayCast(sampleRay, hitDistance, hitNormal, hitTriangle)) @@ -218,7 +217,7 @@ bool ModelTool::GenerateModelSDF(Model* inputModel, ModelData* modelData, float float distance = (float)minDistance; // TODO: surface thickness threshold? shift reduce distance for all voxels by something like 0.01 to enlarge thin geometry // if ((float)hitBackCount > (float)hitCount * 0.3f && hitCount != 0) - if ((float)hitBackCount > (float)sampleDirections.Count() * backfacesThreshold && hitCount != 0) + if ((float)hitBackCount > (float)sampleCount * backfacesThreshold && hitCount != 0) { // Voxel is inside the geometry so turn it into negative distance to the surface distance *= -1; diff --git a/Source/Shaders/GI/DDGI.hlsl b/Source/Shaders/GI/DDGI.hlsl index 6d7c71936..e304b4ffc 100644 --- a/Source/Shaders/GI/DDGI.hlsl +++ b/Source/Shaders/GI/DDGI.hlsl @@ -213,11 +213,11 @@ float3 SampleDDGIIrradiance(DDGIData data, Texture2D probesData, T float2 uv = GetDDGIProbeUV(data, cascadeIndex, probeIndex, octahedralCoords, DDGI_PROBE_RESOLUTION_DISTANCE); float2 probeDistance = probesDistance.SampleLevel(SamplerLinearClamp, uv, 0).rg * 2.0f; float probeDistanceMean = probeDistance.x; - float probeDistanceMean2 = probeDistance.y; // Visibility weight (Chebyshev) if (biasedPosToProbeDist > probeDistanceMean) { + float probeDistanceMean2 = probeDistance.y; float probeDistanceVariance = abs(Square(probeDistanceMean) - probeDistanceMean2); float chebyshevWeight = probeDistanceVariance / (probeDistanceVariance + Square(biasedPosToProbeDist - probeDistanceMean)); weight *= max(chebyshevWeight * chebyshevWeight * chebyshevWeight, 0.05f); diff --git a/Source/Shaders/GlobalSignDistanceField.hlsl b/Source/Shaders/GlobalSignDistanceField.hlsl index 1681460eb..93bdee22b 100644 --- a/Source/Shaders/GlobalSignDistanceField.hlsl +++ b/Source/Shaders/GlobalSignDistanceField.hlsl @@ -223,7 +223,6 @@ GlobalSDFHit RayTraceGlobalSDF(const GlobalSDFData data, Texture3D tex, T float4 cascadePosDistance = data.CascadePosDistance[cascade]; float voxelSize = data.CascadeVoxelSize[cascade]; float voxelExtent = voxelSize * 0.5f; - float cascadeMinStep = voxelSize; float3 worldPosition = trace.WorldPosition + trace.WorldDirection * (voxelSize * cascadeTraceStartBias); // Hit the cascade bounds to find the intersection points @@ -270,7 +269,7 @@ GlobalSDFHit RayTraceGlobalSDF(const GlobalSDFData data, Texture3D tex, T stepDistance *= cascadeMaxDistance; // Detect surface hit - float minSurfaceThickness = voxelExtent * saturate(stepTime / (voxelExtent * 2.0f)); + float minSurfaceThickness = voxelExtent * saturate(stepTime / voxelSize); if (stepDistance < minSurfaceThickness) { // Surface hit @@ -293,7 +292,7 @@ GlobalSDFHit RayTraceGlobalSDF(const GlobalSDFData data, Texture3D tex, T } // Move forward - stepTime += max(stepDistance * trace.StepScale, cascadeMinStep); + stepTime += max(stepDistance * trace.StepScale, voxelSize); } hit.StepsCount += step; }