diff --git a/shaders/mat_rain_windscreen.frag b/shaders/mat_rain_windscreen.frag index f7f057ca..99d7dadf 100644 --- a/shaders/mat_rain_windscreen.frag +++ b/shaders/mat_rain_windscreen.frag @@ -25,6 +25,7 @@ layout(location = 1) out vec4 out_motion; #include #include #include +#include uniform sampler2D diffuse; uniform sampler2D raindropsatlas; @@ -34,10 +35,6 @@ uniform float specular_intensity = 1.0; uniform float wobble_strength = 0.002; uniform float wobble_speed = 30.0; -float hash(vec2 p) { - return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453); -} - vec4 getDropTex(float choice, vec2 uv) { vec2 offset; if (choice < 0.25) offset = vec2(0.0, 0.0); @@ -54,13 +51,14 @@ void main() { if (tex_color.a < 0.01) discard; vec2 rainCoord = f_coord; + float gridSize = ceil(param[2].x); const float numDrops = 20000.0; const float cycleDuration = 4.0; - const float squareMin = 0.0035; - const float squareMax = 0.008; + + float squareMin = 0.5 / gridSize; + float squareMax = 1.2 / gridSize; - float gridSize = ceil(param[2].x); vec2 cell = floor(rainCoord * gridSize); vec3 dropLayer = vec3(0.0); @@ -76,37 +74,37 @@ void main() { float side; float mixFactor = GetMixFactor(neighborCenter, side); - if(mixFactor < hash(neighborCell + vec2(mix(0., .2137, side), 0.))) { + uint seed = Hash(uvec3(neighborCell, side)); + + if(mixFactor < RandF(seed)) { continue; } - - float i = neighborCell.x + neighborCell.y * gridSize; // Show a percentage of droplets given by rain intensity param - float activationSeed = hash(vec2(i, 0.333 + side)); + float activationSeed = RandF(seed); if (activationSeed > rain_params.x) continue; // kropla nieaktywna // Randomly modulate droplet center & size - vec2 dropCenter = (neighborCell + vec2(hash(vec2(i, 0.12 + side)), hash(vec2(i, 0.34 + side)))) / gridSize; - float squareSize = mix(squareMin, squareMax, hash(vec2(i, 0.56 + side))); + vec2 dropCenter = (neighborCell + vec2(RandF(seed), RandF(seed))) / gridSize; + float squareSize = mix(squareMin, squareMax, RandF(seed)); - float lifeTime = time + hash(vec2(i, 0.78 + side)) * cycleDuration; + float lifeTime = time + RandF(seed) * cycleDuration; float phase = fract(lifeTime / cycleDuration); float active = clamp(1.0 - phase, 0.0, 1.0); // Gravity influence (TODO add vehicle speed & wind here!) float gravityStart = 0.5; float gravityPhase = smoothstep(gravityStart, 1.0, phase); - float dropMass = mix(0.3, 1.2, hash(vec2(i, 0.21 + side))); + float dropMass = mix(0.3, 1.2, RandF(seed)); float gravitySpeed = 0.15 * dropMass; vec2 gravityOffset = vec2(0.0, gravityPhase * gravitySpeed * phase); // Random wobble - bool hasWobble = (hash(vec2(i, 0.91 + side)) < 0.10); + bool hasWobble = (RandF(seed) < 0.10); vec2 wobbleOffset = vec2(0.0); if (hasWobble && gravityPhase > 0.0) { - float intensity = sin(time * wobble_speed + i) * wobble_strength * gravityPhase; + float intensity = sin(time * wobble_speed + RandF(seed) * 100.) * wobble_strength * gravityPhase; wobbleOffset = vec2(intensity, 0.0); } @@ -125,7 +123,7 @@ void main() { if (mask > 0.001) { vec2 localUV = (diff + squareSize * 0.5) / squareSize; - float choice = hash(vec2(i, 0.99 + side)); + float choice = RandF(seed); vec4 dropTex = getDropTex(choice, localUV); float sharpAlpha = smoothstep(0.3, 0.9, dropTex.a); @@ -139,7 +137,7 @@ void main() { float sparkle = 0.0; if (hasWobble) { - sparkle = pow(abs(sin(f_coord.x * 8.0 + time * 2.0 + hash(vec2(i, 0.9 + side)) * 6.2831)), 40.0) + sparkle = pow(abs(sin(f_coord.x * 8.0 + time * 2.0 + RandF(seed) * 6.2831)), 40.0) * mix(0.2, 1.0, sunFactor); } diff --git a/shaders/random.glsl b/shaders/random.glsl new file mode 100644 index 00000000..0b25c987 --- /dev/null +++ b/shaders/random.glsl @@ -0,0 +1,39 @@ + +uint Hash(uint s); +uint Hash(uvec2 s); +uint Hash(uvec3 s); +uint Hash(float s); +uint HashCombine(uint seed, uint value); + +// Evolving Sub-Grid Turbulence for Smoke Animation +// H. Schechter and R. Bridson +uint Hash(uint s) { + s ^= 2747636419u; + s *= 2654435769u; + s ^= s >> 16u; + s *= 2654435769u; + s ^= s >> 16u; + s *= 2654435769u; + return s; +} + +uint Hash(uvec2 s) { + return HashCombine(Hash(s.x), s.y); +} + +uint Hash(uvec3 s) { + return HashCombine(Hash(s.xy), s.z); +} + +uint HashCombine(uint seed, uint value) { + return seed ^ (Hash(value) + 0x9e3779b9u + (seed<<6u) + (seed>>2u)); +} + +uint Rand(inout uint seed) { + seed = Hash(seed); + return seed; +} + +float RandF(inout uint seed) { + return float(Rand(seed)) * 2.3283064365386963e-10; +}