Skip to content

Instantly share code, notes, and snippets.

@pmark
Created March 5, 2023 17:19
Show Gist options
  • Save pmark/f3b22629a2a1a361ee23e2c9d3311bd3 to your computer and use it in GitHub Desktop.
Save pmark/f3b22629a2a1a361ee23e2c9d3311bd3 to your computer and use it in GitHub Desktop.
Metal water
// 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;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment