17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-29 11:37:29 +01:00
Files
maszyna/shaders/vk14/water_spawn.comp
2026-10-26 15:51:56 +01:00

69 lines
3.2 KiB
Plaintext

#version 460 core
#define STAGE_COMPUTE 1
// the water on the windscreens (water_sim.glsl): the rain or the snow landing on the glasses in the step. a thread per landing
// tried, a row of groups per glass: a place of the uv picked at random is taken as often as the glass there gets hit (the
// metres squared the place holds, how much it faces the rain coming at it), so the landings go evenly over the glass. a raindrop
// spreads and throws a splash of droplets around, along the way it came, which flow into the drops they land on (water_settle.comp
// takes the water); a flake sticks where it lands
// none of the pass set: everything the kernel reads is pushed with its dispatch (set COMPUTE_SET, water_sim.glsl), so it runs
// before the passes of the frame set theirs up
#define LAYOUT_UI 1
#include "common.glsl"
#include "water_sim.glsl"
layout(local_size_x = WATER_GROUP_SIZE) in;
void main()
{
uint slot = gl_WorkGroupID.y;
uint landing = gl_GlobalInvocationID.x;
if ((water_slots[slot].z < 0.5) || (float(landing) >= water_slots[slot].x))
return;
vec4 r = water_random(water_counts.x, slot, landing, 0u);
vec2 uv = r.xy;
water_frame_s frame = water_frame(slot, uv);
if (frame.valid < 0.75)
return;
// the rain coming at the glass, against the cab
vec3 coming = water_air.xyz - water_up.xyz * water_air.w;
float speed = length(coming);
if (speed < 1e-3)
return;
float facing = max(-dot(coming, frame.normal), 0.0) / speed;
float density = length(cross(frame.tu, frame.tv));
if (r.z >= density * water_slots[slot].y * facing)
return;
float scale = max(water_slots[slot].w, 0.05);
vec4 s = water_random(water_counts.x, slot, landing, 1u);
uint seed = water_pcg4d(uvec4(water_counts.x, slot, landing, 2u)).x;
if (water_step.w > 0.5)
{
// a flake, a few mm of snow holding a little water
water_add(slot, seed, uv, mix(0.3, 2.5, s.x) * scale * scale * scale, 0.0, s.y, true);
return;
}
// the diameter of the raindrop, mm: above the least landing as a drop of its own they go as Marshall-Palmer (exponential)
float diameter = min(water_rain.x - log(max(r.w, 1e-6)) / max(water_rain.y, 0.1), 5.0) * scale;
float drop = 0.5236 * diameter * diameter * diameter;
// most of it stays where it hit, the rest is thrown around as droplets, forward along the glass
float kept = mix(0.55, 0.85, s.x);
water_land(slot, seed, frame, uv, drop * kept, s.y);
vec3 along = coming - frame.normal * dot(coming, frame.normal);
float glancing = length(along) / speed;
vec3 forward = (glancing > 1e-3) ? normalize(along) : normalize(frame.tu);
vec3 across = cross(frame.normal, forward);
float radius = water_radius(drop * kept);
int splash = 2 + int(s.z * 4.0);
for (int k = 0; k < splash; ++k)
{
vec4 e = water_random(water_counts.x, slot, landing, 3u + uint(k));
float angle = e.x * 6.2831853;
vec3 way = cos(angle) * forward + sin(angle) * across + forward * (1.5 * glancing);
way = (length(way) > 1e-3) ? normalize(way) : forward;
float distance = radius * (1.3 + 2.5 * e.y) * (1.0 + glancing);
float volume = drop * (1.0 - kept) / float(splash) * mix(0.4, 1.6, e.z);
water_land(slot, seed + 101u * uint(k + 1), frame, uv + water_to_uv(frame, way * distance), volume, e.w);
}
}