Add Particles support for Large Worlds

This commit is contained in:
Wojtek Figat
2022-07-03 18:09:04 +02:00
parent 039bf8253a
commit cb92e3c54c
6 changed files with 18 additions and 25 deletions

View File

@@ -409,13 +409,11 @@ void ParticleEmitterGraphCPUExecutor::Draw(ParticleEmitter* emitter, ParticleEff
const float radius = (float)GetValue(module->GetBox(1), 3);
const float fallOffExponent = (float)GetValue(module->GetBox(2), 4);
lightData.Position = *(Float3*)positionPtr;
lightData.Color = Float3(color) * color.W;
lightData.Radius = radius;
lightData.FallOffExponent = fallOffExponent;
if (emitter->SimulationSpace == ParticlesSimulationSpace::Local)
Float3::Transform(lightData.Position, transform, lightData.Position);
Float3::Transform(*(Float3*)positionPtr, transform, lightData.Position);
renderContext.List->PointLights.Add(lightData);

View File

@@ -231,7 +231,11 @@ void GPUParticles::Execute(GPUContext* context, ParticleEmitter* emitter, Partic
else
{
Matrix worldMatrix;
effect->GetWorld(&worldMatrix);
const Transform transform = effect->GetTransform();
if (viewTask)
viewTask->View.GetWorldMatrix(transform, worldMatrix);
else
transform.GetWorld(worldMatrix);
Matrix::Transpose(worldMatrix, cbData->WorldMatrix);
worldMatrix.Invert();
Matrix::Transpose(worldMatrix, cbData->InvWorldMatrix);

View File

@@ -14,8 +14,8 @@ ParticleEffect::ParticleEffect(const SpawnParams& params)
, _lastUpdateFrame(0)
, _lastMinDstSqr(MAX_Real)
{
_world = Matrix::Identity;
UpdateBounds();
_box = BoundingBox(_transform.Translation);
BoundingSphere::FromBox(_box, _sphere);
ParticleSystem.Changed.Bind<ParticleEffect, &ParticleEffect::OnParticleSystemModified>(this);
ParticleSystem.Loaded.Bind<ParticleEffect, &ParticleEffect::OnParticleSystemLoaded>(this);
@@ -295,7 +295,7 @@ void ParticleEffect::UpdateBounds()
if (emitter->SimulationSpace == ParticlesSimulationSpace::Local)
{
BoundingBox::Transform(emitterBounds, _world, emitterBounds);
BoundingBox::Transform(emitterBounds, _transform, emitterBounds);
}
BoundingBox::Merge(emitterBounds, bounds, bounds);
@@ -737,6 +737,5 @@ void ParticleEffect::OnTransformChanged()
// Base
Actor::OnTransformChanged();
_transform.GetWorld(_world);
UpdateBounds();
}

View File

@@ -179,7 +179,6 @@ public:
private:
uint64 _lastUpdateFrame;
Real _lastMinDstSqr;
Matrix _world;
int32 _sceneRenderingKey = -1;
uint32 _parametersVersion = 0; // Version number for _parameters to be in sync with Instance.ParametersVersion
Array<ParticleEffectParameter> _parameters; // Cached for scripting API
@@ -246,15 +245,6 @@ public:
API_FIELD(Attributes="EditorDisplay(\"Particle Effect\"), EditorOrder(75), DefaultValue(DrawPass.Default)")
DrawPass DrawModes = DrawPass::Default;
/// <summary>
/// Gets the actor world matrix transform.
/// </summary>
/// <param name="world">Result world matrix</param>
FORCE_INLINE void GetWorld(Matrix* world) const
{
*world = _world;
}
public:
/// <summary>
/// Gets the effect parameters collection. Those parameters are instanced from the <see cref="ParticleSystem"/> that contains a linear list of emitters and every emitter has a list of own parameters.

View File

@@ -362,7 +362,7 @@ Asset::LoadResult ParticleSystem::load()
continue;
#endif
EmittersParametersOverrides.Add(key, Variant(value));
EmittersParametersOverrides[key] = Variant(value);
}
}
@@ -441,7 +441,7 @@ Asset::LoadResult ParticleSystem::load()
continue;
#endif
EmittersParametersOverrides.Add(key, value);
EmittersParametersOverrides[key] = value;
}
}

View File

@@ -877,8 +877,9 @@ void Particles::DrawParticles(RenderContext& renderContext, ParticleEffect* effe
const auto drawModes = static_cast<DrawPass>(view.Pass & effect->DrawModes);
if (drawModes == DrawPass::None || SpriteRenderer.Init())
return;
Matrix world;
effect->GetWorld(&world);
Matrix worlds[2];
Matrix::Translation(-renderContext.View.Origin, worlds[0]); // World
renderContext.View.GetWorldMatrix(effect->GetTransform(), worlds[1]); // Local
const auto staticFlags = effect->GetStaticFlags();
// Draw lights
@@ -888,14 +889,15 @@ void Particles::DrawParticles(RenderContext& renderContext, ParticleEffect* effe
const auto buffer = emitterData.Buffer;
if (!buffer || (buffer->Mode == ParticlesSimulationMode::CPU && buffer->CPU.Count == 0))
continue;
auto emitter = buffer->Emitter;
buffer->Emitter->GraphExecutorCPU.Draw(buffer->Emitter, effect, emitterData, renderContext, world);
buffer->Emitter->GraphExecutorCPU.Draw(buffer->Emitter, effect, emitterData, renderContext, worlds[(int32)emitter->SimulationSpace]);
}
// Setup a draw call common data
DrawCall drawCall;
drawCall.PerInstanceRandom = effect->GetPerInstanceRandom();
drawCall.ObjectPosition = world.GetTranslation();
drawCall.ObjectPosition = effect->GetPosition();
// Draw all emitters
for (int32 emitterIndex = 0; emitterIndex < effect->Instance.Emitters.Count(); emitterIndex++)
@@ -906,7 +908,7 @@ void Particles::DrawParticles(RenderContext& renderContext, ParticleEffect* effe
continue;
auto emitter = buffer->Emitter;
drawCall.World = emitter->SimulationSpace == ParticlesSimulationSpace::World ? Matrix::Identity : world;
drawCall.World = worlds[(int32)emitter->SimulationSpace];
drawCall.WorldDeterminantSign = Math::FloatSelect(drawCall.World.RotDeterminant(), 1, -1);
drawCall.Particle.Particles = buffer;