GPUParticles: Finish refactorisation.

Heightmap are enabled again for snow.

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@14994 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
vincentlj 2014-01-10 17:40:25 +00:00
parent af81015fcd
commit ba61e2cbe4
3 changed files with 429 additions and 193 deletions

View File

@ -0,0 +1,50 @@
#version 130
uniform int dt;
uniform mat4 sourcematrix;
uniform int level;
uniform float size_increase_factor;
uniform float track_x;
uniform float track_z;
uniform float track_x_len;
uniform float track_z_len;
uniform samplerBuffer heightmap;
in vec3 particle_position_initial;
in float lifetime_initial;
in vec3 particle_velocity_initial;
in float size_initial;
in vec3 particle_position;
in float lifetime;
in vec3 particle_velocity;
in float size;
out vec3 new_particle_position;
out float new_lifetime;
out vec3 new_particle_velocity;
out float new_size;
void main(void)
{
bool reset = false;
float i_as_float = clamp(256. * (particle_position.x - track_x) / track_x_len, 0., 255.);
float j_as_float = clamp(256. * (particle_position.z - track_z) / track_z_len, 0., 255.);
int i = int(i_as_float);
int j = int(j_as_float);
float h = particle_position.y - texelFetch(heightmap, i * 256 + j).r;
reset = h < 0.;
vec4 initialposition = sourcematrix * vec4(particle_position_initial, 1.0);
vec4 adjusted_initial_velocity = sourcematrix * vec4(particle_position_initial + particle_velocity_initial, 1.0) - initialposition;
float adjusted_lifetime = lifetime + (float(dt)/lifetime_initial);
reset = reset || (adjusted_lifetime > 1.) && (gl_VertexID <= level);
reset = reset || (lifetime < 0.);
new_particle_position = !reset ? particle_position + particle_velocity.xyz * float(dt) : initialposition.xyz;
new_lifetime = !reset ? adjusted_lifetime : 0.;
new_particle_velocity = !reset ? particle_velocity : adjusted_initial_velocity.xyz;
new_size = !reset ? mix(size_initial, size_initial * size_increase_factor, adjusted_lifetime) : size_initial;
gl_Position = vec4(0.);
}

View File

