From a6b9078c214967379e52be6f0e1a841971ea25e3 Mon Sep 17 00:00:00 2001 From: Andreas Ortmann Date: Fri, 30 Sep 2016 21:24:06 +0200 Subject: [PATCH] very nice particles with heat in the center of the explosion and moving in 3d space. --- data/shader/particle.frag | 17 ++++++-- data/shader/particle.vert | 39 ++++++++++++------- game/renderer_polygon_3d/particle_batch.cpp | 26 ++++++++++--- game/renderer_polygon_3d/particle_batch.hpp | 12 ++++-- .../renderer_polygon_3d.cpp | 39 +++++++++++++------ .../renderer_polygon_3d.hpp | 1 + 6 files changed, 97 insertions(+), 37 deletions(-) diff --git a/data/shader/particle.frag b/data/shader/particle.frag index 66a59ab..c6a381f 100644 --- a/data/shader/particle.frag +++ b/data/shader/particle.frag @@ -1,8 +1,11 @@ #version 120 -varying vec2 vertex; -varying vec2 velocity; +varying vec2 vertex; +varying vec3 velocity; varying float decay; +varying float explCenterDist; +uniform vec3 explCenter; + vec3 hsv2rgb(vec3 c) { vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); @@ -17,10 +20,16 @@ void main() if (r > 1.0) { discard; } - float d = decay; + + float d = decay/(1.0+max(0.0, 1.0-explCenterDist)); float h = (1.0-d)/6.0; - float v = max(0.0, (1.0-d/2.0) - 0.1*(d*d*d)); + float v = max(0.0, (1.0-log(d))); float s = 1.0; + + //v /= decay * 10.0*length(vertex-explCenter); + //v /= 1.0+2.0*length(vertex-explCenter); + v /= 1.0 + max(0.0, min(35.0*(decay-0.2), 1.0)) * 15.0 * explCenterDist; + gl_FragColor = vec4(hsv2rgb(vec3(h, s, v)), 1.0); //gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0); diff --git a/data/shader/particle.vert b/data/shader/particle.vert index bf64a62..f4ef9da 100644 --- a/data/shader/particle.vert +++ b/data/shader/particle.vert @@ -1,26 +1,37 @@ #version 120 attribute vec2 in_vertex; -attribute vec2 in_position; -attribute vec2 in_velocity; +attribute vec3 in_position; +attribute vec3 in_velocity; -uniform float maxAge; -varying float decay; -varying vec2 velocity; -varying vec2 vertex; -uniform float time; +uniform float age; uniform float size; +uniform float maxVelocity; +uniform float maxAge; +uniform vec3 explCenter; + +varying float decay; +varying vec3 velocity; +varying vec2 vertex; +varying float explCenterDist; + +// TODO: rotate to face the user! void main() { - //decay = min(1.0, time+5.0*length(velocity)) / maxAge; + //decay = min(1.0, age+5.0*length(velocity)) / maxAge; //decay = max(decay*decay, sqrt(decay)); - decay = time / maxAge; + decay = age / maxAge; + // faster particles are smaller + float s = size * (1.0-length(in_velocity)/maxVelocity); vec2 base = in_vertex; - vec2 p = size*base; - p += log(1.0+time) * in_velocity; - p += in_position; - gl_Position = vec4(p, 0.0, 1.0); + vec3 p = s*vec3(base, 0.0); + vec3 offset = log(1.0+age) * in_velocity + in_position; + p += offset; - vertex = base; + gl_Position = vec4(p, 1.0); + + vertex = base.xy; velocity = in_velocity; + + explCenterDist = length(explCenter-offset); } \ No newline at end of file diff --git a/game/renderer_polygon_3d/particle_batch.cpp b/game/renderer_polygon_3d/particle_batch.cpp index 8198b97..b9ac890 100644 --- a/game/renderer_polygon_3d/particle_batch.cpp +++ b/game/renderer_polygon_3d/particle_batch.cpp @@ -17,6 +17,8 @@ namespace endofthejedi { , m_particleRadius(particleSize) , m_maxAge(maxAge) , m_age(0.0) + , m_maxVelocity(1.0) + , m_center(glm::vec3(0.0f, 0.0f, 0.0f)) // 2d quad drawn as a triangle fan , m_data_quad({ @@ -61,7 +63,17 @@ namespace endofthejedi { glDeleteBuffers(5, m_data_vbos); } - void ParticleBatch::setParticle(size_t index, const glm::vec2 &p, const glm::vec2 &v) + void ParticleBatch::setCenter(const glm::vec3 ¢er) + { + m_center = center; + } + + void ParticleBatch::setMaxVelocity(float maxVelocity) + { + m_maxVelocity = maxVelocity; + } + + void ParticleBatch::setParticle(size_t index, const glm::vec3 &p, const glm::vec3 &v) { if (index >= m_numParticles) { return; @@ -123,9 +135,11 @@ namespace endofthejedi { //std::cout<<"[ParticleBatch] render " << std::endl; m_shader.bind(); - glUniform1f(m_shader.location("time"), m_age); - glUniform1f(m_shader.location("maxAge"), m_maxAge); - glUniform1f(m_shader.location("size"), m_particleRadius); + glUniform1f(m_shader.location("age"), m_age); + glUniform1f(m_shader.location("maxVelocity"), m_maxVelocity); + glUniform1f(m_shader.location("maxAge"), m_maxAge); + glUniform1f(m_shader.location("size"), m_particleRadius); + glUniform3f(m_shader.location("center"), m_center.x, m_center.y, m_center.z); bind(); @@ -155,9 +169,11 @@ namespace endofthejedi { { switch(i) { case 0: + return 2; + case 1: case 2: - return 2; + return 3; case 3: case 4: diff --git a/game/renderer_polygon_3d/particle_batch.hpp b/game/renderer_polygon_3d/particle_batch.hpp index a75ffe7..004a82f 100644 --- a/game/renderer_polygon_3d/particle_batch.hpp +++ b/game/renderer_polygon_3d/particle_batch.hpp @@ -3,6 +3,7 @@ #include #include +#include #include "glclasses.hpp" @@ -16,7 +17,10 @@ namespace endofthejedi { size_t numParticles() const { return m_numParticles; } - void setParticle(size_t index, const glm::vec2 &p, const glm::vec2 &v); + void setParticle(size_t index, const glm::vec3 &p, const glm::vec3 &v); + + void setCenter(const glm::vec3 ¢er); + void setMaxVelocity(float maxVelocity); void bind(); void upload(); @@ -39,12 +43,14 @@ namespace endofthejedi { float m_particleRadius; const float m_maxAge; float m_age; + float m_maxVelocity; + glm::vec3 m_center; GLuint m_data_vbos[5]; std::vector m_data_quad; - std::vector m_data_position; - std::vector m_data_velocity; + std::vector m_data_position; + std::vector m_data_velocity; std::vector m_data_kind; std::vector m_data_max_age; diff --git a/game/renderer_polygon_3d/renderer_polygon_3d.cpp b/game/renderer_polygon_3d/renderer_polygon_3d.cpp index a449262..890fea5 100644 --- a/game/renderer_polygon_3d/renderer_polygon_3d.cpp +++ b/game/renderer_polygon_3d/renderer_polygon_3d.cpp @@ -5,6 +5,7 @@ #include #include #include +#include namespace endofthejedi { void RendererPolygon3d::setup() @@ -54,11 +55,13 @@ namespace endofthejedi { m_shader.bind(); - glm::vec3 c = glm::vec3(1.0, 1.0, 0.5); + // TODO: add ONE sun planet + // TODO: add lights for explosions + + glm::vec3 c = glm::vec3(1.0, 1.0, 0.8); glUniform3f(m_shader.location("lightColor"), c.x, c.y, c.z); - //glm::vec3 p = glm::vec3(1.0, 0.0, 0.0); - glm::vec3 p = glm::vec3(0.5f, 0.5f, -4.0f); + glm::vec3 p = glm::vec3(0.3f, 0.4f, 0.0f); glUniform3f(m_shader.location("lightPosition"), p.x, p.y, p.z); renderPlanets(); @@ -91,20 +94,34 @@ namespace endofthejedi { void RendererPolygon3d::addExplosionEffect(size_t id, const glm::vec2 &pos, size_t n, float duration) { //float particleRadius = 0.005; - float particleRadius = 0.005; + //float particleRadius = 0.003; + float particleRadius = 0.01; + + // TODO: use this as shader input too and make the area 2x around this + // so that it stays hot/yellow for 2/3 of the time + float explSize = 0.01f; + + float maxVelocity = 0.2f; ParticleBatch *batch = new ParticleBatch(id, n, particleRadius, duration); + batch->setCenter(glm::vec3(pos, 0.0)); + batch->setMaxVelocity(maxVelocity); for (size_t i=0; isetParticle(i, pos, v); + batch->setParticle(i, glm::vec3(pos, 0.0) + glm::ballRand(explSize), v); } batch->upload(); @@ -124,13 +141,13 @@ namespace endofthejedi { } if (!gotIt) { - addExplosionEffect(expl->id, expl->position, 1000, 2.0); + addExplosionEffect(expl->id, expl->position, 500, 5.0); } } - //if (m_particles.size() == 0) { - // addExplosionEffect(0, glm::vec2(0.0, 0.0), 1000, 2.0); - //} + if (m_particles.size() == 0) { + addExplosionEffect(0, glm::vec2(0.0, 0.0), 1000, 5.0); + } std::vector rm; diff --git a/game/renderer_polygon_3d/renderer_polygon_3d.hpp b/game/renderer_polygon_3d/renderer_polygon_3d.hpp index 5f86483..bfb19f7 100644 --- a/game/renderer_polygon_3d/renderer_polygon_3d.hpp +++ b/game/renderer_polygon_3d/renderer_polygon_3d.hpp @@ -17,6 +17,7 @@ #include "particle_batch.hpp" #include "polygon_model.hpp" +#include #include namespace endofthejedi {