diff options
Diffstat (limited to 'servers/rendering/renderer_rd/shaders/particles.glsl')
-rw-r--r-- | servers/rendering/renderer_rd/shaders/particles.glsl | 291 |
1 files changed, 166 insertions, 125 deletions
diff --git a/servers/rendering/renderer_rd/shaders/particles.glsl b/servers/rendering/renderer_rd/shaders/particles.glsl index cb6d8dc7f6..beaff10793 100644 --- a/servers/rendering/renderer_rd/shaders/particles.glsl +++ b/servers/rendering/renderer_rd/shaders/particles.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; @@ -76,6 +76,11 @@ struct FrameParams { float time; float delta; + uint frame; + uint pad0; + uint pad1; + uint pad2; + uint random_seed; uint attractor_count; uint collider_count; @@ -92,10 +97,16 @@ layout(set = 1, binding = 0, std430) restrict buffer FrameHistory { } frame_history; +#define PARTICLE_FLAG_ACTIVE uint(1) +#define PARTICLE_FLAG_STARTED uint(2) +#define PARTICLE_FLAG_TRAILED uint(4) +#define PARTICLE_FRAME_MASK uint(0xFFFF) +#define PARTICLE_FRAME_SHIFT uint(16) + struct ParticleData { mat4 xform; vec3 velocity; - bool is_active; + uint flags; vec4 color; vec4 custom; }; @@ -146,11 +157,11 @@ layout(set = 2, binding = 1) uniform texture2D height_field_texture; /* SET 3: MATERIAL */ -#ifdef USE_MATERIAL_UNIFORMS +#ifdef MATERIAL_UNIFORMS_USED layout(set = 3, binding = 0, std140) uniform MaterialUniforms{ - /* clang-format off */ -MATERIAL_UNIFORMS - /* clang-format on */ + +#MATERIAL_UNIFORMS + } material; #endif @@ -162,7 +173,7 @@ layout(push_constant, binding = 0, std430) uniform Params { bool use_fractional_delta; bool sub_emitter_mode; bool can_emit; - uint pad; + bool trail_pass; } params; @@ -196,15 +207,19 @@ bool emit_subparticle(mat4 p_xform, vec3 p_velocity, vec4 p_color, vec4 p_custom return true; } -/* clang-format off */ - -COMPUTE_SHADER_GLOBALS - -/* clang-format on */ +#GLOBALS void main() { uint particle = gl_GlobalInvocationID.x; + if (params.trail_size > 1) { + if (params.trail_pass) { + particle += (particle / (params.trail_size - 1)) + 1; + } else { + particle *= params.trail_size; + } + } + if (particle >= params.total_particles * params.trail_size) { return; //discard } @@ -233,7 +248,7 @@ void main() { PARTICLE.color = vec4(1.0); PARTICLE.custom = vec4(0.0); PARTICLE.velocity = vec3(0.0); - PARTICLE.is_active = false; + PARTICLE.flags = 0; PARTICLE.xform = mat4( vec4(1.0, 0.0, 0.0, 0.0), vec4(0.0, 1.0, 0.0, 0.0), @@ -241,6 +256,29 @@ void main() { vec4(0.0, 0.0, 0.0, 1.0)); } + //clear started flag if set + + if (params.trail_pass) { + //trail started + uint src_idx = index * params.trail_size; + if (bool(particles.data[src_idx].flags & PARTICLE_FLAG_STARTED)) { + //save start conditions for trails + PARTICLE.color = particles.data[src_idx].color; + PARTICLE.custom = particles.data[src_idx].custom; + PARTICLE.velocity = particles.data[src_idx].velocity; + PARTICLE.flags = PARTICLE_FLAG_TRAILED | ((frame_history.data[0].frame & PARTICLE_FRAME_MASK) << PARTICLE_FRAME_SHIFT); //mark it as trailed, save in which frame it will start + PARTICLE.xform = particles.data[src_idx].xform; + } + + if (bool(PARTICLE.flags & PARTICLE_FLAG_TRAILED) && ((PARTICLE.flags >> PARTICLE_FRAME_SHIFT) == (FRAME.frame & PARTICLE_FRAME_MASK))) { //check this is trailed and see if it should start now + // we just assume that this is the first frame of the particle, the rest is deterministic + PARTICLE.flags = PARTICLE_FLAG_ACTIVE | (particles.data[src_idx].flags & (PARTICLE_FRAME_MASK << PARTICLE_FRAME_SHIFT)); + return; //- this appears like it should be correct, but it seems not to be.. wonder why. + } + } else { + PARTICLE.flags &= ~PARTICLE_FLAG_STARTED; + } + bool collided = false; vec3 collision_normal = vec3(0.0); float collision_depth = 0.0; @@ -249,14 +287,121 @@ void main() { #if !defined(DISABLE_VELOCITY) - if (PARTICLE.is_active) { + if (bool(PARTICLE.flags & PARTICLE_FLAG_ACTIVE)) { PARTICLE.xform[3].xyz += PARTICLE.velocity * local_delta; } #endif - /* Process physics if active */ + if (!params.trail_pass && params.sub_emitter_mode) { + if (!bool(PARTICLE.flags & PARTICLE_FLAG_ACTIVE)) { + int src_index = atomicAdd(src_particles.particle_count, -1) - 1; + + if (src_index >= 0) { + PARTICLE.flags = (PARTICLE_FLAG_ACTIVE | PARTICLE_FLAG_STARTED | (FRAME.cycle << PARTICLE_FRAME_SHIFT)); + restart = true; + + if (bool(src_particles.data[src_index].flags & EMISSION_FLAG_HAS_POSITION)) { + PARTICLE.xform[3] = src_particles.data[src_index].xform[3]; + } else { + PARTICLE.xform[3] = vec4(0, 0, 0, 1); + restart_position = true; + } + if (bool(src_particles.data[src_index].flags & EMISSION_FLAG_HAS_ROTATION_SCALE)) { + PARTICLE.xform[0] = src_particles.data[src_index].xform[0]; + PARTICLE.xform[1] = src_particles.data[src_index].xform[1]; + PARTICLE.xform[2] = src_particles.data[src_index].xform[2]; + } else { + PARTICLE.xform[0] = vec4(1, 0, 0, 0); + PARTICLE.xform[1] = vec4(0, 1, 0, 0); + PARTICLE.xform[2] = vec4(0, 0, 1, 0); + restart_rotation_scale = true; + } + if (bool(src_particles.data[src_index].flags & EMISSION_FLAG_HAS_VELOCITY)) { + PARTICLE.velocity = src_particles.data[src_index].velocity; + } else { + PARTICLE.velocity = vec3(0); + restart_velocity = true; + } + if (bool(src_particles.data[src_index].flags & EMISSION_FLAG_HAS_COLOR)) { + PARTICLE.color = src_particles.data[src_index].color; + } else { + PARTICLE.color = vec4(1); + restart_color = true; + } - if (PARTICLE.is_active) { + if (bool(src_particles.data[src_index].flags & EMISSION_FLAG_HAS_CUSTOM)) { + PARTICLE.custom = src_particles.data[src_index].custom; + } else { + PARTICLE.custom = vec4(0); + restart_custom = true; + } + } + } + + } else if (FRAME.emitting) { + float restart_phase = float(index) / float(params.total_particles); + + if (FRAME.randomness > 0.0) { + uint seed = FRAME.cycle; + if (restart_phase >= FRAME.system_phase) { + seed -= uint(1); + } + seed *= uint(params.total_particles); + seed += uint(index); + float random = float(hash(seed) % uint(65536)) / 65536.0; + restart_phase += FRAME.randomness * random * 1.0 / float(params.total_particles); + } + + restart_phase *= (1.0 - FRAME.explosiveness); + + if (FRAME.system_phase > FRAME.prev_system_phase) { + // restart_phase >= prev_system_phase is used so particles emit in the first frame they are processed + + if (restart_phase >= FRAME.prev_system_phase && restart_phase < FRAME.system_phase) { + restart = true; + if (params.use_fractional_delta) { + local_delta = (FRAME.system_phase - restart_phase) * params.lifetime; + } + } + + } else if (FRAME.delta > 0.0) { + if (restart_phase >= FRAME.prev_system_phase) { + restart = true; + if (params.use_fractional_delta) { + local_delta = (1.0 - restart_phase + FRAME.system_phase) * params.lifetime; + } + + } else if (restart_phase < FRAME.system_phase) { + restart = true; + if (params.use_fractional_delta) { + local_delta = (FRAME.system_phase - restart_phase) * params.lifetime; + } + } + } + + if (params.trail_pass) { + restart = false; + } + + if (restart) { + PARTICLE.flags = FRAME.emitting ? (PARTICLE_FLAG_ACTIVE | PARTICLE_FLAG_STARTED | (FRAME.cycle << PARTICLE_FRAME_SHIFT)) : 0; + restart_position = true; + restart_rotation_scale = true; + restart_velocity = true; + restart_color = true; + restart_custom = true; + } + } + + bool particle_active = bool(PARTICLE.flags & PARTICLE_FLAG_ACTIVE); + + uint particle_number = (PARTICLE.flags >> PARTICLE_FRAME_SHIFT) * uint(params.total_particles) + index; + + if (restart && particle_active) { +#CODE : START + } + + if (particle_active) { for (uint i = 0; i < FRAME.attractor_count; i++) { vec3 dir; float amount; @@ -434,116 +579,12 @@ void main() { } } - if (params.sub_emitter_mode) { - if (!PARTICLE.is_active) { - int src_index = atomicAdd(src_particles.particle_count, -1) - 1; - - if (src_index >= 0) { - PARTICLE.is_active = true; - restart = true; - - if (bool(src_particles.data[src_index].flags & EMISSION_FLAG_HAS_POSITION)) { - PARTICLE.xform[3] = src_particles.data[src_index].xform[3]; - } else { - PARTICLE.xform[3] = vec4(0, 0, 0, 1); - restart_position = true; - } - if (bool(src_particles.data[src_index].flags & EMISSION_FLAG_HAS_ROTATION_SCALE)) { - PARTICLE.xform[0] = src_particles.data[src_index].xform[0]; - PARTICLE.xform[1] = src_particles.data[src_index].xform[1]; - PARTICLE.xform[2] = src_particles.data[src_index].xform[2]; - } else { - PARTICLE.xform[0] = vec4(1, 0, 0, 0); - PARTICLE.xform[1] = vec4(0, 1, 0, 0); - PARTICLE.xform[2] = vec4(0, 0, 1, 0); - restart_rotation_scale = true; - } - if (bool(src_particles.data[src_index].flags & EMISSION_FLAG_HAS_VELOCITY)) { - PARTICLE.velocity = src_particles.data[src_index].velocity; - } else { - PARTICLE.velocity = vec3(0); - restart_velocity = true; - } - if (bool(src_particles.data[src_index].flags & EMISSION_FLAG_HAS_COLOR)) { - PARTICLE.color = src_particles.data[src_index].color; - } else { - PARTICLE.color = vec4(1); - restart_color = true; - } - - if (bool(src_particles.data[src_index].flags & EMISSION_FLAG_HAS_CUSTOM)) { - PARTICLE.custom = src_particles.data[src_index].custom; - } else { - PARTICLE.custom = vec4(0); - restart_custom = true; - } - } - } - - } else if (FRAME.emitting) { - float restart_phase = float(index) / float(params.total_particles); - - if (FRAME.randomness > 0.0) { - uint seed = FRAME.cycle; - if (restart_phase >= FRAME.system_phase) { - seed -= uint(1); - } - seed *= uint(params.total_particles); - seed += uint(index); - float random = float(hash(seed) % uint(65536)) / 65536.0; - restart_phase += FRAME.randomness * random * 1.0 / float(params.total_particles); - } - - restart_phase *= (1.0 - FRAME.explosiveness); - - if (FRAME.system_phase > FRAME.prev_system_phase) { - // restart_phase >= prev_system_phase is used so particles emit in the first frame they are processed - - if (restart_phase >= FRAME.prev_system_phase && restart_phase < FRAME.system_phase) { - restart = true; - if (params.use_fractional_delta) { - local_delta = (FRAME.system_phase - restart_phase) * params.lifetime; - } - } - - } else if (FRAME.delta > 0.0) { - if (restart_phase >= FRAME.prev_system_phase) { - restart = true; - if (params.use_fractional_delta) { - local_delta = (1.0 - restart_phase + FRAME.system_phase) * params.lifetime; - } - - } else if (restart_phase < FRAME.system_phase) { - restart = true; - if (params.use_fractional_delta) { - local_delta = (FRAME.system_phase - restart_phase) * params.lifetime; - } - } - } - - uint current_cycle = FRAME.cycle; - - if (FRAME.system_phase < restart_phase) { - current_cycle -= uint(1); - } - - uint particle_number = current_cycle * uint(params.total_particles) + particle; - - if (restart) { - PARTICLE.is_active = FRAME.emitting; - restart_position = true; - restart_rotation_scale = true; - restart_velocity = true; - restart_color = true; - restart_custom = true; - } + if (particle_active) { +#CODE : PROCESS } - if (PARTICLE.is_active) { - /* clang-format off */ - -COMPUTE_SHADER_CODE - - /* clang-format on */ + PARTICLE.flags &= ~PARTICLE_FLAG_ACTIVE; + if (particle_active) { + PARTICLE.flags |= PARTICLE_FLAG_ACTIVE; } } |