diff --git a/data/shaders/alphatest_particle.vert b/data/shaders/alphatest_particle.vert index 742b9e961..515a5f327 100644 --- a/data/shaders/alphatest_particle.vert +++ b/data/shaders/alphatest_particle.vert @@ -1,12 +1,10 @@ -uniform vec3 color_from; -uniform vec3 color_to; uniform int flips; #ifdef Explicit_Attrib_Location_Usable layout(location = 0) in vec3 Position; -layout(location = 1) in float lifetime; -layout(location = 2) in float size; +layout(location = 1) in vec4 mixed_color; +layout(location = 2) in vec2 lifetime_and_size; layout(location = 3) in vec2 Texcoord; layout(location = 4) in vec2 quadcorner; @@ -15,8 +13,8 @@ layout(location = 6) in float anglespeed; #else in vec3 Position; -in float lifetime; -in float size; +in vec4 mixed_color; +in vec2 lifetime_and_size; in vec2 Texcoord; in vec2 quadcorner; @@ -29,24 +27,24 @@ out vec4 pc; void main(void) { - if (size == 0.0) + if (lifetime_and_size.y == 0.0) { gl_Position = vec4(0.); return; } tc = Texcoord; - pc = vec4(vec3(color_from + (color_to - color_from) * lifetime), 1.0); + pc = mixed_color.zyxw; #if !defined(sRGB_Framebuffer_Usable) && !defined(Advanced_Lighting_Enabled) - pc.rgb = pow(pc.rgb, vec3(1. / 2.2)); + pc.rgb = pow(pc.rgb, vec3(1.0 / 2.2)); #endif vec4 viewpos = vec4(0.); if (flips == 1) { - float angle = lifetime * anglespeed; + float angle = lifetime_and_size.x * anglespeed; float sin_a = sin(mod(angle / 2.0, 6.283185307179586)); float cos_a = cos(mod(angle / 2.0, 6.283185307179586)); vec4 quat = normalize(vec4(vec3(0.0, 1.0, 0.0) * sin_a, cos_a)); - vec3 newquadcorner = size * vec3(quadcorner, 0.); + vec3 newquadcorner = lifetime_and_size.y * vec3(quadcorner, 0.); newquadcorner = newquadcorner + 2.0 * cross(cross(newquadcorner, quat.xyz) + quat.w * newquadcorner, quat.xyz); viewpos = ViewMatrix * vec4(Position + newquadcorner, 1.0); @@ -54,7 +52,7 @@ void main(void) else { viewpos = ViewMatrix * vec4(Position, 1.0); - viewpos += size * vec4(quadcorner, 0., 0.); + viewpos += lifetime_and_size.y * vec4(quadcorner, 0., 0.); } gl_Position = ProjectionMatrix * viewpos; } diff --git a/data/shaders/simple_particle.vert b/data/shaders/simple_particle.vert index 0a10ccc0b..9e5057c5c 100644 --- a/data/shaders/simple_particle.vert +++ b/data/shaders/simple_particle.vert @@ -1,12 +1,10 @@ -uniform vec3 color_from; -uniform vec3 color_to; uniform int flips; #ifdef Explicit_Attrib_Location_Usable layout(location = 0) in vec3 Position; -layout(location = 1) in float lifetime; -layout(location = 2) in float size; +layout(location = 1) in vec4 mixed_color; +layout(location = 2) in vec2 lifetime_and_size; layout(location = 3) in vec2 Texcoord; layout(location = 4) in vec2 quadcorner; @@ -15,8 +13,8 @@ layout(location = 6) in float anglespeed; #else in vec3 Position; -in float lifetime; -in float size; +in vec4 mixed_color; +in vec2 lifetime_and_size; in vec2 Texcoord; in vec2 quadcorner; @@ -29,25 +27,24 @@ out vec4 pc; void main(void) { - if (size == 0.0) + if (lifetime_and_size.y == 0.0) { gl_Position = vec4(0.); return; } tc = Texcoord; - pc = vec4(vec3(color_from + (color_to - color_from) * lifetime), 1.0) * - smoothstep(1., 0.8, lifetime); + pc = mixed_color.zyxw * smoothstep(1.0, 0.8, lifetime_and_size.x); #if !defined(sRGB_Framebuffer_Usable) && !defined(Advanced_Lighting_Enabled) - pc.rgb = pow(pc.rgb, vec3(1. / 2.2)); + pc.rgb = pow(pc.rgb, vec3(1.0 / 2.2)); #endif vec4 viewpos = vec4(0.); if (flips == 1) { - float angle = lifetime * anglespeed; + float angle = lifetime_and_size.x * anglespeed; float sin_a = sin(mod(angle / 2.0, 6.283185307179586)); float cos_a = cos(mod(angle / 2.0, 6.283185307179586)); vec4 quat = normalize(vec4(vec3(0.0, 1.0, 0.0) * sin_a, cos_a)); - vec3 newquadcorner = size * vec3(quadcorner, 0.); + vec3 newquadcorner = lifetime_and_size.y * vec3(quadcorner, 0.); newquadcorner = newquadcorner + 2.0 * cross(cross(newquadcorner, quat.xyz) + quat.w * newquadcorner, quat.xyz); viewpos = ViewMatrix * vec4(Position + newquadcorner, 1.0); @@ -55,7 +52,7 @@ void main(void) else { viewpos = ViewMatrix * vec4(Position, 1.0); - viewpos += size * vec4(quadcorner, 0., 0.); + viewpos += lifetime_and_size.y * vec4(quadcorner, 0., 0.); } gl_Position = ProjectionMatrix * viewpos; } diff --git a/src/graphics/cpu_particle_manager.cpp b/src/graphics/cpu_particle_manager.cpp index 61e879abb..1daedb1ce 100644 --- a/src/graphics/cpu_particle_manager.cpp +++ b/src/graphics/cpu_particle_manager.cpp @@ -32,8 +32,7 @@ // ============================================================================ /** A Shader to render particles. */ -class ParticleRenderer : public TextureShader - +class ParticleRenderer : public TextureShader { public: ParticleRenderer() @@ -41,7 +40,7 @@ public: loadProgram(PARTICLES_RENDERING, GL_VERTEX_SHADER, "simple_particle.vert", GL_FRAGMENT_SHADER, "simple_particle.frag"); - assignUniforms("color_from", "color_to", "flips"); + assignUniforms("flips"); assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED, 1, "dtex", ST_NEAREST_FILTERED); } // ParticleRenderer @@ -51,7 +50,7 @@ public: /** A Shader to render alpha-test particles. */ class AlphaTestParticleRenderer : public TextureShader - + { public: AlphaTestParticleRenderer() @@ -59,7 +58,7 @@ public: loadProgram(PARTICLES_RENDERING, GL_VERTEX_SHADER, "alphatest_particle.vert", GL_FRAGMENT_SHADER, "alphatest_particle.frag"); - assignUniforms("color_from", "color_to", "flips"); + assignUniforms("flips"); assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); } // AlphaTestParticleRenderer }; // AlphaTestParticleRenderer @@ -164,10 +163,12 @@ void CPUParticleManager::uploadAll() glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 20, 0); glVertexAttribDivisorARB(0, 1); glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 20, (void*)12); + glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, 20, + (void*)12); glVertexAttribDivisorARB(1, 1); glEnableVertexAttribArray(2); - glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, 20, (void*)16); + glVertexAttribPointer(2, 2, GL_HALF_FLOAT, GL_FALSE, 20, + (void*)16); glVertexAttribDivisorARB(2, 1); bool flips = false; for (unsigned i = 0; i < m_particles_queue[p.first].size(); i++) @@ -282,17 +283,13 @@ void CPUParticleManager::drawAll() ParticleRenderer::getInstance()->setTextureUnits (cur_mat->getTexture()->getOpenGLTextureName(), irr_driver->getDepthStencilTexture()); - ParticleRenderer::getInstance()->setUniforms( - m_particles_queue.at(p.second)[0]->getColorFrom(), - m_particles_queue.at(p.second)[0]->getColorTo(), flips); + ParticleRenderer::getInstance()->setUniforms(flips); } else { AlphaTestParticleRenderer::getInstance()->setTextureUnits (cur_mat->getTexture()->getOpenGLTextureName()); - AlphaTestParticleRenderer::getInstance()->setUniforms( - m_particles_queue.at(p.second)[0]->getColorFrom(), - m_particles_queue.at(p.second)[0]->getColorTo(), flips); + AlphaTestParticleRenderer::getInstance()->setUniforms(flips); } glBindVertexArray(std::get<0>(m_gl_particles[p.second])); glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, diff --git a/src/graphics/cpu_particle_manager.hpp b/src/graphics/cpu_particle_manager.hpp index 2c5ddb9ab..24e5d4cc2 100644 --- a/src/graphics/cpu_particle_manager.hpp +++ b/src/graphics/cpu_particle_manager.hpp @@ -21,6 +21,7 @@ #ifndef SERVER_ONLY #include "graphics/gl_headers.hpp" +#include "utils/mini_glm.hpp" #include "utils/no_copy.hpp" #include "utils/singleton.hpp" @@ -39,11 +40,21 @@ using namespace irr; struct CPUParticle { core::vector3df m_position; - float m_lifetime; - float m_size; + video::SColor m_mixed_color; + short m_lifetime_and_size[2]; // ------------------------------------------------------------------------ - CPUParticle(const core::vector3df& position, float lifetime, float size) - : m_position(position), m_lifetime(lifetime), m_size(size) {} + CPUParticle(const core::vector3df& position, + const core::vector3df& color_from, + const core::vector3df& color_to, float lifetime, float size) + : m_position(position), m_mixed_color(-1) + { + core::vector3df ret = color_from + (color_to - color_from) * lifetime; + m_mixed_color.setRed(core::clamp((int)(ret.X * 255.0f), 0, 255)); + m_mixed_color.setBlue(core::clamp((int)(ret.Y * 255.0f), 0, 255)); + m_mixed_color.setGreen(core::clamp((int)(ret.Z * 255.0f), 0, 255)); + m_lifetime_and_size[0] = MiniGLM::toFloat16(lifetime); + m_lifetime_and_size[1] = MiniGLM::toFloat16(size); + } }; class STKParticle; diff --git a/src/graphics/shader.cpp b/src/graphics/shader.cpp index 97ab03377..fe1a8d9ab 100644 --- a/src/graphics/shader.cpp +++ b/src/graphics/shader.cpp @@ -156,15 +156,16 @@ void ShaderBase::setAttribute(AttributeType type) glBindAttribLocation(m_program, 5, "lifetime_initial"); glBindAttribLocation(m_program, 6, "particle_velocity_initial"); glBindAttribLocation(m_program, 7, "size_initial"); - if (CVS->needsVertexIdWorkaround()) { glBindAttribLocation(m_program, 8, "vertex_id"); } break; case PARTICLES_RENDERING: - glBindAttribLocation(m_program, 1, "lifetime"); - glBindAttribLocation(m_program, 2, "size"); + glBindAttribLocation(m_program, 0, "Position"); + glBindAttribLocation(m_program, 1, "mixed_color"); + glBindAttribLocation(m_program, 2, "lifetime_and_size"); + glBindAttribLocation(m_program, 3, "Texcoord"); glBindAttribLocation(m_program, 4, "quadcorner"); glBindAttribLocation(m_program, 5, "rotationvec"); glBindAttribLocation(m_program, 6, "anglespeed"); diff --git a/src/graphics/stk_particle.cpp b/src/graphics/stk_particle.cpp index 2e8f2ce13..de7763444 100644 --- a/src/graphics/stk_particle.cpp +++ b/src/graphics/stk_particle.cpp @@ -57,7 +57,7 @@ STKParticle::STKParticle(bool createDefaultEmitter, position, rotation, scale) { m_hm = NULL; - m_color_to = video::SColorf(video::SColor(-1)); + m_color_to = core::vector3df(1.0f); m_color_from = m_color_to; m_size_increase_factor = 0.0f; m_first_execution = true; @@ -358,8 +358,8 @@ void STKParticle::stimulateHeightMap(float dt, unsigned int active_count, } if (out != NULL) { - out->emplace_back(new_particle_position, new_lifetime, - new_size); + out->emplace_back(new_particle_position, m_color_from, + m_color_to, new_lifetime, new_size); } } } @@ -463,8 +463,8 @@ void STKParticle::stimulateNormal(float dt, unsigned int active_count, } if (out != NULL) { - out->emplace_back(new_particle_position, new_lifetime, - new_size); + out->emplace_back(new_particle_position, m_color_from, + m_color_to, new_lifetime, new_size); } } } diff --git a/src/graphics/stk_particle.hpp b/src/graphics/stk_particle.hpp index 89c21dcdd..64d172623 100644 --- a/src/graphics/stk_particle.hpp +++ b/src/graphics/stk_particle.hpp @@ -59,7 +59,7 @@ private: std::vector m_particles_generating, m_initial_particles; - video::SColorf m_color_from, m_color_to; + core::vector3df m_color_from, m_color_to; float m_size_increase_factor; @@ -109,22 +109,18 @@ public: // ------------------------------------------------------------------------ void setColorFrom(float r, float g, float b) { - m_color_from.r = r; - m_color_from.g = g; - m_color_from.b = b; + m_color_from.X = r; + m_color_from.Y = g; + m_color_from.Z = b; } // ------------------------------------------------------------------------ void setColorTo(float r, float g, float b) { - m_color_to.r = r; - m_color_to.g = g; - m_color_to.b = b; + m_color_to.X = r; + m_color_to.Y = g; + m_color_to.Z = b; } // ------------------------------------------------------------------------ - const video::SColorf getColorFrom() const { return m_color_from; } - // ------------------------------------------------------------------------ - const video::SColorf getColorTo() const { return m_color_to; } - // ------------------------------------------------------------------------ virtual void setEmitter(scene::IParticleEmitter* emitter); // ------------------------------------------------------------------------ virtual void render() {}