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();
|