diff options
Diffstat (limited to 'drivers/gles2/shaders/particles.glsl')
-rw-r--r-- | drivers/gles2/shaders/particles.glsl | 258 |
1 files changed, 258 insertions, 0 deletions
diff --git a/drivers/gles2/shaders/particles.glsl b/drivers/gles2/shaders/particles.glsl new file mode 100644 index 0000000000..b7fcb94ed2 --- /dev/null +++ b/drivers/gles2/shaders/particles.glsl @@ -0,0 +1,258 @@ +/* clang-format off */ +[vertex] + +layout(location = 0) in highp vec4 color; +/* clang-format on */ +layout(location = 1) in highp vec4 velocity_active; +layout(location = 2) in highp vec4 custom; +layout(location = 3) in highp vec4 xform_1; +layout(location = 4) in highp vec4 xform_2; +layout(location = 5) in highp vec4 xform_3; + +struct Attractor { + vec3 pos; + vec3 dir; + float radius; + float eat_radius; + float strength; + float attenuation; +}; + +#define MAX_ATTRACTORS 64 + +uniform bool emitting; +uniform float system_phase; +uniform float prev_system_phase; +uniform int total_particles; +uniform float explosiveness; +uniform float randomness; +uniform float time; +uniform float delta; + +uniform int attractor_count; +uniform Attractor attractors[MAX_ATTRACTORS]; +uniform bool clear; +uniform uint cycle; +uniform float lifetime; +uniform mat4 emission_transform; +uniform uint random_seed; + +out highp vec4 out_color; //tfb: +out highp vec4 out_velocity_active; //tfb: +out highp vec4 out_custom; //tfb: +out highp vec4 out_xform_1; //tfb: +out highp vec4 out_xform_2; //tfb: +out highp vec4 out_xform_3; //tfb: + +#if defined(USE_MATERIAL) + +/* clang-format off */ +layout(std140) uniform UniformData { //ubo:0 + +MATERIAL_UNIFORMS +}; +/* clang-format on */ + +#endif + +/* clang-format off */ + +VERTEX_SHADER_GLOBALS + +/* clang-format on */ + +uint hash(uint x) { + x = ((x >> uint(16)) ^ x) * uint(0x45d9f3b); + x = ((x >> uint(16)) ^ x) * uint(0x45d9f3b); + x = (x >> uint(16)) ^ x; + return x; +} + +void main() { +#ifdef PARTICLES_COPY + + out_color = color; + out_velocity_active = velocity_active; + out_custom = custom; + out_xform_1 = xform_1; + out_xform_2 = xform_2; + out_xform_3 = xform_3; + +#else + + bool apply_forces = true; + bool apply_velocity = true; + float local_delta = delta; + + float mass = 1.0; + + float restart_phase = float(gl_VertexID) / float(total_particles); + + if (randomness > 0.0) { + uint seed = cycle; + if (restart_phase >= system_phase) { + seed -= uint(1); + } + seed *= uint(total_particles); + seed += uint(gl_VertexID); + float random = float(hash(seed) % uint(65536)) / 65536.0; + restart_phase += randomness * random * 1.0 / float(total_particles); + } + + restart_phase *= (1.0 - explosiveness); + bool restart = false; + bool shader_active = velocity_active.a > 0.5; + + if (system_phase > prev_system_phase) { + // restart_phase >= prev_system_phase is used so particles emit in the first frame they are processed + + if (restart_phase >= prev_system_phase && restart_phase < system_phase) { + restart = true; +#ifdef USE_FRACTIONAL_DELTA + local_delta = (system_phase - restart_phase) * lifetime; +#endif + } + + } else { + if (restart_phase >= prev_system_phase) { + restart = true; +#ifdef USE_FRACTIONAL_DELTA + local_delta = (1.0 - restart_phase + system_phase) * lifetime; +#endif + } else if (restart_phase < system_phase) { + restart = true; +#ifdef USE_FRACTIONAL_DELTA + local_delta = (system_phase - restart_phase) * lifetime; +#endif + } + } + + uint current_cycle = cycle; + + if (system_phase < restart_phase) { + current_cycle -= uint(1); + } + + uint particle_number = current_cycle * uint(total_particles) + uint(gl_VertexID); + int index = int(gl_VertexID); + + if (restart) { + shader_active = emitting; + } + + mat4 xform; + +#if defined(ENABLE_KEEP_DATA) + if (clear) { +#else + if (clear || restart) { +#endif + out_color = vec4(1.0); + out_velocity_active = vec4(0.0); + out_custom = vec4(0.0); + if (!restart) + shader_active = false; + + xform = mat4( + vec4(1.0, 0.0, 0.0, 0.0), + vec4(0.0, 1.0, 0.0, 0.0), + vec4(0.0, 0.0, 1.0, 0.0), + vec4(0.0, 0.0, 0.0, 1.0)); + } else { + out_color = color; + out_velocity_active = velocity_active; + out_custom = custom; + xform = transpose(mat4(xform_1, xform_2, xform_3, vec4(vec3(0.0), 1.0))); + } + + if (shader_active) { + //execute shader + + { + /* clang-format off */ + +VERTEX_SHADER_CODE + + /* clang-format on */ + } + +#if !defined(DISABLE_FORCE) + + if (false) { + vec3 force = vec3(0.0); + for (int i = 0; i < attractor_count; i++) { + vec3 rel_vec = xform[3].xyz - attractors[i].pos; + float dist = length(rel_vec); + if (attractors[i].radius < dist) + continue; + if (attractors[i].eat_radius > 0.0 && attractors[i].eat_radius > dist) { + out_velocity_active.a = 0.0; + } + + rel_vec = normalize(rel_vec); + + float attenuation = pow(dist / attractors[i].radius, attractors[i].attenuation); + + if (attractors[i].dir == vec3(0.0)) { + //towards center + force += attractors[i].strength * rel_vec * attenuation * mass; + } else { + force += attractors[i].strength * attractors[i].dir * attenuation * mass; + } + } + + out_velocity_active.xyz += force * local_delta; + } +#endif + +#if !defined(DISABLE_VELOCITY) + + if (true) { + xform[3].xyz += out_velocity_active.xyz * local_delta; + } +#endif + } else { + xform = mat4(0.0); + } + + xform = transpose(xform); + + out_velocity_active.a = mix(0.0, 1.0, shader_active); + + out_xform_1 = xform[0]; + out_xform_2 = xform[1]; + out_xform_3 = xform[2]; + +#endif //PARTICLES_COPY +} + +/* clang-format off */ +[fragment] + +//any code here is never executed, stuff is filled just so it works + +#if defined(USE_MATERIAL) + +layout(std140) uniform UniformData { + +MATERIAL_UNIFORMS +}; + +#endif + +FRAGMENT_SHADER_GLOBALS + +void main() { + { + +LIGHT_SHADER_CODE + + } + + { + +FRAGMENT_SHADER_CODE + + } +} +/* clang-format on */ |