Spaces:
Running
Running
File size: 5,546 Bytes
96e7bf7 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
"use strict";
function main() {
// Get A WebGL context
/** @type {HTMLCanvasElement} */
const canvas = document.querySelector("#canvas");
const gl = canvas.getContext("webgl2");
if (!gl) {
return;
}
const vs = `#version 300 es
// an attribute is an input (in) to a vertex shader.
// It will receive data from a buffer
in vec4 a_position;
// all shaders have a main function
void main() {
// gl_Position is a special variable a vertex shader
// is responsible for setting
gl_Position = a_position;
}
`;
const fs = `#version 300 es
precision highp float;
uniform vec2 iResolution;
uniform vec2 iMouse;
uniform float iTime;
// we need to declare an output for the fragment shader
out vec4 outColor;
vec3 palette( float t ) {
vec3 a = vec3(0.5, 0.5, 0.5);
vec3 b = vec3(0.5, 0.5, 0.5);
vec3 c = vec3(1.0, 1.0, 1.0);
vec3 d = vec3(0.263,0.416,0.557);
return a + b*cos( 6.28318*(c*t+d) );
}
//https://www.shadertoy.com/view/mtyGWy
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
vec2 uv = (fragCoord * 2.0 - iResolution.xy) / iResolution.y;
vec2 uv0 = uv;
vec3 finalColor = vec3(0.0);
for (float i = 0.0; i < 4.0; i++) {
uv = fract(uv * 1.5) - 0.5;
float d = length(uv) * exp(-length(uv0));
vec3 col = palette(length(uv0) + i*.4 + iTime*.4);
d = sin(d*8. + iTime)/8.;
d = abs(d);
d = pow(0.01 / d, 1.2);
finalColor += col * d;
}
fragColor = vec4(finalColor, 1.0);
}
void main() {
mainImage(outColor, gl_FragCoord.xy);
}
`;
// setup GLSL program
const program = webglUtils.createProgramFromSources(gl, [vs, fs]);
// look up where the vertex data needs to go.
const positionAttributeLocation = gl.getAttribLocation(program, "a_position");
// look up uniform locations
const resolutionLocation = gl.getUniformLocation(program, "iResolution");
const mouseLocation = gl.getUniformLocation(program, "iMouse");
const timeLocation = gl.getUniformLocation(program, "iTime");
// Create a vertex array object (attribute state)
const vao = gl.createVertexArray();
// and make it the one we're currently working with
gl.bindVertexArray(vao);
// Create a buffer to put three 2d clip space points in
const positionBuffer = gl.createBuffer();
// Bind it to ARRAY_BUFFER (think of it as ARRAY_BUFFER = positionBuffer)
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
// fill it with a 2 triangles that cover clip space
gl.bufferData(
gl.ARRAY_BUFFER,
new Float32Array([
-1,
-1, // first triangle
1,
-1,
-1,
1,
-1,
1, // second triangle
1,
-1,
1,
1,
]),
gl.STATIC_DRAW
);
// Turn on the attribute
gl.enableVertexAttribArray(positionAttributeLocation);
// Tell the attribute how to get data out of positionBuffer (ARRAY_BUFFER)
gl.vertexAttribPointer(
positionAttributeLocation,
2, // 2 components per iteration
gl.FLOAT, // the data is 32bit floats
false, // don't normalize the data
0, // 0 = move forward size * sizeof(type) each iteration to get the next position
0 // start at the beginning of the buffer
);
const playpauseElem = document.querySelector(".playpause");
const inputElem = document.querySelector(".divcanvas");
inputElem.addEventListener("mouseover", requestFrame);
inputElem.addEventListener("mouseout", cancelFrame);
let mouseX = 0;
let mouseY = 0;
function setMousePosition(e) {
const rect = inputElem.getBoundingClientRect();
mouseX = e.clientX - rect.left;
mouseY = rect.height - (e.clientY - rect.top) - 1; // bottom is 0 in WebGL
}
inputElem.addEventListener("mousemove", setMousePosition);
inputElem.addEventListener(
"touchstart",
(e) => {
e.preventDefault();
playpauseElem.classList.add("playpausehide");
requestFrame();
},
{ passive: false }
);
inputElem.addEventListener(
"touchmove",
(e) => {
e.preventDefault();
setMousePosition(e.touches[0]);
},
{ passive: false }
);
inputElem.addEventListener(
"touchend",
(e) => {
e.preventDefault();
playpauseElem.classList.remove("playpausehide");
cancelFrame();
},
{ passive: false }
);
let requestId;
function requestFrame() {
if (!requestId) {
requestId = requestAnimationFrame(render);
}
}
function cancelFrame() {
if (requestId) {
cancelAnimationFrame(requestId);
requestId = undefined;
}
}
let then = 0;
let time = 0;
function render(now) {
requestId = undefined;
now *= 0.001; // convert to seconds
const elapsedTime = Math.min(now - then, 0.1);
time += elapsedTime;
then = now;
webglUtils.resizeCanvasToDisplaySize(gl.canvas);
// Tell WebGL how to convert from clip space to pixels
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
// Tell it to use our program (pair of shaders)
gl.useProgram(program);
// Bind the attribute/buffer set we want.
gl.bindVertexArray(vao);
gl.uniform2f(resolutionLocation, gl.canvas.width, gl.canvas.height);
gl.uniform2f(mouseLocation, mouseX, mouseY);
gl.uniform1f(timeLocation, time);
gl.drawArrays(
gl.TRIANGLES,
0, // offset
6 // num vertices to process
);
requestFrame();
}
requestFrame();
requestAnimationFrame(cancelFrame);
}
main();
|