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> | |