Pack mixed color into instanced array

With half-floats for lifetime and size for same stride
This commit is contained in:
Benau 2017-10-14 12:33:08 +08:00
parent e49a7139d7
commit a0c9ba2b8c
7 changed files with 61 additions and 61 deletions

View File

@ -1,12 +1,10 @@
uniform vec3 color_from;
uniform vec3 color_to;
uniform int flips; uniform int flips;
#ifdef Explicit_Attrib_Location_Usable #ifdef Explicit_Attrib_Location_Usable
layout(location = 0) in vec3 Position; layout(location = 0) in vec3 Position;
layout(location = 1) in float lifetime; layout(location = 1) in vec4 mixed_color;
layout(location = 2) in float size; layout(location = 2) in vec2 lifetime_and_size;
layout(location = 3) in vec2 Texcoord; layout(location = 3) in vec2 Texcoord;
layout(location = 4) in vec2 quadcorner; layout(location = 4) in vec2 quadcorner;
@ -15,8 +13,8 @@ layout(location = 6) in float anglespeed;
#else #else
in vec3 Position; in vec3 Position;
in float lifetime; in vec4 mixed_color;
in float size; in vec2 lifetime_and_size;
in vec2 Texcoord; in vec2 Texcoord;
in vec2 quadcorner; in vec2 quadcorner;
@ -29,24 +27,24 @@ out vec4 pc;
void main(void) void main(void)
{ {
if (size == 0.0) if (lifetime_and_size.y == 0.0)
{ {
gl_Position = vec4(0.); gl_Position = vec4(0.);
return; return;
} }
tc = Texcoord; 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) #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 #endif
vec4 viewpos = vec4(0.); vec4 viewpos = vec4(0.);
if (flips == 1) 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 sin_a = sin(mod(angle / 2.0, 6.283185307179586));
float cos_a = cos(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)); 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, newquadcorner = newquadcorner + 2.0 * cross(cross(newquadcorner,
quat.xyz) + quat.w * newquadcorner, quat.xyz); quat.xyz) + quat.w * newquadcorner, quat.xyz);
viewpos = ViewMatrix * vec4(Position + newquadcorner, 1.0); viewpos = ViewMatrix * vec4(Position + newquadcorner, 1.0);
@ -54,7 +52,7 @@ void main(void)
else else
{ {
viewpos = ViewMatrix * vec4(Position, 1.0); 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; gl_Position = ProjectionMatrix * viewpos;
} }

View File

@ -1,12 +1,10 @@
uniform vec3 color_from;
uniform vec3 color_to;
uniform int flips; uniform int flips;
#ifdef Explicit_Attrib_Location_Usable #ifdef Explicit_Attrib_Location_Usable
layout(location = 0) in vec3 Position; layout(location = 0) in vec3 Position;
layout(location = 1) in float lifetime; layout(location = 1) in vec4 mixed_color;
layout(location = 2) in float size; layout(location = 2) in vec2 lifetime_and_size;
layout(location = 3) in vec2 Texcoord; layout(location = 3) in vec2 Texcoord;
layout(location = 4) in vec2 quadcorner; layout(location = 4) in vec2 quadcorner;
@ -15,8 +13,8 @@ layout(location = 6) in float anglespeed;
#else #else
in vec3 Position; in vec3 Position;
in float lifetime; in vec4 mixed_color;
in float size; in vec2 lifetime_and_size;
in vec2 Texcoord; in vec2 Texcoord;
in vec2 quadcorner; in vec2 quadcorner;
@ -29,25 +27,24 @@ out vec4 pc;
void main(void) void main(void)
{ {
if (size == 0.0) if (lifetime_and_size.y == 0.0)
{ {
gl_Position = vec4(0.); gl_Position = vec4(0.);
return; return;
} }
tc = Texcoord; tc = Texcoord;
pc = vec4(vec3(color_from + (color_to - color_from) * lifetime), 1.0) * pc = mixed_color.zyxw * smoothstep(1.0, 0.8, lifetime_and_size.x);
smoothstep(1., 0.8, lifetime);
#if !defined(sRGB_Framebuffer_Usable) && !defined(Advanced_Lighting_Enabled) #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 #endif
vec4 viewpos = vec4(0.); vec4 viewpos = vec4(0.);
if (flips == 1) 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 sin_a = sin(mod(angle / 2.0, 6.283185307179586));
float cos_a = cos(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)); 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, newquadcorner = newquadcorner + 2.0 * cross(cross(newquadcorner,
quat.xyz) + quat.w * newquadcorner, quat.xyz); quat.xyz) + quat.w * newquadcorner, quat.xyz);
viewpos = ViewMatrix * vec4(Position + newquadcorner, 1.0); viewpos = ViewMatrix * vec4(Position + newquadcorner, 1.0);
@ -55,7 +52,7 @@ void main(void)
else else
{ {
viewpos = ViewMatrix * vec4(Position, 1.0); 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; gl_Position = ProjectionMatrix * viewpos;
} }

