| 
									
										
										
										
											2020-08-19 10:38:24 -03:00
										 |  |  | #[compute] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #version 450 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-13 17:01:43 -03:00
										 |  |  | #VERSION_DEFINES | 
					
						
							| 
									
										
										
										
											2020-08-19 10:38:24 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-27 12:43:49 -03:00
										 |  |  | #define PARTICLE_FLAG_ACTIVE uint(1) | 
					
						
							|  |  |  | #define PARTICLE_FLAG_STARTED uint(2) | 
					
						
							|  |  |  | #define PARTICLE_FLAG_TRAILED uint(4) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-19 10:38:24 -03:00
										 |  |  | struct ParticleData { | 
					
						
							|  |  |  | 	mat4 xform; | 
					
						
							|  |  |  | 	vec3 velocity; | 
					
						
							| 
									
										
										
										
											2021-04-27 12:43:49 -03:00
										 |  |  | 	uint flags; | 
					
						
							| 
									
										
										
										
											2020-08-19 10:38:24 -03:00
										 |  |  | 	vec4 color; | 
					
						
							|  |  |  | 	vec4 custom; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | layout(set = 0, binding = 1, std430) restrict readonly buffer Particles { | 
					
						
							|  |  |  | 	ParticleData data[]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | particles; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | layout(set = 0, binding = 2, std430) restrict writeonly buffer Transforms { | 
					
						
							|  |  |  | 	vec4 data[]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | instances; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef USE_SORT_BUFFER | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | layout(set = 1, binding = 0, std430) restrict buffer SortBuffer { | 
					
						
							|  |  |  | 	vec2 data[]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | sort_buffer; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif // USE_SORT_BUFFER | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-27 12:43:49 -03:00
										 |  |  | layout(set = 2, binding = 0, std430) restrict readonly buffer TrailBindPoses { | 
					
						
							|  |  |  | 	mat4 data[]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | trail_bind_poses; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-19 10:38:24 -03:00
										 |  |  | layout(push_constant, binding = 0, std430) uniform Params { | 
					
						
							|  |  |  | 	vec3 sort_direction; | 
					
						
							|  |  |  | 	uint total_particles; | 
					
						
							| 
									
										
										
										
											2021-04-27 12:43:49 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	uint trail_size; | 
					
						
							|  |  |  | 	uint trail_total; | 
					
						
							|  |  |  | 	float frame_delta; | 
					
						
							|  |  |  | 	float frame_remainder; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vec3 align_up; | 
					
						
							|  |  |  | 	uint align_mode; | 
					
						
							| 
									
										
										
										
											2020-08-19 10:38:24 -03:00
										 |  |  | } | 
					
						
							|  |  |  | params; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-27 12:43:49 -03:00
										 |  |  | #define TRANSFORM_ALIGN_DISABLED 0 | 
					
						
							|  |  |  | #define TRANSFORM_ALIGN_Z_BILLBOARD 1 | 
					
						
							|  |  |  | #define TRANSFORM_ALIGN_Y_TO_VELOCITY 2 | 
					
						
							|  |  |  | #define TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY 3 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-19 10:38:24 -03:00
										 |  |  | void main() { | 
					
						
							|  |  |  | #ifdef MODE_FILL_SORT_BUFFER | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	uint particle = gl_GlobalInvocationID.x; | 
					
						
							|  |  |  | 	if (particle >= params.total_particles) { | 
					
						
							|  |  |  | 		return; //discard | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-27 12:43:49 -03:00
										 |  |  | 	uint src_particle = particle; | 
					
						
							|  |  |  | 	if (params.trail_size > 1) { | 
					
						
							|  |  |  | 		src_particle = src_particle * params.trail_size + params.trail_size / 2; //use trail center for sorting | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	sort_buffer.data[particle].x = dot(params.sort_direction, particles.data[src_particle].xform[3].xyz); | 
					
						
							| 
									
										
										
										
											2020-08-19 10:38:24 -03:00
										 |  |  | 	sort_buffer.data[particle].y = float(particle); | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef MODE_FILL_INSTANCES | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	uint particle = gl_GlobalInvocationID.x; | 
					
						
							|  |  |  | 	uint write_offset = gl_GlobalInvocationID.x * (3 + 1 + 1); //xform + color + custom | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (particle >= params.total_particles) { | 
					
						
							|  |  |  | 		return; //discard | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef USE_SORT_BUFFER | 
					
						
							| 
									
										
										
										
											2021-04-27 12:43:49 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (params.trail_size > 1) { | 
					
						
							|  |  |  | 		particle = uint(sort_buffer.data[particle / params.trail_size].y) + (particle % params.trail_size); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		particle = uint(sort_buffer.data[particle].y); //use index from sort buffer | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-08-19 10:38:24 -03:00
										 |  |  | #endif | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mat4 txform; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-27 12:43:49 -03:00
										 |  |  | 	if (bool(particles.data[particle].flags & PARTICLE_FLAG_ACTIVE) || bool(particles.data[particle].flags & PARTICLE_FLAG_TRAILED)) { | 
					
						
							|  |  |  | 		txform = particles.data[particle].xform; | 
					
						
							|  |  |  | 		if (params.trail_size > 1) { | 
					
						
							|  |  |  | 			// since the steps dont fit precisely in the history frames, must do a tiny bit of | 
					
						
							|  |  |  | 			// interpolation to get them close to their intended location. | 
					
						
							|  |  |  | 			uint part_ofs = particle % params.trail_size; | 
					
						
							|  |  |  | 			float natural_ofs = fract((float(part_ofs) / float(params.trail_size)) * float(params.trail_total)) * params.frame_delta; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			txform[3].xyz -= particles.data[particle].velocity * natural_ofs; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		switch (params.align_mode) { | 
					
						
							|  |  |  | 			case TRANSFORM_ALIGN_DISABLED: { | 
					
						
							|  |  |  | 			} break; //nothing | 
					
						
							|  |  |  | 			case TRANSFORM_ALIGN_Z_BILLBOARD: { | 
					
						
							|  |  |  | 				mat3 local = mat3(normalize(cross(params.align_up, params.sort_direction)), params.align_up, params.sort_direction); | 
					
						
							|  |  |  | 				local = local * mat3(txform); | 
					
						
							|  |  |  | 				txform[0].xyz = local[0]; | 
					
						
							|  |  |  | 				txform[1].xyz = local[1]; | 
					
						
							|  |  |  | 				txform[2].xyz = local[2]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			} break; | 
					
						
							|  |  |  | 			case TRANSFORM_ALIGN_Y_TO_VELOCITY: { | 
					
						
							|  |  |  | 				vec3 v = particles.data[particle].velocity; | 
					
						
							|  |  |  | 				float s = (length(txform[0]) + length(txform[1]) + length(txform[2])) / 3.0; | 
					
						
							|  |  |  | 				if (length(v) > 0.0) { | 
					
						
							|  |  |  | 					txform[1].xyz = normalize(v); | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					txform[1].xyz = normalize(txform[1].xyz); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				txform[0].xyz = normalize(cross(txform[1].xyz, txform[2].xyz)); | 
					
						
							|  |  |  | 				txform[2].xyz = vec3(0.0, 0.0, 1.0) * s; | 
					
						
							|  |  |  | 				txform[0].xyz *= s; | 
					
						
							|  |  |  | 				txform[1].xyz *= s; | 
					
						
							|  |  |  | 			} break; | 
					
						
							|  |  |  | 			case TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY: { | 
					
						
							|  |  |  | 				vec3 v = particles.data[particle].velocity; | 
					
						
							|  |  |  | 				vec3 sv = v - params.sort_direction * dot(params.sort_direction, v); //screen velocity | 
					
						
							|  |  |  | 				float s = (length(txform[0]) + length(txform[1]) + length(txform[2])) / 3.0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if (length(sv) == 0) { | 
					
						
							|  |  |  | 					sv = params.align_up; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				sv = normalize(sv); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				txform[0].xyz = normalize(cross(sv, params.sort_direction)) * s; | 
					
						
							|  |  |  | 				txform[1].xyz = sv * s; | 
					
						
							|  |  |  | 				txform[2].xyz = params.sort_direction * s; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			} break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		txform[3].xyz += particles.data[particle].velocity * params.frame_remainder; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (params.trail_size > 1) { | 
					
						
							|  |  |  | 			uint part_ofs = particle % params.trail_size; | 
					
						
							|  |  |  | 			txform = txform * trail_bind_poses.data[part_ofs]; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		txform = transpose(txform); | 
					
						
							| 
									
										
										
										
											2020-08-19 10:38:24 -03:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		txform = mat4(vec4(0.0), vec4(0.0), vec4(0.0), vec4(0.0)); //zero scale, becomes invisible | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	instances.data[write_offset + 0] = txform[0]; | 
					
						
							|  |  |  | 	instances.data[write_offset + 1] = txform[1]; | 
					
						
							|  |  |  | 	instances.data[write_offset + 2] = txform[2]; | 
					
						
							|  |  |  | 	instances.data[write_offset + 3] = particles.data[particle].color; | 
					
						
							|  |  |  | 	instances.data[write_offset + 4] = particles.data[particle].custom; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | } |