|
// https://twitter.com/zozuar/status/1632160439944478721?s=42&t=kZ3wyx2jn4JBuVn3WNWeYQ |
|
|
|
fragment float4 waterShader(const VertexOut vertexOut [[stage_in]], |
|
constant Uniforms& uniforms [[buffer(0)]]) { |
|
|
|
float height, iteration, amplitude, waveLength, xCoord, globalWaveHeight; |
|
|
|
// Initialize variables |
|
height = vertexOut.position.y; |
|
iteration = 0.0; |
|
amplitude = uniforms.amplitude; |
|
waveLength = uniforms.waveLength; |
|
xCoord = (vertexOut.position.x / uniforms.resolution.y) * uniforms.scale; |
|
globalWaveHeight = uniforms.globalWaveHeight - 3.0; |
|
|
|
// Iterate over waves |
|
for (; iteration++ < 100.0;) { |
|
// Calculate position of current wave |
|
float3 position = float3(vertexOut.position.xy / uniforms.resolution.y * globalWaveHeight, globalWaveHeight, 0.0); |
|
position.yz *= float3x3(rotationMatrix(0.0, 0.6, 0.0)); |
|
|
|
// Adjust position based on wave amplitude and frequency |
|
for (amplitude = 0.8; amplitude > 0.003; amplitude *= 0.8) { |
|
position.xz *= float3x3(rotationMatrix(0.0, 5.0, 0.0)); |
|
xCoord = (++position.x + position.z) / amplitude + uniforms.time * 2.0; |
|
float waveHeight = exp(sin(xCoord) - 2.5) * amplitude; |
|
uniforms.color.gb += waveHeight / 400.0; |
|
position.xz -= float2(waveHeight * cos(xCoord), waveHeight); |
|
height -= waveHeight; |
|
} |
|
|
|
globalWaveHeight += height; |
|
} |
|
|
|
// Calculate final color based on wave height and frequency |
|
uniforms.color += min(height * height * 4e6, 1.0 / globalWaveHeight) + globalWaveHeight * globalWaveHeight / 200.0; |
|
return uniforms.color; |
|
} |