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.MaxValue = 100.0f;
|
||||||
resolution.FloatValue.Value = sdf.Texture != null ? sdf.ResolutionScale : 1.0f;
|
resolution.FloatValue.Value = sdf.Texture != null ? sdf.ResolutionScale : 1.0f;
|
||||||
resolution.FloatValue.BoxValueChanged += b => { proxy.Window._importSettings.SDFResolution = b.Value; };
|
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.");
|
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;
|
lodIndex.IntValue.MinValue = 0;
|
||||||
@@ -286,7 +293,7 @@ namespace FlaxEditor.Windows.Assets
|
|||||||
private void OnRebuildSDF()
|
private void OnRebuildSDF()
|
||||||
{
|
{
|
||||||
var proxy = (MeshesPropertiesProxy)Values[0];
|
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();
|
proxy.Window.MarkAsEdited();
|
||||||
Presenter.BuildLayoutOnUpdate();
|
Presenter.BuildLayoutOnUpdate();
|
||||||
}
|
}
|
||||||
@@ -770,6 +777,7 @@ namespace FlaxEditor.Windows.Assets
|
|||||||
private StaticModel _highlightActor;
|
private StaticModel _highlightActor;
|
||||||
private MeshDataCache _meshData;
|
private MeshDataCache _meshData;
|
||||||
private ModelImportSettings _importSettings = new ModelImportSettings();
|
private ModelImportSettings _importSettings = new ModelImportSettings();
|
||||||
|
private float _backfacesThreshold = 0.6f;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public ModelWindow(Editor editor, AssetItem item)
|
public ModelWindow(Editor editor, AssetItem item)
|
||||||
|
|||||||
@@ -635,7 +635,7 @@ bool Model::Save(bool withMeshDataFromGpu, const StringView& path)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool Model::GenerateSDF(float resolutionScale, int32 lodIndex, bool cacheData)
|
bool Model::GenerateSDF(float resolutionScale, int32 lodIndex, bool cacheData, float backfacesThreshold)
|
||||||
{
|
{
|
||||||
if (EnableModelSDF == 2)
|
if (EnableModelSDF == 2)
|
||||||
return true; // Not supported
|
return true; // Not supported
|
||||||
@@ -658,7 +658,7 @@ bool Model::GenerateSDF(float resolutionScale, int32 lodIndex, bool cacheData)
|
|||||||
#else
|
#else
|
||||||
class MemoryWriteStream* outputStream = nullptr;
|
class MemoryWriteStream* outputStream = nullptr;
|
||||||
#endif
|
#endif
|
||||||
if (ModelTool::GenerateModelSDF(this, nullptr, resolutionScale, lodIndex, &SDF, outputStream, GetPath()))
|
if (ModelTool::GenerateModelSDF(this, nullptr, resolutionScale, lodIndex, &SDF, outputStream, GetPath(), backfacesThreshold))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
#if USE_EDITOR
|
#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="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="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="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>
|
/// <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>
|
/// <summary>
|
||||||
/// Sets set SDF data (releases the current one).
|
/// 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)
|
// Get the last counter value (accept staging readback delay)
|
||||||
auto data = (uint32*)_culledObjectsSizeBuffer->Map(GPUResourceMapMode::Read);
|
auto data = (uint32*)_culledObjectsSizeBuffer->Map(GPUResourceMapMode::Read);
|
||||||
uint32 counter = data[surfaceAtlasData.CulledObjectsCounterIndex];
|
if (data)
|
||||||
_culledObjectsSizeBuffer->Unmap();
|
{
|
||||||
if (counter > 0)
|
uint32 counter = data[surfaceAtlasData.CulledObjectsCounterIndex];
|
||||||
objectsBufferCapacity = counter * sizeof(Vector4);
|
_culledObjectsSizeBuffer->Unmap();
|
||||||
|
if (counter > 0)
|
||||||
|
objectsBufferCapacity = counter * sizeof(Vector4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (surfaceAtlasData.CulledObjectsCounterIndex == -1)
|
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();
|
PROFILE_CPU();
|
||||||
auto startTime = Platform::GetTimeSeconds();
|
auto startTime = Platform::GetTimeSeconds();
|
||||||
@@ -176,7 +176,7 @@ bool ModelTool::GenerateModelSDF(Model* inputModel, ModelData* modelData, float
|
|||||||
for (int32 i = 6; i < sampleCount; i++)
|
for (int32 i = 6; i < sampleCount; i++)
|
||||||
sampleDirections.Get()[i] = rand.GetUnitVector();
|
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");
|
PROFILE_CPU_NAMED("Model SDF Job");
|
||||||
float hitDistance;
|
float hitDistance;
|
||||||
@@ -210,8 +210,8 @@ bool ModelTool::GenerateModelSDF(Model* inputModel, ModelData* modelData, float
|
|||||||
|
|
||||||
float distance = minDistance;
|
float distance = 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 > )hitCount * 0.3f && hitCount != 0)
|
// if ((float)hitBackCount > (float)hitCount * 0.3f && hitCount != 0)
|
||||||
if ((float)hitBackCount > (float)sampleDirections.Count() * 0.6f && 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
|
// Voxel is inside the geometry so turn it into negative distance to the surface
|
||||||
distance *= -1;
|
distance *= -1;
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ public:
|
|||||||
|
|
||||||
// Optional: inputModel or modelData
|
// Optional: inputModel or modelData
|
||||||
// Optional: outputSDF or null, outputStream or null
|
// 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
|
#if USE_EDITOR
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ void CS_RasterizeHeightfield(uint3 GroupId : SV_GroupID, uint3 DispatchThreadId
|
|||||||
uint3 voxelCoord = ChunkCoord + DispatchThreadId;
|
uint3 voxelCoord = ChunkCoord + DispatchThreadId;
|
||||||
float3 voxelWorldPos = voxelCoord * CascadeCoordToPosMul + CascadeCoordToPosAdd;
|
float3 voxelWorldPos = voxelCoord * CascadeCoordToPosMul + CascadeCoordToPosAdd;
|
||||||
float minDistance = MaxDistance * GlobalSDFTex[voxelCoord];
|
float minDistance = MaxDistance * GlobalSDFTex[voxelCoord];
|
||||||
float thickness = CascadeVoxelSize * -4;
|
float thickness = CascadeVoxelSize * -8;
|
||||||
for (uint i = 0; i < ObjectsCount; i++)
|
for (uint i = 0; i < ObjectsCount; i++)
|
||||||
{
|
{
|
||||||
ObjectRasterizeData objectData = ObjectsBuffer[Objects[i / 4][i % 4]];
|
ObjectRasterizeData objectData = ObjectsBuffer[Objects[i / 4][i % 4]];
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ float4 SampleGlobalSurfaceAtlas(const GlobalSurfaceAtlasData data, ByteAddressBu
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Remove the scale vector from the transformation matrix
|
// Remove the scale vector from the transformation matrix
|
||||||
float3x3 worldToLocal = object.WorldToLocal;
|
float3x3 worldToLocal = (float3x3)object.WorldToLocal;
|
||||||
float scaleX = length(worldToLocal[0]);
|
float scaleX = length(worldToLocal[0]);
|
||||||
float scaleY = length(worldToLocal[1]);
|
float scaleY = length(worldToLocal[1]);
|
||||||
float scaleZ = length(worldToLocal[2]);
|
float scaleZ = length(worldToLocal[2]);
|
||||||
|
|||||||
Reference in New Issue
Block a user