View File

@ -32,8 +32,7 @@
// ============================================================================ // ============================================================================
/** A Shader to render particles. /** A Shader to render particles.
*/ */
class ParticleRenderer : public TextureShader class ParticleRenderer : public TextureShader<ParticleRenderer, 2, int>
<ParticleRenderer, 2, video::SColorf, video::SColorf, int>
{ {
public: public:
ParticleRenderer() ParticleRenderer()
@ -41,7 +40,7 @@ public:
loadProgram(PARTICLES_RENDERING, loadProgram(PARTICLES_RENDERING,
GL_VERTEX_SHADER, "simple_particle.vert", GL_VERTEX_SHADER, "simple_particle.vert",
GL_FRAGMENT_SHADER, "simple_particle.frag"); GL_FRAGMENT_SHADER, "simple_particle.frag");
assignUniforms("color_from", "color_to", "flips"); assignUniforms("flips");
assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED, assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED,
1, "dtex", ST_NEAREST_FILTERED); 1, "dtex", ST_NEAREST_FILTERED);
} // ParticleRenderer } // ParticleRenderer
@ -51,7 +50,7 @@ public:
/** A Shader to render alpha-test particles. /** A Shader to render alpha-test particles.
*/ */
class AlphaTestParticleRenderer : public TextureShader class AlphaTestParticleRenderer : public TextureShader
<AlphaTestParticleRenderer, 1, video::SColorf, video::SColorf, int> <AlphaTestParticleRenderer, 1, int>
{ {
public: public:
AlphaTestParticleRenderer() AlphaTestParticleRenderer()
@ -59,7 +58,7 @@ public:
loadProgram(PARTICLES_RENDERING, loadProgram(PARTICLES_RENDERING,
GL_VERTEX_SHADER, "alphatest_particle.vert", GL_VERTEX_SHADER, "alphatest_particle.vert",
GL_FRAGMENT_SHADER, "alphatest_particle.frag"); GL_FRAGMENT_SHADER, "alphatest_particle.frag");
assignUniforms("color_from", "color_to", "flips"); assignUniforms("flips");
assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED); assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED);
} // AlphaTestParticleRenderer } // AlphaTestParticleRenderer
}; // AlphaTestParticleRenderer }; // AlphaTestParticleRenderer
@ -164,10 +163,12 @@ void CPUParticleManager::uploadAll()
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 20, 0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 20, 0);
glVertexAttribDivisorARB(0, 1); glVertexAttribDivisorARB(0, 1);
glEnableVertexAttribArray(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); glVertexAttribDivisorARB(1, 1);
glEnableVertexAttribArray(2); 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); glVertexAttribDivisorARB(2, 1);
bool flips = false; bool flips = false;
for (unsigned i = 0; i < m_particles_queue[p.first].size(); i++) for (unsigned i = 0; i < m_particles_queue[p.first].size(); i++)
@ -282,17 +283,13 @@ void CPUParticleManager::drawAll()
ParticleRenderer::getInstance()->setTextureUnits ParticleRenderer::getInstance()->setTextureUnits
(cur_mat->getTexture()->getOpenGLTextureName(), (cur_mat->getTexture()->getOpenGLTextureName(),
irr_driver->getDepthStencilTexture()); irr_driver->getDepthStencilTexture());
ParticleRenderer::getInstance()->setUniforms( ParticleRenderer::getInstance()->setUniforms(flips);
m_particles_queue.at(p.second)[0]->getColorFrom(),
m_particles_queue.at(p.second)[0]->getColorTo(), flips);
} }
else else
{ {
AlphaTestParticleRenderer::getInstance()->setTextureUnits AlphaTestParticleRenderer::getInstance()->setTextureUnits
(cur_mat->getTexture()->getOpenGLTextureName()); (cur_mat->getTexture()->getOpenGLTextureName());
AlphaTestParticleRenderer::getInstance()->setUniforms( AlphaTestParticleRenderer::getInstance()->setUniforms(flips);
m_particles_queue.at(p.second)[0]->getColorFrom(),
m_particles_queue.at(p.second)[0]->getColorTo(), flips);
} }
glBindVertexArray(std::get<0>(m_gl_particles[p.second])); glBindVertexArray(std::get<0>(m_gl_particles[p.second]));
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4,

