]> git.r.bdr.sh - rbdr/flower/blame - lib/flower.js
Dump codepen to a static site
[rbdr/flower] / lib / flower.js
CommitLineData
b006b62b
BB
1const internals = {
2
3 // Constants
4
5 kEntrypointElementId: 'entrypoint', // The id of the canvas element where we will render
6 kWidthRatio: 2.76,
7 kHeightRatio: 1,
8 kTargetVerticalResolution: 32,
9 kFieldOfView: 45,
10 kNearLimit: 0.1,
11 kFarLimit: 100,
12 kBackgroundColor: [0.811, 0.73, 0.48, 1.0],
13 kRotationValues: [Math.random(), Math.random(), Math.random()],
14 kFPS: 30,
15
16 // Constants: Shaders
17
18 kVertexShader: `
19
20 attribute vec4 aVertexPosition;
21 attribute vec4 aColor;
22
23 varying vec4 vColor;
24
25 uniform mat4 uModelViewMatrix;
26 uniform mat4 uProjectionMatrix;
27
28 void main() {
29
30 gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;
31 vColor = aColor;
32 }
33 `,
34
35 kFragmentShader: `
36
37 precision mediump float;
38 varying vec4 vColor;
39
40 void main() {
41
42 gl_FragColor = vColor;
43 }
44 `,
45
46 // Properties: Animation
47
48 currentTime: 0,
49
50 // Runs on load, Initializes WebGL and starts the animation loop.
51
52 onLoad() {
53
54
55 const canvas = internals.initializeCanvas();
56 const {gl, programInfo, buffers} = internals.initializeWebGL(canvas);
57
58 window.requestAnimationFrame(internals.animate.bind(this, gl, programInfo, buffers));
59 },
60
61 // Gets a canvas element and sets up resizing events.
62
63 initializeCanvas() {
64
65 const canvas = document.getElementById(internals.kEntrypointElementId);
66 internals.resizeCanvas(canvas);
67 window.addEventListener('resize', () => internals.resizeCanvas(canvas));
68
69 return canvas;
70 },
71
72 // Given a canvas, it will initialize the webgl context and set up the shaders.
73
74 initializeWebGL(canvas) {
75
76 const gl = canvas.getContext('webgl', {
77 preserveDrawingBuffer: true
78 });
79 const shaderProgram = internals.initializeShaderProgram(gl, internals.kVertexShader, internals.kFragmentShader);
80
81 const programInfo = {
82 program: shaderProgram,
83 attribLocations: {
84 vertexPosition: gl.getAttribLocation(shaderProgram, 'aVertexPosition'),
85 vertexColor: gl.getAttribLocation(shaderProgram, 'aColor')
86 },
87 uniformLocations: {
88 projectionMatrix: gl.getUniformLocation(shaderProgram, 'uProjectionMatrix'),
89 modelViewMatrix: gl.getUniformLocation(shaderProgram, 'uModelViewMatrix')
90 }
91 };
92
93 const buffers = internals.initializeBuffers(gl);
94
95 return { gl, programInfo, buffers};
96 },
97
98 // Methods: Canvas
99
100 resizeCanvas(canvas) {
101
102 let width = window.innerWidth;
103 let height = Math.round(width * internals.kHeightRatio / internals.kWidthRatio);
104
105 if (window.innerHeight < height) {
106 height = window.innerHeight;
107 width = Math.round(height * internals.kWidthRatio / internals.kHeightRatio);
108 console.log(width, height);
109 }
110
111 canvas.style.width = `${width}px`;
112 canvas.style.height = `${height}px`;
113
114 canvas.width = internals.kTargetVerticalResolution * internals.kWidthRatio;
115 canvas.height = internals.kTargetVerticalResolution;
116
117 canvas.width = width;
118 canvas.height = height;
119 },
120
121 // Methods: Shader / GL Related
122
123 initializeShaderProgram(gl, vertexShaderSource, fragmentShaderSource) {
124
125 const vertexShader = internals.loadShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
126 const fragmentShader = internals.loadShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
127
128 const shaderProgram = gl.createProgram();
129 gl.attachShader(shaderProgram, vertexShader);
130 gl.attachShader(shaderProgram, fragmentShader);
131
132 gl.linkProgram(shaderProgram);
133
134 if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
135 alert(`Unable to initialize shader program: ${gl.getProgramInfoLog(shaderProgram)}`);
136 return null;
137 }
138
139 return shaderProgram;
140 },
141
142 loadShader(gl, type, source) {
143
144 const shader = gl.createShader(type);
145 gl.shaderSource(shader, source);
146 gl.compileShader(shader);
147
148 if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
149 alert(`Unable to compile shader: ${gl.getShaderInfoLog(shader)}`);
150 gl.deleteShader(shader);
151 return null;
152 }
153
154 return shader;
155 },
156
157 initializeBuffers(gl) {
158
159 const positionBuffer = gl.createBuffer();
160
161 gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
162
163 const positions = [
164 -1.0, 1.0, 1.0, // Front-top-left
165 1.0, 1.0, 1.0, // Front-top-right
166 -1.0, -1.0, 1.0, // Front-bottom-left
167 1.0, -1.0, 1.0, // Front-bottom-right
168 1.0, -1.0, -1.0, // Back-bottom-right
169 1.0, 1.0, 1.0, // Front-top-right
170 1.0, 1.0, -1.0, // Back-top-right
171 -1.0, 1.0, 1.0, // Front-top-left
172 -1.0, 1.0, -1.0, // Back-top-left
173 -1.0, -1.0, 1.0, // Front-bottom-left
174 -1.0, -1.0, -1.0, // Back-bottom-left
175 1.0, -1.0, -1.0, // Back-bottom-right
176 -1.0, 1.0, -1.0, // Back-top-left
177 1.0, 1.0, -1.0 // Back-top-right
178 ];
179
180 gl.bufferData(gl.ARRAY_BUFFER,
181 new Float32Array(positions),
182 gl.STATIC_DRAW);
183
184 return {
185 position: positionBuffer
186 }
187 },
188
189 // Methods: Utility
190
191 createMatrix() {
192
193 const matrix = mat4.create();
194
195 mat4.translate(
196 matrix,
197 matrix,
198 [-0.0, 0.0, -6.0]
199 );
200
201 return matrix;
202 },
203
204 // Methods: Animation
205
206 rotate(matrix) {
207
208 mat4.rotate(internals.modelViewMatrix, internals.modelViewMatrix, internals.kRotationValues[0], [1, 0, 0]);
209 mat4.rotate(internals.modelViewMatrix, internals.modelViewMatrix, internals.kRotationValues[1], [0, 1, 0]);
210 mat4.rotate(internals.modelViewMatrix, internals.modelViewMatrix, internals.kRotationValues[2], [0, 0, 1]);
211 },
212
213 drawScene(gl, programInfo, buffers) {
214
215 gl.clearColor(...internals.kBackgroundColor);
216 gl.clearDepth(1.0);
217 gl.enable(gl.DEPTH_TEST);
218 gl.depthFunc(gl.LEQUAL);
219
220 const fieldOfView = internals.kFieldOfView * Math.PI / 180;
221 const aspectRatio = internals.kWidthRatio / internals.kHeightRatio;
222 const projectionMatrix = mat4.create();
223
224 mat4.perspective(
225 projectionMatrix,
226 fieldOfView,
227 aspectRatio,
228 internals.kNearLimit,
229 internals.kFarLimit
230 );
231
232 internals.modelViewMatrix = internals.modelViewMatrix || internals.createMatrix();
233
234 internals.rotate(internals.modelViewMatrix);
235
236 {
237 const numberOfComponents = 3;
238 const type = gl.FLOAT;
239 const normalize = false;
240 const stride = 0;
241 const offset = 0;
242
243 gl.bindBuffer(gl.ARRAY_BUFFER, buffers.position);
244 gl.vertexAttribPointer(
245 programInfo.attribLocations.vertexPosition,
246 numberOfComponents,
247 type,
248 normalize,
249 stride,
250 offset
251 );
252 gl.enableVertexAttribArray(programInfo.attribLocations.vertexPosition);
253 }
254
255 {
256 // ATTEMPT TO SEND COLOR DATA
257
258 const colorBuffer = gl.createBuffer();
259
260 gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
261
262 const colors = [
263 1.0, 0.0, 0.5, 1.0, // Front-top-left
264 1.0, 0.3, 0.8, 1.0, // Front-top-right
265 1.0, 1.0, 0.7, 1.0, // Front-bottom-left
266 0.0, 0.3, 0.5, 1.0, // Front-bottom-right
267 0.0, 0.3, 0.5, 1.0, // Back-bottom-right
268 1.0, 0.3, 0.8, 1.0, // Front-top-right
269 1.0, 0.3, 0.8, 1.0, // Back-top-right
270 1.0, 0.0, 0.5, 1.0, // Front-top-left
271 1.0, 0.0, 0.5, 1.0, // Back-top-left
272 1.0, 1.0, 0.7, 1.0, // Front-bottom-left
273 1.0, 1.0, 0.7, 1.0, // Back-bottom-left
274 0.0, 0.3, 0.5, 1.0, // Back-bottom-right
275 1.0, 0.0, 0.5, 1.0, // Back-top-left
276 1.0, 0.3, 0.8, 1.0 // Back-top-right
277 ];
278
279 gl.bufferData(gl.ARRAY_BUFFER,
280 new Float32Array(colors),
281 gl.STATIC_DRAW);
282
283 const numberOfComponents = 4;
284 const type = gl.FLOAT;
285 const normalize = false;
286 const stride = 0;
287 const offset = 0;
288
289 gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
290 gl.vertexAttribPointer(
291 programInfo.attribLocations.vertexColor,
292 numberOfComponents,
293 type,
294 normalize,
295 stride,
296 offset
297 );
298 gl.enableVertexAttribArray(programInfo.attribLocations.vertexColor);
299
300 // END ATTEMPT
301 }
302
303 gl.useProgram(programInfo.program);
304
305 gl.uniformMatrix4fv(
306 programInfo.uniformLocations.projectionMatrix,
307 false,
308 projectionMatrix
309 );
310 gl.uniformMatrix4fv(
311 programInfo.uniformLocations.modelViewMatrix,
312 false,
313 internals.modelViewMatrix
314 );
315
316 {
317 const offset = 0;
318 const vertexCount = 14;
319 gl.drawArrays(gl.TRIANGLE_STRIP, offset, vertexCount);
320 }
321 },
322
323 animate(gl, programInfo, buffers, time) {
324
325 const delta = time - internals.currentTime;
326 const interval = 1000 / internals.kFPS;
327
328 if (delta >= interval) {
329 internals.drawScene(gl, programInfo, buffers, delta);
330 internals.currentTime = time;
331 }
332
333 window.requestAnimationFrame(internals.animate.bind(this, gl, programInfo, buffers));
334 }
335};
336
337window.addEventListener('load', internals.onLoad);