Spaces:
No application file
No application file
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Fluid Simulation</title> | |
<style> | |
body, html { | |
margin: 0; | |
padding: 0; | |
overflow: hidden; | |
background-color: black; | |
} | |
canvas { | |
display: block; | |
} | |
</style> | |
</head> | |
<body> | |
<canvas id="canvas"></canvas> | |
<script> | |
const canvas = document.getElementById('canvas'); | |
const gl = canvas.getContext('webgl'); | |
canvas.width = window.innerWidth; | |
canvas.height = window.innerHeight; | |
const vertexShaderSource = ` | |
attribute vec2 a_position; | |
void main() { | |
gl_Position = vec4(a_position, 0.0, 1.0); | |
} | |
`; | |
const fragmentShaderSource = ` | |
precision highp float; | |
uniform vec2 u_resolution; | |
uniform float u_time; | |
// Converts HSV to RGB | |
vec3 hsv2rgb(vec3 c) { | |
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); | |
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); | |
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); | |
} | |
void main() { | |
vec2 st = gl_FragCoord.xy / u_resolution; | |
st.x *= u_resolution.x / u_resolution.y; | |
float colorHue = mod(u_time * 0.1 + length(st - 0.5), 1.0); | |
float colorValue = smoothstep(0.0, 0.5, 0.5 - length(st - 0.5)); | |
vec3 color = hsv2rgb(vec3(colorHue, 1.0, colorValue)); | |
gl_FragColor = vec4(color, 1.0); | |
} | |
`; | |
function createShader(gl, type, source) { | |
const shader = gl.createShader(type); | |
gl.shaderSource(shader, source); | |
gl.compileShader(shader); | |
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { | |
console.error(gl.getShaderInfoLog(shader)); | |
gl.deleteShader(shader); | |
return null; | |
} | |
return shader; | |
} | |
function createProgram(gl, vertexShader, fragmentShader) { | |
const program = gl.createProgram(); | |
gl.attachShader(program, vertexShader); | |
gl.attachShader(program, fragmentShader); | |
gl.linkProgram(program); | |
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { | |
console.error(gl.getProgramInfoLog(program)); | |
gl.deleteProgram(program); | |
return null; | |
} | |
return program; | |
} | |
const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource); | |
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource); | |
const program = createProgram(gl, vertexShader, fragmentShader); | |
const positionBuffer = gl.createBuffer(); | |
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); | |
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ | |
-1, -1, | |
1, -1, | |
-1, 1, | |
-1, 1, | |
1, -1, | |
1, 1, | |
]), gl.STATIC_DRAW); | |
const positionLocation = gl.getAttribLocation(program, 'a_position'); | |
const resolutionLocation = gl.getUniformLocation(program, 'u_resolution'); | |
const timeLocation = gl.getUniformLocation(program, 'u_time'); | |
function render(time) { | |
time *= 0.001; // convert time to seconds | |
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height); | |
gl.clearColor(0, 0, 0, 1); | |
gl.clear(gl.COLOR_BUFFER_BIT); | |
gl.useProgram(program); | |
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); | |
gl.enableVertexAttribArray(positionLocation); | |
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0); | |
gl.uniform2f(resolutionLocation, gl.canvas.width, gl.canvas.height); | |
gl.uniform1f(timeLocation, time); | |
gl.drawArrays(gl.TRIANGLES, 0, 6); | |
requestAnimationFrame(render); | |
} | |
requestAnimationFrame(render); | |
</script> | |
</body> | |
</html> | |