View File

@ -21,6 +21,7 @@
#ifndef SERVER_ONLY #ifndef SERVER_ONLY
#include "graphics/gl_headers.hpp" #include "graphics/gl_headers.hpp"
#include "utils/mini_glm.hpp"
#include "utils/no_copy.hpp" #include "utils/no_copy.hpp"
#include "utils/singleton.hpp" #include "utils/singleton.hpp"
@ -39,11 +40,21 @@ using namespace irr;
struct CPUParticle struct CPUParticle
{ {
core::vector3df m_position; core::vector3df m_position;
float m_lifetime; video::SColor m_mixed_color;
float m_size; short m_lifetime_and_size[2];
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
CPUParticle(const core::vector3df& position, float lifetime, float size) CPUParticle(const core::vector3df& position,
: m_position(position), m_lifetime(lifetime), m_size(size) {} 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; class STKParticle;

View File

@ -156,15 +156,16 @@ void ShaderBase::setAttribute(AttributeType type)
glBindAttribLocation(m_program, 5, "lifetime_initial"); glBindAttribLocation(m_program, 5, "lifetime_initial");
glBindAttribLocation(m_program, 6, "particle_velocity_initial"); glBindAttribLocation(m_program, 6, "particle_velocity_initial");
glBindAttribLocation(m_program, 7, "size_initial"); glBindAttribLocation(m_program, 7, "size_initial");
if (CVS->needsVertexIdWorkaround()) if (CVS->needsVertexIdWorkaround())
{ {
glBindAttribLocation(m_program, 8, "vertex_id"); glBindAttribLocation(m_program, 8, "vertex_id");
} }
break; break;
case PARTICLES_RENDERING: case PARTICLES_RENDERING:
glBindAttribLocation(m_program, 1, "lifetime"); glBindAttribLocation(m_program, 0, "Position");
glBindAttribLocation(m_program, 2, "size"); 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, 4, "quadcorner");
glBindAttribLocation(m_program, 5, "rotationvec"); glBindAttribLocation(m_program, 5, "rotationvec");
glBindAttribLocation(m_program, 6, "anglespeed"); glBindAttribLocation(m_program, 6, "anglespeed");

View File

@ -57,7 +57,7 @@ STKParticle::STKParticle(bool createDefaultEmitter,
position, rotation, scale) position, rotation, scale)
{ {
m_hm = NULL; 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_color_from = m_color_to;
m_size_increase_factor = 0.0f; m_size_increase_factor = 0.0f;
m_first_execution = true; m_first_execution = true;
@ -358,8 +358,8 @@ void STKParticle::stimulateHeightMap(float dt, unsigned int active_count,
} }
if (out != NULL) if (out != NULL)
{ {
out->emplace_back(new_particle_position, new_lifetime, out->emplace_back(new_particle_position, m_color_from,
new_size); m_color_to, new_lifetime, new_size);
} }
} }
} }
@ -463,8 +463,8 @@ void STKParticle::stimulateNormal(float dt, unsigned int active_count,
} }
if (out != NULL) if (out != NULL)
{ {
out->emplace_back(new_particle_position, new_lifetime, out->emplace_back(new_particle_position, m_color_from,
new_size); m_color_to, new_lifetime, new_size);
} }
} }
} }

View File

@ -59,7 +59,7 @@ private:
std::vector<ParticleData> m_particles_generating, m_initial_particles; std::vector<ParticleData> 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; float m_size_increase_factor;
@ -109,22 +109,18 @@ public:
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void setColorFrom(float r, float g, float b) void setColorFrom(float r, float g, float b)
{ {
m_color_from.r = r; m_color_from.X = r;
m_color_from.g = g; m_color_from.Y = g;
m_color_from.b = b; m_color_from.Z = b;
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void setColorTo(float r, float g, float b) void setColorTo(float r, float g, float b)
{ {
m_color_to.r = r; m_color_to.X = r;
m_color_to.g = g; m_color_to.Y = g;
m_color_to.b = b; 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 setEmitter(scene::IParticleEmitter* emitter);
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
virtual void render() {} virtual void render() {}