@ -11,6 +11,133 @@ GLuint getTextureGLuint(irr::video::ITexture *tex) {
#define COMPONENTCOUNT 8
namespace SimpleSimulationShader
{
GLuint Program;
GLuint attrib_position, attrib_velocity, attrib_lifetime, attrib_initial_position, attrib_initial_velocity, attrib_initial_lifetime, attrib_size, attrib_initial_size;
GLuint uniform_sourcematrix, uniform_dt, uniform_level, uniform_size_increase_factor;
void init()
{
initGL();
const char *varyings[] = {
"new_particle_position",
"new_lifetime",
"new_particle_velocity",
"new_size",
};
Program = LoadTFBProgram(file_manager->getAsset("shaders/pointemitter.vert").c_str(), varyings, 4);
uniform_dt = glGetUniformLocation(Program, "dt");
uniform_sourcematrix = glGetUniformLocation(Program, "sourcematrix");
uniform_level = glGetUniformLocation(Program, "level");
uniform_size_increase_factor = glGetUniformLocation(Program, "size_increase_factor");
attrib_position = glGetAttribLocation(Program, "particle_position");
attrib_lifetime = glGetAttribLocation(Program, "lifetime");
attrib_velocity = glGetAttribLocation(Program, "particle_velocity");
attrib_size = glGetAttribLocation(Program, "size");
attrib_initial_position = glGetAttribLocation(Program, "particle_position_initial");
attrib_initial_lifetime = glGetAttribLocation(Program, "lifetime_initial");
attrib_initial_velocity = glGetAttribLocation(Program, "particle_velocity_initial");
attrib_initial_size = glGetAttribLocation(Program, "size_initial");
}
}
namespace HeightmapSimulationShader
{
GLuint Program;
GLuint attrib_position, attrib_velocity, attrib_lifetime, attrib_initial_position, attrib_initial_velocity, attrib_initial_lifetime, attrib_size, attrib_initial_size;
GLuint uniform_sourcematrix, uniform_dt, uniform_level, uniform_size_increase_factor;
GLuint uniform_track_x, uniform_track_z, uniform_track_x_len, uniform_track_z_len, uniform_heightmap;
void init()
{
initGL();
const char *varyings[] = {
"new_particle_position",
"new_lifetime",
"new_particle_velocity",
"new_size",
};
Program = LoadTFBProgram(file_manager->getAsset("shaders/particlesimheightmap.vert").c_str(), varyings, 4);
uniform_dt = glGetUniformLocation(Program, "dt");
uniform_sourcematrix = glGetUniformLocation(Program, "sourcematrix");
uniform_level = glGetUniformLocation(Program, "level");
uniform_size_increase_factor = glGetUniformLocation(Program, "size_increase_factor");
attrib_position = glGetAttribLocation(Program, "particle_position");
attrib_lifetime = glGetAttribLocation(Program, "lifetime");
attrib_velocity = glGetAttribLocation(Program, "particle_velocity");
attrib_size = glGetAttribLocation(Program, "size");
attrib_initial_position = glGetAttribLocation(Program, "particle_position_initial");
attrib_initial_lifetime = glGetAttribLocation(Program, "lifetime_initial");
attrib_initial_velocity = glGetAttribLocation(Program, "particle_velocity_initial");
attrib_initial_size = glGetAttribLocation(Program, "size_initial");
uniform_heightmap = glGetUniformLocation(Program, "heightmap");
uniform_track_x = glGetUniformLocation(Program, "track_x");
uniform_track_x_len = glGetUniformLocation(Program, "track_x_len");
uniform_track_z = glGetUniformLocation(Program, "track_z");
uniform_track_z_len = glGetUniformLocation(Program, "track_z_len");
}
}
namespace SimpleParticleRender
{
GLuint Program;
GLuint attrib_pos, attrib_lf, attrib_quadcorner, attrib_texcoord, attrib_sz;
GLuint uniform_matrix, uniform_viewmatrix, uniform_texture, uniform_normal_and_depths, uniform_screen, uniform_invproj;
void init()
{
initGL();
Program = LoadProgram(file_manager->getAsset("shaders/particle.vert").c_str(), file_manager->getAsset("shaders/particle.frag").c_str());
attrib_pos = glGetAttribLocation(Program, "position");
attrib_sz = glGetAttribLocation(Program, "size");
attrib_lf = glGetAttribLocation(Program, "lifetime");
attrib_quadcorner = glGetAttribLocation(Program, "quadcorner");
attrib_texcoord = glGetAttribLocation(Program, "texcoord");
uniform_matrix = glGetUniformLocation(Program, "ProjectionMatrix");
uniform_viewmatrix = glGetUniformLocation(Program, "ViewMatrix");
uniform_texture = glGetUniformLocation(Program, "texture");
uniform_invproj = glGetUniformLocation(Program, "invproj");
uniform_screen = glGetUniformLocation(Program, "screen");
uniform_normal_and_depths = glGetUniformLocation(Program, "normals_and_depth");
}
}
namespace FlipParticleRender
{
GLuint Program;
GLuint attrib_pos, attrib_lf, attrib_quadcorner, attrib_texcoord, attrib_sz, attrib_rotationvec, attrib_anglespeed;
GLuint uniform_matrix, uniform_viewmatrix, uniform_texture, uniform_normal_and_depths, uniform_screen, uniform_invproj;
void init()
{
initGL();
Program = LoadProgram(file_manager->getAsset("shaders/flipparticle.vert").c_str(), file_manager->getAsset("shaders/particle.frag").c_str());
attrib_pos = glGetAttribLocation(Program, "position");
attrib_sz = glGetAttribLocation(Program, "size");
attrib_lf = glGetAttribLocation(Program, "lifetime");
attrib_quadcorner = glGetAttribLocation(Program, "quadcorner");
attrib_texcoord = glGetAttribLocation(Program, "texcoord");
attrib_anglespeed = glGetAttribLocation(Program, "anglespeed");
attrib_rotationvec = glGetAttribLocation(Program, "rotationvec");
uniform_matrix = glGetUniformLocation(Program, "ProjectionMatrix");
uniform_viewmatrix = glGetUniformLocation(Program, "ViewMatrix");
uniform_texture = glGetUniformLocation(Program, "texture");
uniform_invproj = glGetUniformLocation(Program, "invproj");
uniform_screen = glGetUniformLocation(Program, "screen");
uniform_normal_and_depths = glGetUniformLocation(Program, "normals_and_depth");
}
}
GPUParticle::GPUParticle(scene::ISceneNode *parent, scene::ISceneManager* mgr, ITexture *tex)
: scene::ISceneNode(parent, mgr, -1) {
initGL();
@ -109,7 +236,23 @@ void ParticleSystemProxy::setAlphaAdditive(bool val) { m_alpha_additive = val; }
void ParticleSystemProxy::setIncreaseFactor(float val) { size_increase_factor = val; }
void ParticleSystemProxy::setFlip() {
flip = true;
flip = true;
float *quaternions = new float[4 * count];
for (unsigned i = 0; i < count; i++)
{
core::vector3df rotationdir(0., 1., 0.);
/*rotationdir.rotateXYBy(os::Randomizer::frand() * 180.);
rotationdir.rotateYZBy(os::Randomizer::frand() * 180.);
rotationdir.rotateXZBy(os::Randomizer::frand() * 180.);*/
quaternions[4 * i] = rotationdir.X;
quaternions[4 * i + 1] = rotationdir.Y;
quaternions[4 * i + 2] = rotationdir.Z;
quaternions[4 * i + 3] = 3.14 * 3. * (2. * os::Randomizer::frand() - 1.); // 3 half rotation during lifetime at max
}
glGenBuffers(1, &quaternionsbuffer);
glBindBuffer(GL_ARRAY_BUFFER, quaternionsbuffer);
glBufferData(GL_ARRAY_BUFFER, 4 * count * sizeof(float), quaternions, GL_STATIC_DRAW);
delete[] quaternions;
}
void ParticleSystemProxy::setHeightmap(const std::vector<std::vector<float> > &hm,
@ -266,44 +409,6 @@ void ParticleSystemProxy::generateParticlesFromSphereEmitter(scene::IParticleSph
delete[] initialvalue;
}
GLuint ParticleSystemProxy::SimulationProgram = 0;
GLuint ParticleSystemProxy::RenderProgram = 0;
GLuint ParticleSystemProxy::attrib_position;
GLuint ParticleSystemProxy::attrib_velocity;
GLuint ParticleSystemProxy::attrib_lifetime;
GLuint ParticleSystemProxy::attrib_initial_position;
GLuint ParticleSystemProxy::attrib_initial_velocity;
GLuint ParticleSystemProxy::attrib_initial_lifetime;
GLuint ParticleSystemProxy::attrib_size;
GLuint ParticleSystemProxy::attrib_initial_size;
GLuint ParticleSystemProxy::uniform_sourcematrix;
GLuint ParticleSystemProxy::uniform_dt;
GLuint ParticleSystemProxy::uniform_level;
GLuint ParticleSystemProxy::uniform_size_increase_factor;
GLuint ParticleSystemProxy::uniform_has_heightmap;
GLuint ParticleSystemProxy::uniform_heightmap;
GLuint ParticleSystemProxy::uniform_track_x;
GLuint ParticleSystemProxy::uniform_track_x_len;
GLuint ParticleSystemProxy::uniform_track_z;
GLuint ParticleSystemProxy::uniform_track_z_len;
GLuint ParticleSystemProxy::uniform_flips;
GLuint ParticleSystemProxy::attrib_pos;
GLuint ParticleSystemProxy::attrib_lf;
GLuint ParticleSystemProxy::attrib_quadcorner;
GLuint ParticleSystemProxy::attrib_texcoord;
GLuint ParticleSystemProxy::attrib_sz;
GLuint ParticleSystemProxy::attrib_rotationvec;
GLuint ParticleSystemProxy::attrib_anglespeed;
GLuint ParticleSystemProxy::uniform_matrix;
GLuint ParticleSystemProxy::uniform_viewmatrix;
GLuint ParticleSystemProxy::uniform_texture;
GLuint ParticleSystemProxy::uniform_normal_and_depths;
GLuint ParticleSystemProxy::uniform_screen;
GLuint ParticleSystemProxy::uniform_invproj;
static bool isGPUParticleType(scene::E_PARTICLE_EMITTER_TYPE type)
{
switch (type)
@ -345,80 +450,20 @@ void ParticleSystemProxy::setEmitter(scene::IParticleEmitter* emitter)
assert(0 && "Wrong particle type");
}
float *quaternions = new float[4 * count];
for (unsigned i = 0; i < count; i++)
{
core::vector3df rotationdir(0., 1., 0.);
/*rotationdir.rotateXYBy(os::Randomizer::frand() * 180.);
rotationdir.rotateYZBy(os::Randomizer::frand() * 180.);
rotationdir.rotateXZBy(os::Randomizer::frand() * 180.);*/
quaternions[4 * i] = rotationdir.X;
quaternions[4 * i + 1] = rotationdir.Y;
quaternions[4 * i + 2] = rotationdir.Z;
quaternions[4 * i + 3] = 3.14 * 3. * ( 2. * os::Randomizer::frand() - 1.); // 3 half rotation during lifetime at max
}
glGenBuffers(1, &quaternionsbuffer);
glBindBuffer(GL_ARRAY_BUFFER, quaternionsbuffer);
glBufferData(GL_ARRAY_BUFFER, 4 * count * sizeof(float), quaternions, GL_STATIC_DRAW);
delete[] quaternions;
glBindBuffer(GL_ARRAY_BUFFER, 0);
texture = getTextureGLuint(getMaterial(0).getTexture(0));
normal_and_depth = getTextureGLuint(irr_driver->getRTT(RTT_NORMAL_AND_DEPTH));
if (SimulationProgram && RenderProgram)
if (SimpleSimulationShader::Program && SimpleParticleRender::Program && FlipParticleRender::Program && HeightmapSimulationShader::Program)
return;
const char *varyings[] = {
"new_particle_position",
"new_lifetime",
"new_particle_velocity",
"new_size",
};
SimulationProgram = LoadTFBProgram(file_manager->getAsset("shaders/pointemitter.vert").c_str(), varyings, 4);
uniform_dt = glGetUniformLocation(SimulationProgram, "dt");
uniform_sourcematrix = glGetUniformLocation(SimulationProgram, "sourcematrix");
uniform_level = glGetUniformLocation(SimulationProgram, "level");
uniform_size_increase_factor = glGetUniformLocation(SimulationProgram, "size_increase_factor");
attrib_position = glGetAttribLocation(SimulationProgram, "particle_position");
attrib_lifetime = glGetAttribLocation(SimulationProgram, "lifetime");
attrib_velocity = glGetAttribLocation(SimulationProgram, "particle_velocity");
attrib_size = glGetAttribLocation(SimulationProgram, "size");
attrib_initial_position = glGetAttribLocation(SimulationProgram, "particle_position_initial");
attrib_initial_lifetime = glGetAttribLocation(SimulationProgram, "lifetime_initial");
attrib_initial_velocity = glGetAttribLocation(SimulationProgram, "particle_velocity_initial");
attrib_initial_size = glGetAttribLocation(SimulationProgram, "size_initial");
RenderProgram = LoadProgram(file_manager->getAsset("shaders/particle.vert").c_str(), file_manager->getAsset("shaders/particle.frag").c_str());
attrib_pos = glGetAttribLocation(RenderProgram, "position");
attrib_sz = glGetAttribLocation(RenderProgram, "size");
attrib_lf = glGetAttribLocation(RenderProgram, "lifetime");
attrib_quadcorner = glGetAttribLocation(RenderProgram, "quadcorner");
attrib_texcoord = glGetAttribLocation(RenderProgram, "texcoord");
attrib_rotationvec = glGetAttribLocation(RenderProgram, "rotationvec");
attrib_anglespeed = glGetAttribLocation(RenderProgram, "anglespeed");
uniform_matrix = glGetUniformLocation(RenderProgram, "ProjectionMatrix");
uniform_viewmatrix = glGetUniformLocation(RenderProgram, "ViewMatrix");
uniform_texture = glGetUniformLocation(RenderProgram, "texture");
uniform_invproj = glGetUniformLocation(RenderProgram, "invproj");
uniform_screen = glGetUniformLocation(RenderProgram, "screen");
uniform_normal_and_depths = glGetUniformLocation(RenderProgram, "normals_and_depth");
uniform_has_heightmap = glGetUniformLocation(RenderProgram, "hasHeightMap");
uniform_heightmap = glGetUniformLocation(RenderProgram, "heightmap");
uniform_track_x = glGetUniformLocation(RenderProgram, "track_x");
uniform_track_x_len = glGetUniformLocation(RenderProgram, "track_x_len");
uniform_track_z = glGetUniformLocation(RenderProgram, "track_z");
uniform_track_z_len = glGetUniformLocation(RenderProgram, "track_z_len");
uniform_flips = glGetUniformLocation(RenderProgram, "flips");
SimpleSimulationShader::init();
HeightmapSimulationShader::init();
SimpleParticleRender::init();
FlipParticleRender::init();
}
void ParticleSystemProxy::simulate()
void ParticleSystemProxy::simulateHeightmap()
{
unsigned time = os::Timer::getTime();
if (LastEmitTime == 0)
@ -431,50 +476,120 @@ void ParticleSystemProxy::simulate()
LastEmitTime = time;
int active_count = getEmitter()->getMaxLifeTime() * getEmitter()->getMaxParticlesPerSecond() / 1000;
core::matrix4 matrix = getAbsoluteTransformation();
glUseProgram(SimulationProgram);
glUseProgram(HeightmapSimulationShader::Program);
glEnable(GL_RASTERIZER_DISCARD);
glEnableVertexAttribArray(attrib_position);
glEnableVertexAttribArray(attrib_lifetime);
glEnableVertexAttribArray(attrib_velocity);
glEnableVertexAttribArray(attrib_size);
glEnableVertexAttribArray(HeightmapSimulationShader::attrib_position);
glEnableVertexAttribArray(HeightmapSimulationShader::attrib_lifetime);
glEnableVertexAttribArray(HeightmapSimulationShader::attrib_velocity);
glEnableVertexAttribArray(HeightmapSimulationShader::attrib_size);
glBindBuffer(GL_ARRAY_BUFFER, tfb_buffers[0]);
glVertexAttribPointer(attrib_position, 3, GL_FLOAT, GL_FALSE, sizeof(ParticleData), (GLvoid*)0);
glVertexAttribPointer(attrib_lifetime, 1, GL_FLOAT, GL_FALSE, sizeof(ParticleData), (GLvoid*)(3 * sizeof(float)));
glVertexAttribPointer(attrib_velocity, 4, GL_FLOAT, GL_FALSE, sizeof(ParticleData), (GLvoid*)(4 * sizeof(float)));
glVertexAttribPointer(attrib_size, 1, GL_FLOAT, GL_FALSE, sizeof(ParticleData), (GLvoid*)(7 * sizeof(float)));
glEnableVertexAttribArray(attrib_initial_position);
glEnableVertexAttribArray(attrib_initial_lifetime);
glEnableVertexAttribArray(attrib_initial_velocity);
glEnableVertexAttribArray(attrib_initial_size);
glVertexAttribPointer(HeightmapSimulationShader::attrib_position, 3, GL_FLOAT, GL_FALSE, sizeof(ParticleData), (GLvoid*)0);
glVertexAttribPointer(HeightmapSimulationShader::attrib_lifetime, 1, GL_FLOAT, GL_FALSE, sizeof(ParticleData), (GLvoid*)(3 * sizeof(float)));
glVertexAttribPointer(HeightmapSimulationShader::attrib_velocity, 4, GL_FLOAT, GL_FALSE, sizeof(ParticleData), (GLvoid*)(4 * sizeof(float)));
glVertexAttribPointer(HeightmapSimulationShader::attrib_size, 1, GL_FLOAT, GL_FALSE, sizeof(ParticleData), (GLvoid*)(7 * sizeof(float)));
glEnableVertexAttribArray(HeightmapSimulationShader::attrib_initial_position);
glEnableVertexAttribArray(HeightmapSimulationShader::attrib_initial_lifetime);
glEnableVertexAttribArray(HeightmapSimulationShader::attrib_initial_velocity);
glEnableVertexAttribArray(HeightmapSimulationShader::attrib_initial_size);
glBindBuffer(GL_ARRAY_BUFFER, initial_values_buffer);
glVertexAttribPointer(attrib_initial_position, 3, GL_FLOAT, GL_FALSE, sizeof(ParticleData), (GLvoid*)0);
glVertexAttribPointer(attrib_initial_lifetime, 1, GL_FLOAT, GL_FALSE, sizeof(ParticleData), (GLvoid*)(3 * sizeof(float)));
glVertexAttribPointer(attrib_initial_velocity, 4, GL_FLOAT, GL_FALSE, sizeof(ParticleData), (GLvoid*)(4 * sizeof(float)));
glVertexAttribPointer(attrib_initial_size, 1, GL_FLOAT, GL_FALSE, sizeof(ParticleData), (GLvoid*)(7 * sizeof(float)));
glVertexAttribPointer(HeightmapSimulationShader::attrib_initial_position, 3, GL_FLOAT, GL_FALSE, sizeof(ParticleData), (GLvoid*)0);
glVertexAttribPointer(HeightmapSimulationShader::attrib_initial_lifetime, 1, GL_FLOAT, GL_FALSE, sizeof(ParticleData), (GLvoid*)(3 * sizeof(float)));
glVertexAttribPointer(HeightmapSimulationShader::attrib_initial_velocity, 4, GL_FLOAT, GL_FALSE, sizeof(ParticleData), (GLvoid*)(4 * sizeof(float)));
glVertexAttribPointer(HeightmapSimulationShader::attrib_initial_size, 1, GL_FLOAT, GL_FALSE, sizeof(ParticleData), (GLvoid*)(7 * sizeof(float)));
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tfb_buffers[1]);
glUniform1i(uniform_dt, timediff);
glUniform1i(uniform_level, active_count);
glUniformMatrix4fv(uniform_sourcematrix, 1, GL_FALSE, matrix.pointer());
glUniform1f(uniform_size_increase_factor, size_increase_factor);
glUniform1i(HeightmapSimulationShader::uniform_dt, timediff);
glUniform1i(HeightmapSimulationShader::uniform_level, active_count);
glUniformMatrix4fv(HeightmapSimulationShader::uniform_sourcematrix, 1, GL_FALSE, matrix.pointer());
glUniform1f(HeightmapSimulationShader::uniform_size_increase_factor, size_increase_factor);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_BUFFER, heightmaptexture);
glUniform1i(HeightmapSimulationShader::uniform_heightmap, 2);
glUniform1f(HeightmapSimulationShader::uniform_track_x, track_x);
glUniform1f(HeightmapSimulationShader::uniform_track_z, track_z);
glUniform1f(HeightmapSimulationShader::uniform_track_x_len, track_x_len);
glUniform1f(HeightmapSimulationShader::uniform_track_z_len, track_z_len);
glBeginTransformFeedback(GL_POINTS);
glDrawArrays(GL_POINTS, 0, count);
glEndTransformFeedback();
glDisableVertexAttribArray(attrib_position);
glDisableVertexAttribArray(attrib_lifetime);
glDisableVertexAttribArray(attrib_velocity);
glDisableVertexAttribArray(attrib_size);
glDisableVertexAttribArray(attrib_initial_position);
glDisableVertexAttribArray(attrib_initial_lifetime);
glDisableVertexAttribArray(attrib_initial_velocity);
glDisableVertexAttribArray(attrib_initial_size);
glDisableVertexAttribArray(HeightmapSimulationShader::attrib_position);
glDisableVertexAttribArray(HeightmapSimulationShader::attrib_lifetime);
glDisableVertexAttribArray(HeightmapSimulationShader::attrib_velocity);
glDisableVertexAttribArray(HeightmapSimulationShader::attrib_size);
glDisableVertexAttribArray(HeightmapSimulationShader::attrib_initial_position);
glDisableVertexAttribArray(HeightmapSimulationShader::attrib_initial_lifetime);
glDisableVertexAttribArray(HeightmapSimulationShader::attrib_initial_velocity);
glDisableVertexAttribArray(HeightmapSimulationShader::attrib_initial_size);
glDisable(GL_RASTERIZER_DISCARD);
std::swap(tfb_buffers[0], tfb_buffers[1]);
}
void ParticleSystemProxy::draw()
void ParticleSystemProxy::simulateNoHeightmap()
{
unsigned time = os::Timer::getTime();
if (LastEmitTime == 0)
{
LastEmitTime = time;
return;
}
u32 timediff = time - LastEmitTime;
LastEmitTime = time;
int active_count = getEmitter()->getMaxLifeTime() * getEmitter()->getMaxParticlesPerSecond() / 1000;
core::matrix4 matrix = getAbsoluteTransformation();
glUseProgram(SimpleSimulationShader::Program);
glEnable(GL_RASTERIZER_DISCARD);
glEnableVertexAttribArray(SimpleSimulationShader::attrib_position);
glEnableVertexAttribArray(SimpleSimulationShader::attrib_lifetime);
glEnableVertexAttribArray(SimpleSimulationShader::attrib_velocity);
glEnableVertexAttribArray(SimpleSimulationShader::attrib_size);
glBindBuffer(GL_ARRAY_BUFFER, tfb_buffers[0]);
glVertexAttribPointer(SimpleSimulationShader::attrib_position, 3, GL_FLOAT, GL_FALSE, sizeof(ParticleData), (GLvoid*)0);
glVertexAttribPointer(SimpleSimulationShader::attrib_lifetime, 1, GL_FLOAT, GL_FALSE, sizeof(ParticleData), (GLvoid*)(3 * sizeof(float)));
glVertexAttribPointer(SimpleSimulationShader::attrib_velocity, 4, GL_FLOAT, GL_FALSE, sizeof(ParticleData), (GLvoid*)(4 * sizeof(float)));
glVertexAttribPointer(SimpleSimulationShader::attrib_size, 1, GL_FLOAT, GL_FALSE, sizeof(ParticleData), (GLvoid*)(7 * sizeof(float)));
glEnableVertexAttribArray(SimpleSimulationShader::attrib_initial_position);
glEnableVertexAttribArray(SimpleSimulationShader::attrib_initial_lifetime);
glEnableVertexAttribArray(SimpleSimulationShader::attrib_initial_velocity);
glEnableVertexAttribArray(SimpleSimulationShader::attrib_initial_size);
glBindBuffer(GL_ARRAY_BUFFER, initial_values_buffer);
glVertexAttribPointer(SimpleSimulationShader::attrib_initial_position, 3, GL_FLOAT, GL_FALSE, sizeof(ParticleData), (GLvoid*)0);
glVertexAttribPointer(SimpleSimulationShader::attrib_initial_lifetime, 1, GL_FLOAT, GL_FALSE, sizeof(ParticleData), (GLvoid*)(3 * sizeof(float)));
glVertexAttribPointer(SimpleSimulationShader::attrib_initial_velocity, 4, GL_FLOAT, GL_FALSE, sizeof(ParticleData), (GLvoid*)(4 * sizeof(float)));
glVertexAttribPointer(SimpleSimulationShader::attrib_initial_size, 1, GL_FLOAT, GL_FALSE, sizeof(ParticleData), (GLvoid*)(7 * sizeof(float)));
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tfb_buffers[1]);
glUniform1i(SimpleSimulationShader::uniform_dt, timediff);
glUniform1i(SimpleSimulationShader::uniform_level, active_count);
glUniformMatrix4fv(SimpleSimulationShader::uniform_sourcematrix, 1, GL_FALSE, matrix.pointer());
glUniform1f(SimpleSimulationShader::uniform_size_increase_factor, size_increase_factor);
glBeginTransformFeedback(GL_POINTS);
glDrawArrays(GL_POINTS, 0, count);
glEndTransformFeedback();
glDisableVertexAttribArray(SimpleSimulationShader::attrib_position);
glDisableVertexAttribArray(SimpleSimulationShader::attrib_lifetime);
glDisableVertexAttribArray(SimpleSimulationShader::attrib_velocity);
glDisableVertexAttribArray(SimpleSimulationShader::attrib_size);
glDisableVertexAttribArray(SimpleSimulationShader::attrib_initial_position);
glDisableVertexAttribArray(SimpleSimulationShader::attrib_initial_lifetime);
glDisableVertexAttribArray(SimpleSimulationShader::attrib_initial_velocity);
glDisableVertexAttribArray(SimpleSimulationShader::attrib_initial_size);
glDisable(GL_RASTERIZER_DISCARD);
std::swap(tfb_buffers[0], tfb_buffers[1]);
}
void ParticleSystemProxy::simulate()
{
if (has_height_map)
simulateHeightmap();
else
simulateNoHeightmap();
}
void ParticleSystemProxy::drawFlip()
{
glDepthMask(GL_FALSE);
glDisable(GL_CULL_FACE);
@ -484,74 +599,151 @@ void ParticleSystemProxy::draw()
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
else
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glUseProgram(RenderProgram);
glEnableVertexAttribArray(attrib_pos);
glEnableVertexAttribArray(attrib_lf);
glEnableVertexAttribArray(attrib_quadcorner);
glEnableVertexAttribArray(attrib_texcoord);
glEnableVertexAttribArray(attrib_sz);
glUseProgram(FlipParticleRender::Program);
glEnableVertexAttribArray(FlipParticleRender::attrib_pos);
glEnableVertexAttribArray(FlipParticleRender::attrib_lf);
glEnableVertexAttribArray(FlipParticleRender::attrib_quadcorner);
glEnableVertexAttribArray(FlipParticleRender::attrib_texcoord);
glEnableVertexAttribArray(FlipParticleRender::attrib_sz);
float screen[2] = {
(float)UserConfigParams::m_width,
(float)UserConfigParams::m_height
};
bindUniformToTextureUnit(uniform_texture, texture, 0);
bindUniformToTextureUnit(uniform_normal_and_depths, normal_and_depth, 1);
bindUniformToTextureUnit(FlipParticleRender::uniform_texture, texture, 0);
bindUniformToTextureUnit(FlipParticleRender::uniform_normal_and_depths, normal_and_depth, 1);
glUniformMatrix4fv(uniform_invproj, 1, GL_FALSE, irr_driver->getInvProjMatrix().pointer());
glUniform2f(uniform_screen, screen[0], screen[1]);
glUniformMatrix4fv(uniform_matrix, 1, GL_FALSE, irr_driver->getProjMatrix().pointer());
glUniformMatrix4fv(uniform_viewmatrix, 1, GL_FALSE, irr_driver->getViewMatrix().pointer());
glUniformMatrix4fv(FlipParticleRender::uniform_invproj, 1, GL_FALSE, irr_driver->getInvProjMatrix().pointer());
glUniform2f(FlipParticleRender::uniform_screen, screen[0], screen[1]);
glUniformMatrix4fv(FlipParticleRender::uniform_matrix, 1, GL_FALSE, irr_driver->getProjMatrix().pointer());
glUniformMatrix4fv(FlipParticleRender::uniform_viewmatrix, 1, GL_FALSE, irr_driver->getViewMatrix().pointer());
glUniform1i(uniform_has_heightmap, has_height_map);
/* glUniform1i(FlipParticleRender::uniform_has_heightmap, has_height_map);
if (has_height_map)
{
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_BUFFER, heightmaptexture);
glUniform1i(uniform_heightmap, 2);
glUniform1f(uniform_track_x, track_x);
glUniform1f(uniform_track_z, track_z);
glUniform1f(uniform_track_x_len, track_x_len);
glUniform1f(uniform_track_z_len, track_z_len);
}
glEnableVertexAttribArray(attrib_rotationvec);
glEnableVertexAttribArray(attrib_anglespeed);
glUniform1i(uniform_flips, flip);
glUniform1i(FlipParticleRender::uniform_heightmap, 2);
glUniform1f(FlipParticleRender::uniform_track_x, track_x);
glUniform1f(FlipParticleRender::uniform_track_z, track_z);
glUniform1f(FlipParticleRender::uniform_track_x_len, track_x_len);
glUniform1f(FlipParticleRender::uniform_track_z_len, track_z_len);
}*/
glEnableVertexAttribArray(FlipParticleRender::attrib_rotationvec);
glEnableVertexAttribArray(FlipParticleRender::attrib_anglespeed);
glBindBuffer(GL_ARRAY_BUFFER, quaternionsbuffer);
glVertexAttribPointer(attrib_rotationvec, 3, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
glVertexAttribPointer(attrib_anglespeed, 1, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (GLvoid *)(3 * sizeof(float)));
glVertexAttribPointer(FlipParticleRender::attrib_rotationvec, 3, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
glVertexAttribPointer(FlipParticleRender::attrib_anglespeed, 1, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (GLvoid *)(3 * sizeof(float)));
glBindBuffer(GL_ARRAY_BUFFER, quad_vertex_buffer);
glVertexAttribPointer(attrib_quadcorner, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
glVertexAttribPointer(attrib_texcoord, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (GLvoid *)(2 * sizeof(float)));
glVertexAttribPointer(FlipParticleRender::attrib_quadcorner, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
glVertexAttribPointer(FlipParticleRender::attrib_texcoord, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (GLvoid *)(2 * sizeof(float)));
glBindBuffer(GL_ARRAY_BUFFER, tfb_buffers[0]);
glVertexAttribPointer(attrib_pos, 3, GL_FLOAT, GL_FALSE, sizeof(ParticleData), 0);
glVertexAttribPointer(attrib_lf, 1, GL_FLOAT, GL_FALSE, sizeof(ParticleData), (GLvoid *)(3 * sizeof(float)));
glVertexAttribPointer(attrib_sz, 1, GL_FLOAT, GL_FALSE, sizeof(ParticleData), (GLvoid *)(7 * sizeof(float)));
glVertexAttribPointer(FlipParticleRender::attrib_pos, 3, GL_FLOAT, GL_FALSE, sizeof(ParticleData), 0);
glVertexAttribPointer(FlipParticleRender::attrib_lf, 1, GL_FLOAT, GL_FALSE, sizeof(ParticleData), (GLvoid *)(3 * sizeof(float)));
glVertexAttribPointer(FlipParticleRender::attrib_sz, 1, GL_FLOAT, GL_FALSE, sizeof(ParticleData), (GLvoid *)(7 * sizeof(float)));
glVertexAttribDivisor(attrib_lf, 1);
glVertexAttribDivisor(attrib_pos, 1);
glVertexAttribDivisor(attrib_sz, 1);
glVertexAttribDivisor(attrib_rotationvec, 1);
glVertexAttribDivisor(attrib_anglespeed, 1);
glVertexAttribDivisor(FlipParticleRender::attrib_lf, 1);
glVertexAttribDivisor(FlipParticleRender::attrib_pos, 1);
glVertexAttribDivisor(FlipParticleRender::attrib_sz, 1);
glVertexAttribDivisor(FlipParticleRender::attrib_rotationvec, 1);
glVertexAttribDivisor(FlipParticleRender::attrib_anglespeed, 1);
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, count);
glVertexAttribDivisor(attrib_lf, 0);
glVertexAttribDivisor(attrib_pos, 0);
glVertexAttribDivisor(attrib_sz, 0);
glVertexAttribDivisor(attrib_rotationvec, 0);
glVertexAttribDivisor(attrib_anglespeed, 0);
glDisableVertexAttribArray(attrib_pos);
glDisableVertexAttribArray(attrib_lf);
glDisableVertexAttribArray(attrib_quadcorner);
glDisableVertexAttribArray(attrib_texcoord);
glDisableVertexAttribArray(attrib_sz);
glDisableVertexAttribArray(attrib_rotationvec);
glDisableVertexAttribArray(attrib_anglespeed);
glVertexAttribDivisor(FlipParticleRender::attrib_lf, 0);
glVertexAttribDivisor(FlipParticleRender::attrib_pos, 0);
glVertexAttribDivisor(FlipParticleRender::attrib_sz, 0);
glVertexAttribDivisor(FlipParticleRender::attrib_rotationvec, 0);
glVertexAttribDivisor(FlipParticleRender::attrib_anglespeed, 0);
glDisableVertexAttribArray(FlipParticleRender::attrib_pos);
glDisableVertexAttribArray(FlipParticleRender::attrib_lf);
glDisableVertexAttribArray(FlipParticleRender::attrib_quadcorner);
glDisableVertexAttribArray(FlipParticleRender::attrib_texcoord);
glDisableVertexAttribArray(FlipParticleRender::attrib_sz);
glDisableVertexAttribArray(FlipParticleRender::attrib_rotationvec);
glDisableVertexAttribArray(FlipParticleRender::attrib_anglespeed);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glActiveTexture(GL_TEXTURE0);
glDisable(GL_BLEND);
}
void ParticleSystemProxy::drawNotFlip()
{
glDepthMask(GL_FALSE);
glDisable(GL_CULL_FACE);
glEnable(GL_BLEND);
if (m_alpha_additive)
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
else
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glUseProgram(SimpleParticleRender::Program);
glEnableVertexAttribArray(SimpleParticleRender::attrib_pos);
glEnableVertexAttribArray(SimpleParticleRender::attrib_lf);
glEnableVertexAttribArray(SimpleParticleRender::attrib_quadcorner);
glEnableVertexAttribArray(SimpleParticleRender::attrib_texcoord);
glEnableVertexAttribArray(SimpleParticleRender::attrib_sz);
float screen[2] = {
(float)UserConfigParams::m_width,
(float)UserConfigParams::m_height
};
bindUniformToTextureUnit(SimpleParticleRender::uniform_texture, texture, 0);
bindUniformToTextureUnit(SimpleParticleRender::uniform_normal_and_depths, normal_and_depth, 1);
glUniformMatrix4fv(SimpleParticleRender::uniform_invproj, 1, GL_FALSE, irr_driver->getInvProjMatrix().pointer());
glUniform2f(SimpleParticleRender::uniform_screen, screen[0], screen[1]);
glUniformMatrix4fv(SimpleParticleRender::uniform_matrix, 1, GL_FALSE, irr_driver->getProjMatrix().pointer());
glUniformMatrix4fv(SimpleParticleRender::uniform_viewmatrix, 1, GL_FALSE, irr_driver->getViewMatrix().pointer());
/* glUniform1i(SimpleParticleRender::uniform_has_heightmap, has_height_map);
if (has_height_map)
{
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_BUFFER, heightmaptexture);
glUniform1i(SimpleParticleRender::uniform_heightmap, 2);
glUniform1f(SimpleParticleRender::uniform_track_x, track_x);
glUniform1f(SimpleParticleRender::uniform_track_z, track_z);
glUniform1f(SimpleParticleRender::uniform_track_x_len, track_x_len);
glUniform1f(SimpleParticleRender::uniform_track_z_len, track_z_len);
}*/
glBindBuffer(GL_ARRAY_BUFFER, quad_vertex_buffer);
glVertexAttribPointer(SimpleParticleRender::attrib_quadcorner, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
glVertexAttribPointer(SimpleParticleRender::attrib_texcoord, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (GLvoid *)(2 * sizeof(float)));
glBindBuffer(GL_ARRAY_BUFFER, tfb_buffers[0]);
glVertexAttribPointer(SimpleParticleRender::attrib_pos, 3, GL_FLOAT, GL_FALSE, sizeof(ParticleData), 0);
glVertexAttribPointer(SimpleParticleRender::attrib_lf, 1, GL_FLOAT, GL_FALSE, sizeof(ParticleData), (GLvoid *)(3 * sizeof(float)));
glVertexAttribPointer(SimpleParticleRender::attrib_sz, 1, GL_FLOAT, GL_FALSE, sizeof(ParticleData), (GLvoid *)(7 * sizeof(float)));
glVertexAttribDivisor(SimpleParticleRender::attrib_lf, 1);
glVertexAttribDivisor(SimpleParticleRender::attrib_pos, 1);
glVertexAttribDivisor(SimpleParticleRender::attrib_sz, 1);
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, count);
glVertexAttribDivisor(SimpleParticleRender::attrib_lf, 0);
glVertexAttribDivisor(SimpleParticleRender::attrib_pos, 0);
glVertexAttribDivisor(SimpleParticleRender::attrib_sz, 0);
glDisableVertexAttribArray(SimpleParticleRender::attrib_pos);
glDisableVertexAttribArray(SimpleParticleRender::attrib_lf);
glDisableVertexAttribArray(SimpleParticleRender::attrib_quadcorner);
glDisableVertexAttribArray(SimpleParticleRender::attrib_texcoord);
glDisableVertexAttribArray(SimpleParticleRender::attrib_sz);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glActiveTexture(GL_TEXTURE0);
glDisable(GL_BLEND);
}
void ParticleSystemProxy::draw()
{
if (flip)
drawFlip();
else
drawNotFlip();
}
void ParticleSystemProxy::render() {

View File

@ -31,21 +31,15 @@ protected:
bool m_alpha_additive, has_height_map, flip;
float size_increase_factor, track_x, track_z, track_x_len, track_z_len;
static GLuint SimulationProgram;
static GLuint attrib_position, attrib_velocity, attrib_lifetime, attrib_initial_position, attrib_initial_velocity, attrib_initial_lifetime, attrib_size, attrib_initial_size;
static GLuint uniform_sourcematrix, uniform_dt, uniform_level, uniform_size_increase_factor, uniform_has_heightmap, uniform_heightmap;
static GLuint RenderProgram;
static GLuint attrib_pos, attrib_lf, attrib_quadcorner, attrib_texcoord, attrib_sz, attrib_rotationvec, attrib_anglespeed;
static GLuint uniform_matrix, uniform_viewmatrix, uniform_texture, uniform_normal_and_depths, uniform_screen, uniform_invproj, uniform_flips;
static GLuint uniform_track_x, uniform_track_z, uniform_track_x_len, uniform_track_z_len;
static GLuint quad_vertex_buffer;
GLuint texture, normal_and_depth;
unsigned duration, count, LastEmitTime;
void simulateHeightmap();
void simulateNoHeightmap();
void drawFlip();
void drawNotFlip();
virtual void simulate();
virtual void draw();
void generateParticlesFromPointEmitter(scene::IParticlePointEmitter *);