diff options
Diffstat (limited to 'drivers/gles2/shaders/particles.glsl')
-rw-r--r-- | drivers/gles2/shaders/particles.glsl | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/drivers/gles2/shaders/particles.glsl b/drivers/gles2/shaders/particles.glsl new file mode 100644 index 0000000000..a62c124dfe --- /dev/null +++ b/drivers/gles2/shaders/particles.glsl @@ -0,0 +1,260 @@ +[vertex] + + + +layout(location=0) in highp vec4 color; +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) + +layout(std140) uniform UniformData { //ubo:0 + +MATERIAL_UNIFORMS + +}; + +#endif + + +VERTEX_SHADER_GLOBALS + +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 + + { +VERTEX_SHADER_CODE + } + +#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 + +} + +[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 + } +} |