When the particles position is computed, the position of the emitter in both current and previous frames is now taken into account. There is no more visual artifact when the particles velocity and emitter velocity are not aligned (for example with nitro particles when a kart is skidding)
This commit is contained in:
parent
43d5dbeb3e
commit
01c8b25cb6
@ -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,44 @@ 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 = 1. - 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(previous_frame_position,
|
||||
current_frame_position,
|
||||
coeff);
|
||||
|
||||
vec4 updated_initial_velocity = mix(previous_frame_sourcematrix * vec4(particle_velocity_initial, 0.0),
|
||||
sourcematrix * vec4(particle_velocity_initial, 0.0),
|
||||
coeff) ; //TODO: add emitter speed
|
||||
//+ (current_frame_position - previous_frame_position) / dt;
|
||||
|
||||
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.);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,10 @@ protected:
|
||||
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. */
|
||||
|
Loading…
x
Reference in New Issue
Block a user