Fix GPU particles issues with Global SDF far away from scene geometry
This commit is contained in:
@@ -626,8 +626,8 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node)
|
||||
" // Position (Global SDF)\n"
|
||||
" float3 wsPos = {2};\n"
|
||||
" float dist;\n"
|
||||
" float3 dir = -normalize(SampleGlobalSDFGradient({1}, {1}_Tex, wsPos, dist));\n"
|
||||
" {0} += dir * dist;\n"
|
||||
" float3 dir = -normalize(SampleGlobalSDFGradient({1}, {1}_Tex, {1}_Mip, wsPos, dist));\n"
|
||||
" {0} += dist < GLOBAL_SDF_WORLD_SIZE ? dir * dist : float3(0, 0, 0);\n"
|
||||
" }}\n"
|
||||
), position.Value, param.ShaderName, wsPos);
|
||||
break;
|
||||
@@ -892,7 +892,7 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node)
|
||||
" {{\n"
|
||||
" // Conform to Global SDF\n"
|
||||
" float dist;\n"
|
||||
" float3 dir = normalize(SampleGlobalSDFGradient({3}, {3}_Tex, {0}, dist));\n"
|
||||
" float3 dir = normalize(SampleGlobalSDFGradient({3}, {3}_Tex, {3}_Mip, {0}, dist));\n"
|
||||
" if (dist > 0) dir *= -1;\n"
|
||||
" float distToSurface = abs(dist);\n"
|
||||
" float spdNormal = dot(dir, {1});\n"
|
||||
@@ -900,7 +900,7 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node)
|
||||
" float tgtSpeed = {4} * ratio;\n"
|
||||
" float deltaSpeed = tgtSpeed - spdNormal;\n"
|
||||
" float3 deltaVelocity = dir * (sign(deltaSpeed) * min(abs(deltaSpeed), DeltaTime * lerp({7}, {5}, ratio)) / max({2}, PARTICLE_THRESHOLD));\n"
|
||||
" {1} += deltaVelocity;\n"
|
||||
" {1} += dist < GLOBAL_SDF_WORLD_SIZE ? deltaVelocity : 0.0f;\n"
|
||||
" }}\n"
|
||||
), position.Value, velocity.Value, mass.Value, param.ShaderName, attractionSpeed.Value, attractionForce.Value, stickDistance.Value, stickForce.Value);
|
||||
break;
|
||||
@@ -917,11 +917,11 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node)
|
||||
" // Collision (Global SDF)\n"
|
||||
" float3 nextPos = {0} + {1} * DeltaTime;\n"
|
||||
" nextPos = mul(float4(nextPos, 1), WorldMatrix).xyz;\n"
|
||||
" float dist = SampleGlobalSDF({10}, {10}_Tex, nextPos);\n"
|
||||
" float dist = SampleGlobalSDF({10}, {10}_Tex, {10}_Mip, nextPos);\n"
|
||||
" if (dist < {5})\n"
|
||||
" {{\n"
|
||||
" {0} = mul(float4({0}, 1), WorldMatrix).xyz;\n"
|
||||
" float3 n = normalize(SampleGlobalSDFGradient({10}, {10}_Tex, {0}, dist));\n"
|
||||
" float3 n = normalize(SampleGlobalSDFGradient({10}, {10}_Tex, {10}_Mip, {0}, dist));\n"
|
||||
" {0} += n * -dist;\n"
|
||||
" {0} = mul(float4({0}, 1), InvWorldMatrix).xyz;\n"
|
||||
COLLISION_LOGIC()
|
||||
@@ -931,10 +931,10 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node)
|
||||
" {{\n"
|
||||
" // Collision (Global SDF)\n"
|
||||
" float3 nextPos = {0} + {1} * DeltaTime;\n"
|
||||
" float dist = SampleGlobalSDF({10}, {10}_Tex, nextPos);\n"
|
||||
" float dist = SampleGlobalSDF({10}, {10}_Tex, {10}_Mip, nextPos);\n"
|
||||
" if (dist < {5})\n"
|
||||
" {{\n"
|
||||
" float3 n = normalize(SampleGlobalSDFGradient({10}, {10}_Tex, {0}, dist));\n"
|
||||
" float3 n = normalize(SampleGlobalSDFGradient({10}, {10}_Tex, {10}_Mip, {0}, dist));\n"
|
||||
" {0} += n * -dist;\n"
|
||||
COLLISION_LOGIC()
|
||||
" }}\n"
|
||||
|
||||
@@ -155,13 +155,14 @@ float SampleGlobalSDF(const GlobalSDFData data, Texture3D<snorm float> tex, Text
|
||||
}
|
||||
|
||||
// Samples the Global SDF and returns the gradient vector (derivative) at the given world location. Normalize it to get normal vector.
|
||||
float3 SampleGlobalSDFGradient(const GlobalSDFData data, Texture3D<snorm float> tex, float3 worldPosition, out float distance)
|
||||
float3 SampleGlobalSDFGradient(const GlobalSDFData data, Texture3D<snorm float> tex, float3 worldPosition, out float distance, uint startCascade = 0)
|
||||
{
|
||||
float3 gradient = float3(0, 0.00001f, 0);
|
||||
distance = GLOBAL_SDF_WORLD_SIZE;
|
||||
if (data.CascadePosDistance[3].w <= 0.0f)
|
||||
return gradient;
|
||||
for (uint cascade = 0; cascade < data.CascadesCount; cascade++)
|
||||
startCascade = min(startCascade, data.CascadesCount - 1);
|
||||
for (uint cascade = startCascade; cascade < data.CascadesCount; cascade++)
|
||||
{
|
||||
float3 cascadeUV, textureUV;
|
||||
GetGlobalSDFCascadeUV(data, cascade, worldPosition, cascadeUV, textureUV);
|
||||
@@ -205,19 +206,32 @@ float3 SampleGlobalSDFGradient(const GlobalSDFData data, Texture3D<snorm float>
|
||||
float distanceMip = mip.SampleLevel(SamplerLinearClamp, textureUV, 0) * maxDistanceMip;
|
||||
if (distanceMip < chunkSize && all(cascadeUV > 0) && all(cascadeUV < 1))
|
||||
{
|
||||
distance = distanceMip;
|
||||
float maxDistanceTex = data.CascadeMaxDistanceTex[cascade];
|
||||
float distanceTex = tex.SampleLevel(SamplerLinearClamp, textureUV, 0) * maxDistanceTex;
|
||||
if (distanceTex < chunkMargin)
|
||||
{
|
||||
distance = distanceTex;
|
||||
float texelOffset = 1.0f / data.Resolution;
|
||||
float xp = tex.SampleLevel(SamplerLinearClamp, float3(textureUV.x + texelOffset, textureUV.y, textureUV.z), 0).x;
|
||||
float xn = tex.SampleLevel(SamplerLinearClamp, float3(textureUV.x - texelOffset, textureUV.y, textureUV.z), 0).x;
|
||||
float yp = tex.SampleLevel(SamplerLinearClamp, float3(textureUV.x, textureUV.y + texelOffset, textureUV.z), 0).x;
|
||||
float yn = tex.SampleLevel(SamplerLinearClamp, float3(textureUV.x, textureUV.y - texelOffset, textureUV.z), 0).x;
|
||||
float zp = tex.SampleLevel(SamplerLinearClamp, float3(textureUV.x, textureUV.y, textureUV.z + texelOffset), 0).x;
|
||||
float zn = tex.SampleLevel(SamplerLinearClamp, float3(textureUV.x, textureUV.y, textureUV.z - texelOffset), 0).x;
|
||||
gradient = float3(xp - xn, yp - yn, zp - zn) * maxDistanceTex;
|
||||
float texelOffset = 1.0f / data.Resolution;
|
||||
float xp = tex.SampleLevel(SamplerLinearClamp, float3(textureUV.x + texelOffset, textureUV.y, textureUV.z), 0).x;
|
||||
float xn = tex.SampleLevel(SamplerLinearClamp, float3(textureUV.x - texelOffset, textureUV.y, textureUV.z), 0).x;
|
||||
float yp = tex.SampleLevel(SamplerLinearClamp, float3(textureUV.x, textureUV.y + texelOffset, textureUV.z), 0).x;
|
||||
float yn = tex.SampleLevel(SamplerLinearClamp, float3(textureUV.x, textureUV.y - texelOffset, textureUV.z), 0).x;
|
||||
float zp = tex.SampleLevel(SamplerLinearClamp, float3(textureUV.x, textureUV.y, textureUV.z + texelOffset), 0).x;
|
||||
float zn = tex.SampleLevel(SamplerLinearClamp, float3(textureUV.x, textureUV.y, textureUV.z - texelOffset), 0).x;
|
||||
gradient = float3(xp - xn, yp - yn, zp - zn) * maxDistanceTex;
|
||||
}
|
||||
else
|
||||
{
|
||||
distance = distanceMip;
|
||||
float texelOffset = (float)GLOBAL_SDF_RASTERIZE_MIP_FACTOR / data.Resolution;
|
||||
float xp = mip.SampleLevel(SamplerLinearClamp, float3(textureUV.x + texelOffset, textureUV.y, textureUV.z), 0).x;
|
||||
float xn = mip.SampleLevel(SamplerLinearClamp, float3(textureUV.x - texelOffset, textureUV.y, textureUV.z), 0).x;
|
||||
float yp = mip.SampleLevel(SamplerLinearClamp, float3(textureUV.x, textureUV.y + texelOffset, textureUV.z), 0).x;
|
||||
float yn = mip.SampleLevel(SamplerLinearClamp, float3(textureUV.x, textureUV.y - texelOffset, textureUV.z), 0).x;
|
||||
float zp = mip.SampleLevel(SamplerLinearClamp, float3(textureUV.x, textureUV.y, textureUV.z + texelOffset), 0).x;
|
||||
float zn = mip.SampleLevel(SamplerLinearClamp, float3(textureUV.x, textureUV.y, textureUV.z - texelOffset), 0).x;
|
||||
gradient = float3(xp - xn, yp - yn, zp - zn) * maxDistanceMip;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user