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