diff --git a/Source/Engine/Particles/Graph/CPU/ParticleEmitterGraph.CPU.ParticleModules.cpp b/Source/Engine/Particles/Graph/CPU/ParticleEmitterGraph.CPU.ParticleModules.cpp index bebe80479..7aa68e32e 100644 --- a/Source/Engine/Particles/Graph/CPU/ParticleEmitterGraph.CPU.ParticleModules.cpp +++ b/Source/Engine/Particles/Graph/CPU/ParticleEmitterGraph.CPU.ParticleModules.cpp @@ -69,7 +69,7 @@ namespace scale *= 1.72531f; } - return noise / weight; + return noise / Math::Max(weight, ZeroTolerance); } VariantType::Types GetVariantType(ParticleAttribute::ValueTypes type) @@ -486,7 +486,7 @@ void ParticleEmitterGraphCPUExecutor::ProcessModule(ParticleEmitterGraphCPUNode* float particleDrag = drag; \ if (useSpriteSize) \ particleDrag *= ((Vector2*)spriteSizePtr)->MulValues(); \ - *((Vector3*)velocityPtr) *= Math::Max(0.0f, 1.0f - (particleDrag * _deltaTime) / *(float*)massPtr); \ + *((Vector3*)velocityPtr) *= Math::Max(0.0f, 1.0f - (particleDrag * _deltaTime) / Math::Max(*(float*)massPtr, ZeroTolerance)); \ velocityPtr += stride; \ massPtr += stride; \ spriteSizePtr += stride @@ -545,7 +545,7 @@ void ParticleEmitterGraphCPUExecutor::ProcessModule(ParticleEmitterGraphCPUNode* Vector3 vectorFieldUVW = Vector3::Transform(*((Vector3*)positionPtr), invFieldTransformMatrix); \ Vector3 force = Noise3D(vectorFieldUVW + 0.5f, octavesCount, roughness); \ force = Vector3::Transform(force, fieldTransformMatrix) * intensity; \ - *((Vector3*)velocityPtr) += force * (_deltaTime / *(float*)massPtr); \ + *((Vector3*)velocityPtr) += force * (_deltaTime / Math::Max(*(float*)massPtr, ZeroTolerance)); \ positionPtr += stride; \ velocityPtr += stride; \ massPtr += stride @@ -1009,7 +1009,7 @@ void ParticleEmitterGraphCPUExecutor::ProcessModule(ParticleEmitterGraphCPUNode* #define INPUTS_FETCH() \ const Vector3 center = (Vector3)GetValue(centerBox, 2); \ - const float radius = (float)GetValue(radiusBox, 3); \ + const float radius = Math::Max((float)GetValue(radiusBox, 3), ZeroTolerance); \ const float thickness = (float)GetValue(thicknessBox, 4); \ const float arc = (float)GetValue(arcBox, 5) * DegreesToRadians #define LOGIC() \ @@ -1017,20 +1017,20 @@ void ParticleEmitterGraphCPUExecutor::ProcessModule(ParticleEmitterGraphCPUNode* float sinTheta, cosTheta; \ Math::SinCos(u.X * TWO_PI, sinTheta, cosTheta); \ float r = Math::Saturate(thickness / radius); \ - Vector2 s1_1 = r * Vector2(cosTheta, sinTheta) + Vector2(1, 0); \ - Vector2 s1_2 = r * Vector2(-cosTheta, sinTheta) + Vector2(1, 0); \ - float w = s1_1.X / (s1_1.X + s1_2.X); \ + Vector2 s11 = r * Vector2(cosTheta, sinTheta) + Vector2(1, 0); \ + Vector2 s12 = r * Vector2(-cosTheta, sinTheta) + Vector2(1, 0); \ + float w = s11.X / (s11.X + s12.X); \ Vector3 t; \ float phi; \ if (u.Y < w) \ { \ phi = arc * u.Y / w; \ - t = Vector3(s1_1.X, 0, s1_1.Y); \ + t = Vector3(s11.X, 0, s11.Y); \ } \ else \ { \ phi = arc * (u.Y - w) / (1.0f - w); \ - t = Vector3(s1_2.X, 0, s1_2.Y); \ + t = Vector3(s12.X, 0, s12.Y); \ } \ float s, c; \ Math::SinCos(phi, c, s); \ @@ -1262,7 +1262,7 @@ void ParticleEmitterGraphCPUExecutor::ProcessModule(ParticleEmitterGraphCPUNode* if (sign * sqrLength <= sign * totalRadius * totalRadius) \ { \ float dist = Math::Sqrt(sqrLength); \ - Vector3 n = sign * dir / dist; \ + Vector3 n = sign * dir / Math::Max(dist, ZeroTolerance); \ *(Vector3*)positionPtr = position - n * (dist - totalRadius) * sign; \ COLLISION_LOGIC() @@ -1374,7 +1374,7 @@ void ParticleEmitterGraphCPUExecutor::ProcessModule(ParticleEmitterGraphCPUNode* collision = Math::Abs(dir.Y) > halfHeight || sqrLength > cylinderRadiusT * cylinderRadiusT; \ if (collision) \ { \ - float dist = Math::Sqrt(sqrLength); \ + float dist = Math::Max(Math::Sqrt(sqrLength), ZeroTolerance); \ float distToCap = sign * (halfHeight - Math::Abs(dir.Y)); \ float distToSide = sign * (cylinderRadiusT - dist); \ Vector3 n = Vector3(dir.X / dist, Math::Sign(dir.Y), dir.Z / dist) * sign; \ diff --git a/Source/Engine/Particles/Graph/CPU/ParticleEmitterGraph.CPU.Particles.cpp b/Source/Engine/Particles/Graph/CPU/ParticleEmitterGraph.CPU.Particles.cpp index 08db1c0d3..d56bf6d5c 100644 --- a/Source/Engine/Particles/Graph/CPU/ParticleEmitterGraph.CPU.Particles.cpp +++ b/Source/Engine/Particles/Graph/CPU/ParticleEmitterGraph.CPU.Particles.cpp @@ -284,7 +284,7 @@ void ParticleEmitterGraphCPUExecutor::ProcessGroupParticles(Box* box, Node* node { const float age = GET_PARTICLE_ATTRIBUTE(0, float); const float lifetime = GET_PARTICLE_ATTRIBUTE(1, float); - value = age / lifetime; + value = age / Math::Max(lifetime, ZeroTolerance); break; } // Effect Position diff --git a/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.ParticleModules.cpp b/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.ParticleModules.cpp index 23dac1622..57d4ededc 100644 --- a/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.ParticleModules.cpp +++ b/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.ParticleModules.cpp @@ -177,7 +177,7 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node) " {{\n" " // Linear Drag\n" " float drag = {2} * {3}.x * {3}.y;\n" - " {0} *= max(0.0f, 1.0f - (drag * DeltaTime) / {1});\n" + " {0} *= max(0.0f, 1.0f - (drag * DeltaTime) / max({1}, PARTICLE_THRESHOLD));\n" " }}\n" ), velocity.Value, mass.Value, drag.Value, spriteSize.Value); } @@ -188,7 +188,7 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node) " {{\n" " // Linear Drag\n" " float drag = {2};\n" - " {0} *= max(0.0f, 1.0f - (drag * DeltaTime) / {1});\n" + " {0} *= max(0.0f, 1.0f - (drag * DeltaTime) / max({1}, PARTICLE_THRESHOLD));\n" " }}\n" ), velocity.Value, mass.Value, drag.Value); } @@ -219,7 +219,7 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node) " float3 vectorFieldUVW = mul(invFieldTransformMatrix, float4({0}, 1.0f)).xyz;\n" " float3 force = Noise3D(vectorFieldUVW + 0.5f, {8}, {6});\n" " force = mul(fieldTransformMatrix, float4(force, 0.0f)).xyz * {7};\n" - " {1} += force * (DeltaTime / {2});\n" + " {1} += force * (DeltaTime / max({2}, PARTICLE_THRESHOLD));\n" " }}\n" ), position.Value, velocity.Value, mass.Value, fieldPosition.Value, fieldRotation.Value, fieldScale.Value, roughness.Value, intensity.Value, octavesCount.Value); break; @@ -486,21 +486,21 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node) " float3 u = RAND3;\n" " float sinTheta, cosTheta;\n" " sincos(u.x * PI * 2.0f, sinTheta, cosTheta);\n" - " float r = saturate((float){4} / {3});\n" - " float2 s1_1 = r * float2( cosTheta, sinTheta) + float2(1, 0);\n" - " float2 s1_2 = r * float2(-cosTheta, sinTheta) + float2(1, 0);\n" - " float w = s1_1.x / (s1_1.x + s1_2.x);\n" + " float r = saturate((float){4} / max({3}, PARTICLE_THRESHOLD));\n" + " float2 s11 = r * float2( cosTheta, sinTheta) + float2(1, 0);\n" + " float2 s12 = r * float2(-cosTheta, sinTheta) + float2(1, 0);\n" + " float w = s11.x / (s11.x + s12.x);\n" " float3 t;\n" " float phi;\n" " if (u.y < w)\n" " {{\n" " phi = radians({5}) * u.y / w;\n" - " t = float3(s1_1.x, 0, s1_1.y);\n" + " t = float3(s11.x, 0, s11.y);\n" " }}\n" " else\n" " {{\n" " phi = radians({5}) * (u.y - w) / (1.0f - w);\n" - " t = float3(s1_2.x, 0, s1_2.y);\n" + " t = float3(s12.x, 0, s12.y);\n" " }}\n" " float s, c;\n" " sincos(phi, c, s);\n" @@ -693,7 +693,7 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node) " if ({4} * sqrLength <= {4} * totalRadius * totalRadius)\n" " {{\n" " float dist = sqrt(sqrLength);\n" - " float3 n = {4} * dir / dist;\n" + " float3 n = {4} * dir / max(dist, PARTICLE_THRESHOLD);\n" " {0} -= n * (dist - totalRadius) * {4};\n" COLLISION_LOGIC() " }}\n" @@ -787,7 +787,7 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node) " collision = abs(dir.y) > halfHeight || sqrLength > cylinderRadiusT * cylinderRadiusT;\n" " if (collision)\n" " {{\n" - " float dist = sqrt(sqrLength);\n" + " float dist = max(sqrt(sqrLength), PARTICLE_THRESHOLD);\n" " float distToCap = {4} * (halfHeight - abs(dir.y));\n" " float distToSide = {4} * (cylinderRadiusT - dist);\n" " float3 n = float3(dir.x / dist, sign(dir.y), dir.z / dist) * {4};\n"