Merge branch 'Elderme-Fix_particles'

This commit is contained in:
hiker 2015-08-14 13:51:53 +10:00
commit ce17da98bf
6 changed files with 68 additions and 46 deletions

View File

@ -1,4 +1,5 @@
uniform int dt;
uniform mat4 previous_frame_sourcematrix;
uniform mat4 sourcematrix;
uniform int level;
uniform float size_increase_factor;
@ -32,31 +33,48 @@ out float new_size;
void main(void)
{
float updated_lifetime = lifetime + (float(dt)/lifetime_initial);
if (updated_lifetime > 1.)
{
if (gl_VertexID < level)
float updated_lifetime = lifetime + (float(dt)/lifetime_initial);
if (updated_lifetime > 1.)
{
float dt_from_last_frame = fract(updated_lifetime) * lifetime_initial;
vec4 updated_initialposition = sourcematrix * vec4(particle_position_initial, 1.0);
vec4 updated_initial_velocity = sourcematrix * vec4(particle_position_initial + particle_velocity_initial, 1.0) - updated_initialposition;
new_particle_position = updated_initialposition.xyz + updated_initial_velocity.xyz * float(dt_from_last_frame);
new_particle_velocity = updated_initial_velocity.xyz;
new_lifetime = fract(updated_lifetime);
new_size = mix(size_initial, size_initial * size_increase_factor, fract(updated_lifetime));
if (gl_VertexID < level)
{
float dt_from_last_frame = fract(updated_lifetime) * lifetime_initial;
float coeff = dt_from_last_frame / dt;
vec4 previous_frame_position = previous_frame_sourcematrix * vec4(particle_position_initial, 1.0);
vec4 current_frame_position = sourcematrix * vec4(particle_position_initial, 1.0);
vec4 updated_initialposition = mix(current_frame_position,
previous_frame_position,
coeff);
vec4 updated_initial_velocity = mix(sourcematrix * vec4(particle_velocity_initial, 0.0),
previous_frame_sourcematrix * vec4(particle_velocity_initial, 0.0),
coeff);
//+ (current_frame_position - previous_frame_position) / dt;
//To be accurate, emitter speed should be added.
//But the simple formula ( (current_frame_position - previous_frame_position) / dt ) with a constant speed
//between 2 frames creates visual artifacts when the framerate is low, and a more accurate formula would need
//more complex computations.
new_particle_position = updated_initialposition.xyz + dt_from_last_frame * updated_initial_velocity.xyz;
new_particle_velocity = updated_initial_velocity.xyz;
new_lifetime = fract(updated_lifetime);
new_size = mix(size_initial, size_initial * size_increase_factor, fract(updated_lifetime));
}
else
{
new_lifetime = fract(updated_lifetime);
new_size = 0;
}
}
else
{
new_lifetime = fract(updated_lifetime);
new_size = 0;
new_particle_position = particle_position + particle_velocity.xyz * float(dt);
new_particle_velocity = particle_velocity;
new_lifetime = updated_lifetime;
new_size = (size == 0) ? 0. : mix(size_initial, size_initial * size_increase_factor, updated_lifetime);
}
}
else
{
new_particle_position = particle_position + particle_velocity.xyz * float(dt);
new_particle_velocity = particle_velocity;
new_lifetime = updated_lifetime;
new_size = (size == 0) ? 0. : mix(size_initial, size_initial * size_increase_factor, updated_lifetime);
}
gl_Position = vec4(0.);
gl_Position = vec4(0.);
}

View File

