mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-29 11:37:29 +01:00
69 lines
3.2 KiB
Plaintext
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);
|
|
}
|
|
}
|