From 8aa5ee92caf5b8278653985276503b759dfb2e97 Mon Sep 17 00:00:00 2001 From: Vsevolod Kremianskii Date: Sun, 16 May 2021 14:34:08 +0700 Subject: [PATCH] Fix particle animation --- src/engine/scene/node/emitternode.cpp | 109 +++++++++++++------------- src/engine/scene/node/emitternode.h | 6 +- 2 files changed, 56 insertions(+), 59 deletions(-) diff --git a/src/engine/scene/node/emitternode.cpp b/src/engine/scene/node/emitternode.cpp index 0882378e..5a31c36e 100644 --- a/src/engine/scene/node/emitternode.cpp +++ b/src/engine/scene/node/emitternode.cpp @@ -133,66 +133,14 @@ void EmitterSceneNode::doSpawnParticle() { float velocity = sign * (_velocity + random(0.0f, _randomVelocity)); auto particle = make_shared(); + particle->emitter = this; particle->position = move(position); particle->velocity = velocity; - particle->emitter = this; - _particles.push_back(particle); -} - -void EmitterSceneNode::drawParticles(const vector &particles) { - if (particles.empty()) return; - - shared_ptr emitter(_modelNode->emitter()); - shared_ptr texture(emitter->texture); - if (!texture) return; - - ShaderUniforms uniforms(_sceneGraph->uniformsPrototype()); - uniforms.combined.featureMask |= UniformFeatureFlags::particles; - uniforms.particles->gridSize = glm::vec2(emitter->gridWidth, emitter->gridHeight); - uniforms.particles->render = static_cast(emitter->renderMode); - - for (size_t i = 0; i < particles.size(); ++i) { - const Particle &particle = *particles[i]; - - glm::mat4 transform(_absTransform); - transform = glm::translate(transform, particles[i]->position); - if (emitter->renderMode == ModelNode::Emitter::RenderMode::MotionBlur) { - transform = glm::scale(transform, glm::vec3((1.0f + kMotionBlurStrength * kProjectileSpeed) * particle.size, particle.size, particle.size)); - } else { - transform = glm::scale(transform, glm::vec3(particle.size)); - } - - uniforms.particles->particles[i].transform = move(transform); - uniforms.particles->particles[i].color = glm::vec4(particle.color, 1.0f); - uniforms.particles->particles[i].size = glm::vec2(particle.size); - uniforms.particles->particles[i].alpha = particle.alpha; - uniforms.particles->particles[i].frame = particle.frame; - } - - Shaders::instance().activate(ShaderProgram::ParticleParticle, uniforms); - - StateManager::instance().setActiveTextureUnit(TextureUnits::diffuseMap); - texture->bind(); - - bool lighten = emitter->blendMode == ModelNode::Emitter::BlendMode::Lighten; - if (lighten) { - StateManager::instance().withLightenBlending([&particles]() { - Meshes::instance().getBillboard()->drawInstanced(static_cast(particles.size())); - }); - } else { - Meshes::instance().getBillboard()->drawInstanced(static_cast(particles.size())); - } -} - -void EmitterSceneNode::detonate() { - doSpawnParticle(); -} - -void EmitterSceneNode::initParticle(Particle &particle) { + particle->frame = _frameStart; if (_fps > 0.0f) { - particle.animLength = (_frameEnd - _frameStart + 1) / _fps; + particle->animLength = (_frameEnd - _frameStart + 1) / _fps; } - particle.frame = _frameStart; + _particles.push_back(particle); } void EmitterSceneNode::updateParticle(Particle &particle, float dt) { @@ -243,6 +191,55 @@ void EmitterSceneNode::updateParticleAnimation(Particle &particle, float dt) { particle.alpha = interpolateConstraints(_alpha, maturity); } +void EmitterSceneNode::detonate() { + doSpawnParticle(); +} + +void EmitterSceneNode::drawParticles(const vector &particles) { + if (particles.empty()) return; + + shared_ptr emitter(_modelNode->emitter()); + shared_ptr texture(emitter->texture); + if (!texture) return; + + ShaderUniforms uniforms(_sceneGraph->uniformsPrototype()); + uniforms.combined.featureMask |= UniformFeatureFlags::particles; + uniforms.particles->gridSize = glm::vec2(emitter->gridWidth, emitter->gridHeight); + uniforms.particles->render = static_cast(emitter->renderMode); + + for (size_t i = 0; i < particles.size(); ++i) { + const Particle &particle = *particles[i]; + + glm::mat4 transform(_absTransform); + transform = glm::translate(transform, particles[i]->position); + if (emitter->renderMode == ModelNode::Emitter::RenderMode::MotionBlur) { + transform = glm::scale(transform, glm::vec3((1.0f + kMotionBlurStrength * kProjectileSpeed) * particle.size, particle.size, particle.size)); + } else { + transform = glm::scale(transform, glm::vec3(particle.size)); + } + + uniforms.particles->particles[i].transform = move(transform); + uniforms.particles->particles[i].color = glm::vec4(particle.color, 1.0f); + uniforms.particles->particles[i].size = glm::vec2(particle.size); + uniforms.particles->particles[i].alpha = particle.alpha; + uniforms.particles->particles[i].frame = particle.frame; + } + + Shaders::instance().activate(ShaderProgram::ParticleParticle, uniforms); + + StateManager::instance().setActiveTextureUnit(TextureUnits::diffuseMap); + texture->bind(); + + bool lighten = emitter->blendMode == ModelNode::Emitter::BlendMode::Lighten; + if (lighten) { + StateManager::instance().withLightenBlending([&particles]() { + Meshes::instance().getBillboard()->drawInstanced(static_cast(particles.size())); + }); + } else { + Meshes::instance().getBillboard()->drawInstanced(static_cast(particles.size())); + } +} + } // namespace scene } // namespace reone diff --git a/src/engine/scene/node/emitternode.h b/src/engine/scene/node/emitternode.h index 2ea726c5..b00fc540 100644 --- a/src/engine/scene/node/emitternode.h +++ b/src/engine/scene/node/emitternode.h @@ -31,14 +31,14 @@ class ModelSceneNode; class EmitterSceneNode : public ModelNodeSceneNode { public: struct Particle { - glm::vec3 position { 0.0f }; - float velocity { 0.0f }; EmitterSceneNode *emitter { nullptr }; + glm::vec3 position { 0.0f }; + glm::vec3 color { 1.0f }; + float velocity { 0.0f }; float animLength { 0.0f }; float lifetime { 0.0f }; int frame { 0 }; float size { 1.0f }; - glm::vec3 color { 1.0f }; float alpha { 1.0f }; };