mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-22 15:33:21 +02:00
76 lines
3.8 KiB
Plaintext
76 lines
3.8 KiB
Plaintext
// rain and snow of the gpu (opengl46_gpu_particles), in every colour pass which draws them: a thread per drop or flake. the
|
|
// particles fill three boxes around the camera, a small dense one and two larger ones, each repeated along the world axes:
|
|
// a particle keeps its place in the box, moved by how far the wind took them all and how far it fell, so nothing is kept
|
|
// from frame to frame. what the camera sees is lit (particle_light.glsl) and drawn as a streak from where it is to where
|
|
// it was a moment ago, seen from the moving camera (particles_precipitation.vert)
|
|
|
|
#include <common>
|
|
#include <weather_common.glsl>
|
|
#include <particle_light.glsl>
|
|
#include <particle_common.glsl>
|
|
|
|
layout(local_size_x = PARTICLE_GROUP_SIZE) in;
|
|
|
|
// x, y: first particles of the second and of the third box, z: particles, w: 1 for snow, 0 for rain
|
|
layout(location = 0) uniform uvec4 counts;
|
|
// xyz: how far the wind took the particles less where the camera is, in each box (metres, 0 to the size of the box); w: how
|
|
// far they fell in it, 0 to 16 sizes of the box
|
|
layout(location = 1) uniform vec4 offsets[3];
|
|
// xyz: size of each box, metres; w unused
|
|
layout(location = 4) uniform vec4 sizes;
|
|
// xyz: velocity of the wind less the one of the camera, m/s; w: speed of the fall
|
|
layout(location = 5) uniform vec4 velocity;
|
|
// x: seconds (for the flutter of the flakes), y: how long a streak lasts, seconds, z: opacity, w: places for the draws
|
|
layout(location = 6) uniform vec4 timing;
|
|
// the world axes around the camera to the view space of the pass
|
|
layout(location = 7) uniform mat4 view;
|
|
// y: how much a particle scatters the light onwards, z: brightness
|
|
layout(location = 11) uniform vec4 options;
|
|
layout(location = 12) uniform vec4 planes[5];
|
|
|
|
void main()
|
|
{
|
|
uint index = gl_GlobalInvocationID.x;
|
|
if (index >= counts.z)
|
|
return;
|
|
uint box = (index < counts.x) ? 0U : (index < counts.y) ? 1U : 2U;
|
|
float size = sizes[box];
|
|
bool snow = counts.w != 0U;
|
|
|
|
uint state = particle_hash(index * 3U + 0x9E3779B9U);
|
|
vec3 home = vec3(particle_random(state), particle_random(state), particle_random(state)) * size;
|
|
// the speed of the fall is (16 + k) / 16 of the common one, so a whole number of sizes of the box (16 of them) of the common
|
|
// fall is a whole number of them for every particle, and the fall can be kept within 16 sizes
|
|
float pace = (16.0 + floor(particle_random(state) * 7.0) - 3.0) / 16.0;
|
|
float width = snow ? mix(0.004, 0.012, particle_random(state)) : mix(0.0012, 0.0025, particle_random(state));
|
|
vec3 move = vec3(velocity.xyz) + vec3(0.0, -velocity.w * pace, 0.0);
|
|
vec3 place = home + offsets[box].xyz - vec3(0.0, offsets[box].w * pace, 0.0);
|
|
if (snow)
|
|
{
|
|
// the flakes flutter about their way
|
|
float amplitude = mix(0.1, 0.35, particle_random(state));
|
|
vec2 frequency = mix(vec2(1.5), vec2(5.0), vec2(particle_random(state), particle_random(state)));
|
|
vec2 phase = vec2(particle_random(state), particle_random(state)) * 6.2831853;
|
|
vec2 angle = frequency * timing.x + phase;
|
|
place.xz += amplitude * sin(angle);
|
|
move.xz += amplitude * frequency * cos(angle);
|
|
}
|
|
// within the box around the camera
|
|
vec3 world = mod(place, size) - 0.5 * size;
|
|
float opacity = timing.z;
|
|
// fading at the walls of the box, where the particles wrap around, and right at the camera
|
|
vec3 walls = abs(world) / (0.5 * size);
|
|
opacity *= 1.0 - smoothstep(0.7, 1.0, max(max(walls.x, walls.y), walls.z));
|
|
opacity *= smoothstep(0.15, 0.6, length(world));
|
|
if (opacity <= 0.002)
|
|
return;
|
|
vec3 tail = -move * timing.y;
|
|
float streak = length(tail);
|
|
if (streak > 3.0)
|
|
tail *= 3.0 / streak;
|
|
if (false == particle_visible(planes, world + 0.5 * tail, 0.5 * length(tail) + width))
|
|
return;
|
|
vec3 color = particle_light((view * vec4(world, 1.0)).xyz, world, options.y);
|
|
particle_emit(world, width, tail, color * options.z, opacity, uint(timing.w));
|
|
}
|