Minor sdf imporvements
This commit is contained in:
@@ -18,6 +18,7 @@
|
|||||||
#include "Engine/Content/Assets/Model.h"
|
#include "Engine/Content/Assets/Model.h"
|
||||||
#include "Engine/Content/Content.h"
|
#include "Engine/Content/Content.h"
|
||||||
#include "Engine/Serialization/MemoryWriteStream.h"
|
#include "Engine/Serialization/MemoryWriteStream.h"
|
||||||
|
#include "Engine/Engine/Units.h"
|
||||||
#if USE_EDITOR
|
#if USE_EDITOR
|
||||||
#include "Engine/Core/Utilities.h"
|
#include "Engine/Core/Utilities.h"
|
||||||
#include "Engine/Core/Types/StringView.h"
|
#include "Engine/Core/Types/StringView.h"
|
||||||
@@ -85,7 +86,7 @@ bool ModelTool::GenerateModelSDF(Model* inputModel, ModelData* modelData, float
|
|||||||
return true;
|
return true;
|
||||||
Float3 size = bounds.GetSize();
|
Float3 size = bounds.GetSize();
|
||||||
ModelBase::SDFData sdf;
|
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)));
|
Int3 resolution(Float3::Ceil(Float3::Clamp(size / sdf.WorldUnitsPerVoxel, 4, 256)));
|
||||||
Float3 uvwToLocalMul = size;
|
Float3 uvwToLocalMul = size;
|
||||||
Float3 uvwToLocalAdd = bounds.Minimum;
|
Float3 uvwToLocalAdd = bounds.Minimum;
|
||||||
@@ -96,7 +97,6 @@ bool ModelTool::GenerateModelSDF(Model* inputModel, ModelData* modelData, float
|
|||||||
sdf.LocalBoundsMax = bounds.Maximum;
|
sdf.LocalBoundsMax = bounds.Maximum;
|
||||||
sdf.ResolutionScale = resolutionScale;
|
sdf.ResolutionScale = resolutionScale;
|
||||||
sdf.LOD = lodIndex;
|
sdf.LOD = lodIndex;
|
||||||
// TODO: maybe apply 1 voxel margin around the geometry?
|
|
||||||
const int32 maxMips = 3;
|
const int32 maxMips = 3;
|
||||||
const int32 mipCount = Math::Min(MipLevelsCount(resolution.X, resolution.Y, resolution.Z, true), maxMips);
|
const int32 mipCount = Math::Min(MipLevelsCount(resolution.X, resolution.Y, resolution.Z, true), maxMips);
|
||||||
PixelFormat format = PixelFormat::R16_UNorm;
|
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
|
// 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
|
// 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;
|
constexpr int32 sampleCount = 12;
|
||||||
Array<Float3> sampleDirections;
|
Float3 sampleDirections[sampleCount];
|
||||||
sampleDirections.Resize(sampleCount);
|
|
||||||
{
|
{
|
||||||
RandomStream rand;
|
RandomStream rand;
|
||||||
sampleDirections.Get()[0] = Float3::Up;
|
sampleDirections[0] = Float3::Up;
|
||||||
sampleDirections.Get()[1] = Float3::Down;
|
sampleDirections[1] = Float3::Down;
|
||||||
sampleDirections.Get()[2] = Float3::Left;
|
sampleDirections[2] = Float3::Left;
|
||||||
sampleDirections.Get()[3] = Float3::Right;
|
sampleDirections[3] = Float3::Right;
|
||||||
sampleDirections.Get()[4] = Float3::Forward;
|
sampleDirections[4] = Float3::Forward;
|
||||||
sampleDirections.Get()[5] = Float3::Backward;
|
sampleDirections[5] = Float3::Backward;
|
||||||
for (int32 i = 6; i < sampleCount; i++)
|
for (int32 i = 6; i < sampleCount; i++)
|
||||||
sampleDirections.Get()[i] = rand.GetUnitVector();
|
sampleDirections[i] = rand.GetUnitVector();
|
||||||
}
|
}
|
||||||
Function<void(int32)> sdfJob = [&sdf, &resolution, &backfacesThreshold, &sampleDirections, &scene, &voxels, &xyzToLocalMul, &xyzToLocalAdd, &encodeMAD, &formatStride, &formatWrite](int32 z)
|
Function<void(int32)> sdfJob = [&sdf, &resolution, &backfacesThreshold, sampleDirections, &sampleCount, &scene, &voxels, &xyzToLocalMul, &xyzToLocalAdd, &encodeMAD, &formatStride, &formatWrite](int32 z)
|
||||||
{
|
{
|
||||||
PROFILE_CPU_NAMED("Model SDF Job");
|
PROFILE_CPU_NAMED("Model SDF Job");
|
||||||
Real hitDistance;
|
Real hitDistance;
|
||||||
@@ -203,7 +202,7 @@ bool ModelTool::GenerateModelSDF(Model* inputModel, ModelData* modelData, float
|
|||||||
|
|
||||||
// Raycast samples around voxel to count triangle backfaces hit
|
// Raycast samples around voxel to count triangle backfaces hit
|
||||||
int32 hitBackCount = 0, hitCount = 0;
|
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]);
|
Ray sampleRay(voxelPos, sampleDirections[sample]);
|
||||||
if (scene.RayCast(sampleRay, hitDistance, hitNormal, hitTriangle))
|
if (scene.RayCast(sampleRay, hitDistance, hitNormal, hitTriangle))
|
||||||
@@ -218,7 +217,7 @@ bool ModelTool::GenerateModelSDF(Model* inputModel, ModelData* modelData, float
|
|||||||
float distance = (float)minDistance;
|
float distance = (float)minDistance;
|
||||||
// TODO: surface thickness threshold? shift reduce distance for all voxels by something like 0.01 to enlarge thin geometry
|
// 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)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
|
// Voxel is inside the geometry so turn it into negative distance to the surface
|
||||||
distance *= -1;
|
distance *= -1;
|
||||||
|
|||||||
@@ -213,11 +213,11 @@ float3 SampleDDGIIrradiance(DDGIData data, Texture2D<snorm float4> probesData, T
|
|||||||
float2 uv = GetDDGIProbeUV(data, cascadeIndex, probeIndex, octahedralCoords, DDGI_PROBE_RESOLUTION_DISTANCE);
|
float2 uv = GetDDGIProbeUV(data, cascadeIndex, probeIndex, octahedralCoords, DDGI_PROBE_RESOLUTION_DISTANCE);
|
||||||
float2 probeDistance = probesDistance.SampleLevel(SamplerLinearClamp, uv, 0).rg * 2.0f;
|
float2 probeDistance = probesDistance.SampleLevel(SamplerLinearClamp, uv, 0).rg * 2.0f;
|
||||||
float probeDistanceMean = probeDistance.x;
|
float probeDistanceMean = probeDistance.x;
|
||||||
float probeDistanceMean2 = probeDistance.y;
|
|
||||||
|
|
||||||
// Visibility weight (Chebyshev)
|
// Visibility weight (Chebyshev)
|
||||||
if (biasedPosToProbeDist > probeDistanceMean)
|
if (biasedPosToProbeDist > probeDistanceMean)
|
||||||
{
|
{
|
||||||
|
float probeDistanceMean2 = probeDistance.y;
|
||||||
float probeDistanceVariance = abs(Square(probeDistanceMean) - probeDistanceMean2);
|
float probeDistanceVariance = abs(Square(probeDistanceMean) - probeDistanceMean2);
|
||||||
float chebyshevWeight = probeDistanceVariance / (probeDistanceVariance + Square(biasedPosToProbeDist - probeDistanceMean));
|
float chebyshevWeight = probeDistanceVariance / (probeDistanceVariance + Square(biasedPosToProbeDist - probeDistanceMean));
|
||||||
weight *= max(chebyshevWeight * chebyshevWeight * chebyshevWeight, 0.05f);
|
weight *= max(chebyshevWeight * chebyshevWeight * chebyshevWeight, 0.05f);
|
||||||
|
|||||||
@@ -223,7 +223,6 @@ GlobalSDFHit RayTraceGlobalSDF(const GlobalSDFData data, Texture3D<float> tex, T
|
|||||||
float4 cascadePosDistance = data.CascadePosDistance[cascade];
|
float4 cascadePosDistance = data.CascadePosDistance[cascade];
|
||||||
float voxelSize = data.CascadeVoxelSize[cascade];
|
float voxelSize = data.CascadeVoxelSize[cascade];
|
||||||
float voxelExtent = voxelSize * 0.5f;
|
float voxelExtent = voxelSize * 0.5f;
|
||||||
float cascadeMinStep = voxelSize;
|
|
||||||
float3 worldPosition = trace.WorldPosition + trace.WorldDirection * (voxelSize * cascadeTraceStartBias);
|
float3 worldPosition = trace.WorldPosition + trace.WorldDirection * (voxelSize * cascadeTraceStartBias);
|
||||||
|
|
||||||
// Hit the cascade bounds to find the intersection points
|
// Hit the cascade bounds to find the intersection points
|
||||||
@@ -270,7 +269,7 @@ GlobalSDFHit RayTraceGlobalSDF(const GlobalSDFData data, Texture3D<float> tex, T
|
|||||||
stepDistance *= cascadeMaxDistance;
|
stepDistance *= cascadeMaxDistance;
|
||||||
|
|
||||||
// Detect surface hit
|
// Detect surface hit
|
||||||
float minSurfaceThickness = voxelExtent * saturate(stepTime / (voxelExtent * 2.0f));
|
float minSurfaceThickness = voxelExtent * saturate(stepTime / voxelSize);
|
||||||
if (stepDistance < minSurfaceThickness)
|
if (stepDistance < minSurfaceThickness)
|
||||||
{
|
{
|
||||||
// Surface hit
|
// Surface hit
|
||||||
@@ -293,7 +292,7 @@ GlobalSDFHit RayTraceGlobalSDF(const GlobalSDFData data, Texture3D<float> tex, T
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Move forward
|
// Move forward
|
||||||
stepTime += max(stepDistance * trace.StepScale, cascadeMinStep);
|
stepTime += max(stepDistance * trace.StepScale, voxelSize);
|
||||||
}
|
}
|
||||||
hit.StepsCount += step;
|
hit.StepsCount += step;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user