very nice particles with heat in the center of the explosion and moving in 3d space.

This commit is contained in:
Andreas Ortmann 2016-09-30 21:24:06 +02:00
parent 067cfb6203
commit a6b9078c21
6 changed files with 97 additions and 37 deletions

View file

@ -1,8 +1,11 @@
#version 120 #version 120
varying vec2 vertex; varying vec2 vertex;
varying vec2 velocity; varying vec3 velocity;
varying float decay; varying float decay;
varying float explCenterDist;
uniform vec3 explCenter;
vec3 hsv2rgb(vec3 c) vec3 hsv2rgb(vec3 c)
{ {
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); 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) { if (r > 1.0) {
discard; discard;
} }
float d = decay;
float d = decay/(1.0+max(0.0, 1.0-explCenterDist));
float h = (1.0-d)/6.0; 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; 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(hsv2rgb(vec3(h, s, v)), 1.0);
//gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0); //gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);

View file

@ -1,26 +1,37 @@
#version 120 #version 120
attribute vec2 in_vertex; attribute vec2 in_vertex;
attribute vec2 in_position; attribute vec3 in_position;
attribute vec2 in_velocity; attribute vec3 in_velocity;
uniform float maxAge; uniform float age;
varying float decay;
varying vec2 velocity;
varying vec2 vertex;
uniform float time;
uniform float size; 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() 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 = 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 base = in_vertex;
vec2 p = size*base; vec3 p = s*vec3(base, 0.0);
p += log(1.0+time) * in_velocity; vec3 offset = log(1.0+age) * in_velocity + in_position;
p += in_position; p += offset;
gl_Position = vec4(p, 0.0, 1.0);
vertex = base; gl_Position = vec4(p, 1.0);
vertex = base.xy;
velocity = in_velocity; velocity = in_velocity;
explCenterDist = length(explCenter-offset);
} }

View file

@ -17,6 +17,8 @@ namespace endofthejedi {
, m_particleRadius(particleSize) , m_particleRadius(particleSize)
, m_maxAge(maxAge) , m_maxAge(maxAge)
, m_age(0.0) , 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 // 2d quad drawn as a triangle fan
, m_data_quad({ , m_data_quad({
@ -61,7 +63,17 @@ namespace endofthejedi {
glDeleteBuffers(5, m_data_vbos); 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 &center)
{
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) { if (index >= m_numParticles) {
return; return;
@ -123,9 +135,11 @@ namespace endofthejedi {
//std::cout<<"[ParticleBatch] render " << std::endl; //std::cout<<"[ParticleBatch] render " << std::endl;
m_shader.bind(); m_shader.bind();
glUniform1f(m_shader.location("time"), m_age); glUniform1f(m_shader.location("age"), m_age);
glUniform1f(m_shader.location("maxAge"), m_maxAge); glUniform1f(m_shader.location("maxVelocity"), m_maxVelocity);
glUniform1f(m_shader.location("size"), m_particleRadius); 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(); bind();
@ -155,9 +169,11 @@ namespace endofthejedi {
{ {
switch(i) { switch(i) {
case 0: case 0:
return 2;
case 1: case 1:
case 2: case 2:
return 2; return 3;
case 3: case 3:
case 4: case 4:

View file

@ -3,6 +3,7 @@
#include <vector> #include <vector>
#include <glm/vec2.hpp> #include <glm/vec2.hpp>
#include <glm/vec3.hpp>
#include "glclasses.hpp" #include "glclasses.hpp"
@ -16,7 +17,10 @@ namespace endofthejedi {
size_t numParticles() const { return m_numParticles; } 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 &center);
void setMaxVelocity(float maxVelocity);
void bind(); void bind();
void upload(); void upload();
@ -39,12 +43,14 @@ namespace endofthejedi {
float m_particleRadius; float m_particleRadius;
const float m_maxAge; const float m_maxAge;
float m_age; float m_age;
float m_maxVelocity;
glm::vec3 m_center;
GLuint m_data_vbos[5]; GLuint m_data_vbos[5];
std::vector<float> m_data_quad; std::vector<float> m_data_quad;
std::vector<glm::vec2> m_data_position; std::vector<glm::vec3> m_data_position;
std::vector<glm::vec2> m_data_velocity; std::vector<glm::vec3> m_data_velocity;
std::vector<float> m_data_kind; std::vector<float> m_data_kind;
std::vector<float> m_data_max_age; std::vector<float> m_data_max_age;

View file

@ -5,6 +5,7 @@
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/euler_angles.hpp> #include <glm/gtx/euler_angles.hpp>
#include <glm/gtc/random.hpp>
namespace endofthejedi { namespace endofthejedi {
void RendererPolygon3d::setup() void RendererPolygon3d::setup()
@ -54,11 +55,13 @@ namespace endofthejedi {
m_shader.bind(); 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); 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.3f, 0.4f, 0.0f);
glm::vec3 p = glm::vec3(0.5f, 0.5f, -4.0f);
glUniform3f(m_shader.location("lightPosition"), p.x, p.y, p.z); glUniform3f(m_shader.location("lightPosition"), p.x, p.y, p.z);
renderPlanets(); renderPlanets();
@ -91,20 +94,34 @@ namespace endofthejedi {
void RendererPolygon3d::addExplosionEffect(size_t id, const glm::vec2 &pos, size_t n, float duration) 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.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); ParticleBatch *batch = new ParticleBatch(id, n, particleRadius, duration);
batch->setCenter(glm::vec3(pos, 0.0));
batch->setMaxVelocity(maxVelocity);
for (size_t i=0; i<n; i++) { for (size_t i=0; i<n; i++) {
// distribute in a circle // distribute in a circle
float t = 2.0 * M_PI * i / (float) n; //float t = 2.0 * M_PI * i / (float) n;
//t += 0.2*util::randf_m1_1(); //t += 0.2*util::randf_m1_1();
// with random velocities // with random velocities
glm::vec2 v = 0.5f*glm::vec2(sin(t), cos(t)); // this is 3d because it looks better if some particles leave/enter
// the space and they are not all on one plane.
// especially in 3d this would look bad without 3d velocity vector.
//glm::vec3 v = 0.5f*glm::vec3(sin(t), cos(t), util::randf_m1_1());
glm::vec3 v = glm::ballRand(maxVelocity);
v *= util::randf_0_1() + util::randf_0_1(); v *= util::randf_0_1() + util::randf_0_1();
batch->setParticle(i, pos, v); batch->setParticle(i, glm::vec3(pos, 0.0) + glm::ballRand(explSize), v);
} }
batch->upload(); batch->upload();
@ -124,13 +141,13 @@ namespace endofthejedi {
} }
if (!gotIt) { if (!gotIt) {
addExplosionEffect(expl->id, expl->position, 1000, 2.0); addExplosionEffect(expl->id, expl->position, 500, 5.0);
} }
} }
//if (m_particles.size() == 0) { if (m_particles.size() == 0) {
// addExplosionEffect(0, glm::vec2(0.0, 0.0), 1000, 2.0); addExplosionEffect(0, glm::vec2(0.0, 0.0), 1000, 5.0);
//} }
std::vector<ParticleBatch*> rm; std::vector<ParticleBatch*> rm;

View file

@ -17,6 +17,7 @@
#include "particle_batch.hpp" #include "particle_batch.hpp"
#include "polygon_model.hpp" #include "polygon_model.hpp"
#include <glm/vec3.hpp>
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
namespace endofthejedi { namespace endofthejedi {