@ -37,7 +37,7 @@
/** Transform feedback shader that simulates the particles on GPU.
*/
class PointEmitterShader : public Shader
< PointEmitterShader, core::matrix4, int, int, float >
< PointEmitterShader, core::matrix4, core::matrix4, int, int, float >
{
public:
PointEmitterShader()
@ -45,7 +45,8 @@ public:
const char *varyings[] = { "new_particle_position", "new_lifetime",
"new_particle_velocity", "new_size" };
loadTFBProgram("pointemitter.vert", varyings, 4);
assignUniforms("sourcematrix", "dt", "level", "size_increase_factor");
assignUniforms("previous_frame_sourcematrix", "sourcematrix",
"dt", "level", "size_increase_factor");
} // PointEmitterShader
}; // PointEmitterShader
@ -262,7 +263,7 @@ void ParticleSystemProxy::generateParticlesFromPointEmitter(scene::IParticlePoin
ParticleParams[i].PositionZ = 0;
// Initial lifetime is >1
InitialValues[i].Lifetime = 2.;
memcpy(&(InitialValues[i].PositionX), &(ParticleParams[i].PositionX), 3 * sizeof(float));
generateLifetimeSizeDirection(emitter, ParticleParams[i].Lifetime, ParticleParams[i].Size,
@ -466,11 +467,11 @@ void ParticleSystemProxy::CommonSimulationVAO(GLuint position_vbo, GLuint initia
}
void ParticleSystemProxy::simulate()
{
{
int timediff = int(GUIEngine::getLatestDt() * 1000.f);
int active_count = getEmitter()->getMaxLifeTime() * getEmitter()->getMaxParticlesPerSecond() / 1000;
core::matrix4 matrix = getAbsoluteTransformation();
glEnable(GL_RASTERIZER_DISCARD);
if (has_height_map)
{
@ -482,9 +483,10 @@ void ParticleSystemProxy::simulate()
else
{
PointEmitterShader::getInstance()->use();
PointEmitterShader::getInstance()->setUniforms(matrix, timediff, active_count, size_increase_factor);
PointEmitterShader::getInstance()->setUniforms(m_previous_frame_matrix, matrix, timediff, active_count, size_increase_factor);
}
m_previous_frame_matrix = matrix;
glBindVertexArray(current_simulation_vao);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tfb_buffers[1]);
@ -617,8 +619,14 @@ void ParticleSystemProxy::render() {
return;
}
if (m_first_execution)
{
generateVAOs();
m_first_execution = false;
simulate();
draw();
m_previous_frame_matrix = getAbsoluteTransformation();
m_first_execution = false;
}
else
{
simulate();
draw();
}
}

View File

@ -40,9 +40,12 @@ protected:
float m_color_to[3];
bool m_first_execution;
bool m_randomize_initial_y;
GLuint texture;
/** Previous frame particles emitter source matrix */
core::matrix4 m_previous_frame_matrix;
/** Current count of particles. */
unsigned m_count;
/** Previous count - for error handling only. */

View File

@ -2582,9 +2582,8 @@ void Kart::updateGraphics(float dt, const Vec3& offset_xyz,
// the normal maximum speed of the kart.
if(nitro_frac>1.0f) nitro_frac = 1.0f;
}
// speed * dt is the new size of the box in which particles start
m_kart_gfx->updateNitroGraphics(nitro_frac, getSpeed()*dt);
m_kart_gfx->updateNitroGraphics(nitro_frac);
// Handle leaning of karts
// -----------------------
// Note that we compare with maximum speed of the kart, not

View File

@ -350,11 +350,10 @@ void KartGFX::update(float dt)
} // update
// ----------------------------------------------------------------------------
/** Updates nitro dependent particle effects (and box sizes).
/** Updates nitro dependent particle effects.
* \param nitro_frac Nitro fraction/
* \param new_size New size of the box in which new particles are emitted.
*/
void KartGFX::updateNitroGraphics(float nitro_frac, float new_size)
void KartGFX::updateNitroGraphics(float nitro_frac)
{
// Upate particle effects (creation rate, and emitter size
// depending on speed)
@ -375,11 +374,6 @@ void KartGFX::updateNitroGraphics(float nitro_frac, float new_size)
setCreationRateAbsolute(KartGFX::KGFX_NITROSMOKE2, 0);
m_nitro_light->setVisible(false);
}
resizeBox(KartGFX::KGFX_NITRO1, new_size);
resizeBox(KartGFX::KGFX_NITRO2, new_size);
resizeBox(KartGFX::KGFX_NITROSMOKE1, new_size);
resizeBox(KartGFX::KGFX_NITROSMOKE2, new_size);
resizeBox(KartGFX::KGFX_ZIPPER, new_size);
} // updateGraphics

View File

@ -99,7 +99,7 @@ public:
void setCreationRateRelative(const KartGFXType type, float f);
void updateTerrain(const ParticleKind *pk);
void update(float dt);
void updateNitroGraphics(float f, float new_size);
void updateNitroGraphics(float f);
void updateSkidLight(unsigned int level);
}; // KartWGFX