Various improvements for SDF rendering
This commit is contained in:
BIN
Content/Shaders/GlobalSignDistanceField.flax
(Stored with Git LFS)
BIN
Content/Shaders/GlobalSignDistanceField.flax
(Stored with Git LFS)
Binary file not shown.
@@ -201,6 +201,13 @@ namespace FlaxEditor.Windows.Assets
|
||||
resolution.FloatValue.MaxValue = 100.0f;
|
||||
resolution.FloatValue.Value = sdf.Texture != null ? sdf.ResolutionScale : 1.0f;
|
||||
resolution.FloatValue.BoxValueChanged += b => { proxy.Window._importSettings.SDFResolution = b.Value; };
|
||||
proxy.Window._importSettings.SDFResolution = sdf.ResolutionScale;
|
||||
|
||||
var backfacesThreshold = group.FloatValue("Backfaces Threshold", "Custom threshold (in range 0-1) for adjusting mesh internals detection based on the percentage of test rays hit triangle backfaces. Use lower value for more dense mesh.");
|
||||
backfacesThreshold.FloatValue.MinValue = 0.001f;
|
||||
backfacesThreshold.FloatValue.MaxValue = 1.0f;
|
||||
backfacesThreshold.FloatValue.Value = proxy.Window._backfacesThreshold;
|
||||
backfacesThreshold.FloatValue.BoxValueChanged += b => { proxy.Window._backfacesThreshold = b.Value; };
|
||||
|
||||
var lodIndex = group.IntegerValue("LOD Index", "Index of the model Level of Detail to use for SDF data building. By default uses the lowest quality LOD for fast building.");
|
||||
lodIndex.IntValue.MinValue = 0;
|
||||
@@ -286,7 +293,7 @@ namespace FlaxEditor.Windows.Assets
|
||||
private void OnRebuildSDF()
|
||||
{
|
||||
var proxy = (MeshesPropertiesProxy)Values[0];
|
||||
proxy.Asset.GenerateSDF(proxy.Window._importSettings.SDFResolution, _sdfModelLodIndex.Value);
|
||||
proxy.Asset.GenerateSDF(proxy.Window._importSettings.SDFResolution, _sdfModelLodIndex.Value, true, proxy.Window._backfacesThreshold);
|
||||
proxy.Window.MarkAsEdited();
|
||||
Presenter.BuildLayoutOnUpdate();
|
||||
}
|
||||
@@ -770,6 +777,7 @@ namespace FlaxEditor.Windows.Assets
|
||||
private StaticModel _highlightActor;
|
||||
private MeshDataCache _meshData;
|
||||
private ModelImportSettings _importSettings = new ModelImportSettings();
|
||||
private float _backfacesThreshold = 0.6f;
|
||||
|
||||
/// <inheritdoc />
|
||||
public ModelWindow(Editor editor, AssetItem item)
|
||||
|
||||
@@ -635,7 +635,7 @@ bool Model::Save(bool withMeshDataFromGpu, const StringView& path)
|
||||
|
||||
#endif
|
||||
|
||||
bool Model::GenerateSDF(float resolutionScale, int32 lodIndex, bool cacheData)
|
||||
bool Model::GenerateSDF(float resolutionScale, int32 lodIndex, bool cacheData, float backfacesThreshold)
|
||||
{
|
||||
if (EnableModelSDF == 2)
|
||||
return true; // Not supported
|
||||
@@ -658,7 +658,7 @@ bool Model::GenerateSDF(float resolutionScale, int32 lodIndex, bool cacheData)
|
||||
#else
|
||||
class MemoryWriteStream* outputStream = nullptr;
|
||||
#endif
|
||||
if (ModelTool::GenerateModelSDF(this, nullptr, resolutionScale, lodIndex, &SDF, outputStream, GetPath()))
|
||||
if (ModelTool::GenerateModelSDF(this, nullptr, resolutionScale, lodIndex, &SDF, outputStream, GetPath(), backfacesThreshold))
|
||||
return true;
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
@@ -213,8 +213,9 @@ public:
|
||||
/// <param name="resolutionScale">The SDF texture resolution scale. Use higher values for more precise data but with significant performance and memory overhead.</param>
|
||||
/// <param name="lodIndex">The index of the LOD to use for the SDF building.</param>
|
||||
/// <param name="cacheData">If true, the generated SDF texture data will be cached on CPU (in asset chunk storage) to allow saving it later, otherwise it will be runtime for GPU-only. Ignored for virtual assets or in build.</param>
|
||||
/// <param name="backfacesThreshold">Custom threshold (in range 0-1) for adjusting mesh internals detection based on the percentage of test rays hit triangle backfaces. Use lower value for more dense mesh.</param>
|
||||
/// <returns>True if failed, otherwise false.</returns>
|
||||
API_FUNCTION() bool GenerateSDF(float resolutionScale = 1.0f, int32 lodIndex = 6, bool cacheData = true);
|
||||
API_FUNCTION() bool GenerateSDF(float resolutionScale = 1.0f, int32 lodIndex = 6, bool cacheData = true, float backfacesThreshold = 0.6f);
|
||||
|
||||
/// <summary>
|
||||
/// Sets set SDF data (releases the current one).
|
||||
|
||||
@@ -580,10 +580,13 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
|
||||
{
|
||||
// Get the last counter value (accept staging readback delay)
|
||||
auto data = (uint32*)_culledObjectsSizeBuffer->Map(GPUResourceMapMode::Read);
|
||||
uint32 counter = data[surfaceAtlasData.CulledObjectsCounterIndex];
|
||||
_culledObjectsSizeBuffer->Unmap();
|
||||
if (counter > 0)
|
||||
objectsBufferCapacity = counter * sizeof(Vector4);
|
||||
if (data)
|
||||
{
|
||||
uint32 counter = data[surfaceAtlasData.CulledObjectsCounterIndex];
|
||||
_culledObjectsSizeBuffer->Unmap();
|
||||
if (counter > 0)
|
||||
objectsBufferCapacity = counter * sizeof(Vector4);
|
||||
}
|
||||
}
|
||||
if (surfaceAtlasData.CulledObjectsCounterIndex == -1)
|
||||
{
|
||||
|
||||
@@ -66,7 +66,7 @@ ModelSDFMip::ModelSDFMip(int32 mipIndex, const TextureMipData& mip)
|
||||
{
|
||||
}
|
||||
|
||||
bool ModelTool::GenerateModelSDF(Model* inputModel, ModelData* modelData, float resolutionScale, int32 lodIndex, ModelBase::SDFData* outputSDF, MemoryWriteStream* outputStream, const StringView& assetName)
|
||||
bool ModelTool::GenerateModelSDF(Model* inputModel, ModelData* modelData, float resolutionScale, int32 lodIndex, ModelBase::SDFData* outputSDF, MemoryWriteStream* outputStream, const StringView& assetName, float backfacesThreshold)
|
||||
{
|
||||
PROFILE_CPU();
|
||||
auto startTime = Platform::GetTimeSeconds();
|
||||
@@ -176,7 +176,7 @@ bool ModelTool::GenerateModelSDF(Model* inputModel, ModelData* modelData, float
|
||||
for (int32 i = 6; i < sampleCount; i++)
|
||||
sampleDirections.Get()[i] = rand.GetUnitVector();
|
||||
}
|
||||
Function<void(int32)> sdfJob = [&sdf, &resolution, &sampleDirections, &scene, &voxels, &xyzToLocalMul, &xyzToLocalAdd, &encodeMAD, &formatStride, &formatWrite](int32 z)
|
||||
Function<void(int32)> sdfJob = [&sdf, &resolution, &backfacesThreshold, &sampleDirections, &scene, &voxels, &xyzToLocalMul, &xyzToLocalAdd, &encodeMAD, &formatStride, &formatWrite](int32 z)
|
||||
{
|
||||
PROFILE_CPU_NAMED("Model SDF Job");
|
||||
float hitDistance;
|
||||
@@ -210,8 +210,8 @@ bool ModelTool::GenerateModelSDF(Model* inputModel, ModelData* modelData, float
|
||||
|
||||
float distance = minDistance;
|
||||
// TODO: surface thickness threshold? shift reduce distance for all voxels by something like 0.01 to enlarge thin geometry
|
||||
//if ((float)hitBackCount > )hitCount * 0.3f && hitCount != 0)
|
||||
if ((float)hitBackCount > (float)sampleDirections.Count() * 0.6f && hitCount != 0)
|
||||
// if ((float)hitBackCount > (float)hitCount * 0.3f && hitCount != 0)
|
||||
if ((float)hitBackCount > (float)sampleDirections.Count() * backfacesThreshold && hitCount != 0)
|
||||
{
|
||||
// Voxel is inside the geometry so turn it into negative distance to the surface
|
||||
distance *= -1;
|
||||
|
||||
@@ -185,7 +185,7 @@ public:
|
||||
|
||||
// Optional: inputModel or modelData
|
||||
// Optional: outputSDF or null, outputStream or null
|
||||
static bool GenerateModelSDF(class Model* inputModel, class ModelData* modelData, float resolutionScale, int32 lodIndex, ModelBase::SDFData* outputSDF, class MemoryWriteStream* outputStream, const StringView& assetName);
|
||||
static bool GenerateModelSDF(class Model* inputModel, class ModelData* modelData, float resolutionScale, int32 lodIndex, ModelBase::SDFData* outputSDF, class MemoryWriteStream* outputStream, const StringView& assetName, float backfacesThreshold = 0.6f);
|
||||
|
||||
#if USE_EDITOR
|
||||
public:
|
||||
|
||||
@@ -128,7 +128,7 @@ void CS_RasterizeHeightfield(uint3 GroupId : SV_GroupID, uint3 DispatchThreadId
|
||||
uint3 voxelCoord = ChunkCoord + DispatchThreadId;
|
||||
float3 voxelWorldPos = voxelCoord * CascadeCoordToPosMul + CascadeCoordToPosAdd;
|
||||
float minDistance = MaxDistance * GlobalSDFTex[voxelCoord];
|
||||
float thickness = CascadeVoxelSize * -4;
|
||||
float thickness = CascadeVoxelSize * -8;
|
||||
for (uint i = 0; i < ObjectsCount; i++)
|
||||
{
|
||||
ObjectRasterizeData objectData = ObjectsBuffer[Objects[i / 4][i % 4]];
|
||||
|
||||
@@ -194,7 +194,7 @@ float4 SampleGlobalSurfaceAtlas(const GlobalSurfaceAtlasData data, ByteAddressBu
|
||||
continue;
|
||||
|
||||
// Remove the scale vector from the transformation matrix
|
||||
float3x3 worldToLocal = object.WorldToLocal;
|
||||
float3x3 worldToLocal = (float3x3)object.WorldToLocal;
|
||||
float scaleX = length(worldToLocal[0]);
|
||||
float scaleY = length(worldToLocal[1]);
|
||||
float scaleZ = length(worldToLocal[2]);
|
||||
|
||||
Reference in New Issue
Block a user