[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 mat4 origin; uniform float system_phase; uniform float prev_system_phase; uniform float total_particles; uniform float explosiveness; uniform vec4 time; uniform float delta; uniform vec3 gravity; uniform int attractor_count; uniform Attractor attractors[MAX_ATTRACTORS]; 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: VERTEX_SHADER_GLOBALS #if defined(USE_MATERIAL) layout(std140) uniform UniformData { //ubo:0 MATERIAL_UNIFORMS }; #endif void main() { bool apply_forces=true; bool apply_velocity=true; float mass = 1.0; float restart_phase = float(gl_InstanceID)/total_particles; restart_phase*= explosiveness; bool restart=false; bool active = out_velocity_active.a > 0.5; if (system_phase > prev_system_phase) { restart = prev_system_phase < restart_phase && system_phase >= restart_phase; } else { restart = prev_system_phase < restart_phase || system_phase >= restart_phase; } if (restart) { active=true; } out_color=color; out_velocity_active=velocity_active; out_custom=custom; mat4 xform = transpose(mat4(xform_1,xform_2,xform_3,vec4(vec3(0.0),1.0))); out_rot_active=rot_active; if (active) { //execute shader { VERTEX_SHADER_CODE } #if !defined(DISABLE_FORCE) { vec3 force = gravity; for(int i=0;i0 && 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_seed.xyz += force * delta; } #endif #if !defined(DISABLE_VELOCITY) { out_pos_lifetime.xyz += out_velocity_seed.xyz * delta; } #endif } xform = transpose(xform); out_velocity_active.a = mix(0.0,1.0,active); out_xform_1 = xform[0]; out_xform_2 = xform[1]; out_xform_3 = xform[2]; } [fragment] //any code here is never executed, stuff is filled just so it works FRAGMENT_SHADER_GLOBALS #if defined(USE_MATERIAL) layout(std140) uniform UniformData { MATERIAL_UNIFORMS }; #endif void main() { { FRAGMENT_SHADER_CODE } }