summaryrefslogtreecommitdiff
path: root/drivers/gles2/shaders/particles.glsl
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gles2/shaders/particles.glsl')
-rw-r--r--drivers/gles2/shaders/particles.glsl258
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 */