gedeng/Shader/particle_update.gs

129 lines
4.0 KiB
GLSL

#version 430
layout(points) in;
layout(points) out;
layout(max_vertices = 40) out;
// All that we get from vertex shader
in vec3 position_pass[];
in vec3 velocity_pass[];
in vec3 color_pass[];
in float lifetime_pass[];
in float size_pass[];
in float type_pass[];
// All that we send further
out vec3 position_out;
out vec3 velocity_out;
out vec3 color_out;
out float lifetime_out;
out float size_out;
out float type_out;
uniform vec3 spawn_position; // Position where new particles are spawned
uniform vec3 spawn_gravity; // Gravity vector for particles - updates velocity of particles
uniform vec3 spawn_velocity_min; // Velocity of new particle - from min to (min+range)
uniform vec3 spawn_velocity_range;
uniform vec3 spawn_color;
uniform float spawn_size;
uniform float spawn_lifetime_min, spawn_lifetime_range; // Life of new particle - from min to (min+range)
uniform float delta; // Time passed since last frame
uniform vec3 random_seed; // Seed number for our random number function
vec3 local_seed;
uniform int number_to_generate; // How many particles will be generated next time, if greater than zero, particles are generated
float random_zero_to_one() {
uint n = floatBitsToUint(local_seed.y * 214013.0 + local_seed.x * 2531011.0 + local_seed.z * 141251.0);
n = n * (n * n * 15731u + 789221u);
n = (n >> 9u) | 0x3F800000u;
float fRes = 2.0 - uintBitsToFloat(n);
local_seed = vec3(local_seed.x + 147158.0 * fRes, local_seed.y*fRes + 415161.0 * fRes, local_seed.z + 324154.0*fRes);
return fRes;
}
void main() {
local_seed = random_seed;
// gl_Position doesn't matter now, as rendering is discarded
position_out = position_pass[0];
velocity_out = velocity_pass[0];
if(type_pass[0] != 0.0) position_out += velocity_out * delta;
if(type_pass[0] != 0.0) velocity_out += spawn_gravity * delta;
color_out = color_pass[0];
lifetime_out = lifetime_pass[0] - delta;
size_out = size_pass[0];
type_out = type_pass[0];
if(type_out == 0.0) {
// This is the emitter particle
EmitVertex();
EndPrimitive();
for(int i = 0; i < number_to_generate; i++)
{
position_out = spawn_position;
velocity_out = spawn_velocity_min + vec3(
spawn_velocity_range.x * random_zero_to_one(),
spawn_velocity_range.y * random_zero_to_one(),
spawn_velocity_range.z * random_zero_to_one()
);
color_out = spawn_color;
lifetime_out = spawn_lifetime_min + spawn_lifetime_range * random_zero_to_one();
size_out = spawn_size;
type_out = 1.0;
EmitVertex();
EndPrimitive();
}
} else if (lifetime_out > 0.0) {
// This is a normal particle which is still alive
EmitVertex();
EndPrimitive();
} else if (type_out == 1.0) {
// The lifetime is over -- transform this particle in a new one or discard
for(int i = 0; i < 15; i++) {
// Keep the position
velocity_out = (spawn_velocity_min + vec3(
spawn_velocity_range.x * random_zero_to_one(),
spawn_velocity_range.y * random_zero_to_one(),
spawn_velocity_range.z * random_zero_to_one()
)) * 0.75;
color_out = vec3(1.0, 0, 0);
lifetime_out = spawn_lifetime_min + spawn_lifetime_range * random_zero_to_one();
size_out = spawn_size * 2.0;
type_out = 2.0;
EmitVertex();
EndPrimitive();
}
} else if (type_out == 2.0) {
// The lifetime is over -- transform this particle in a new one or discard
for(int i = 0; i < 10; i++) {
// Keep the position
velocity_out = (spawn_velocity_min + vec3(
spawn_velocity_range.x * random_zero_to_one(),
spawn_velocity_range.y * random_zero_to_one(),
spawn_velocity_range.z * random_zero_to_one()
)) * 0.5;
color_out = vec3(0.0, 1.0, 0);
lifetime_out = (spawn_lifetime_min + spawn_lifetime_range * random_zero_to_one()) * 0.3;
size_out = spawn_size * 0.75;
type_out = 3.0;
EmitVertex();
EndPrimitive();
}
}
}