5 kEntrypointElementId: 'entrypoint', // The id of the canvas element where we will render
8 kTargetVerticalResolution: 32,
12 kBackgroundColor: [0.811, 0.73, 0.48, 1.0],
13 kRotationValues: [Math
.random(), Math
.random(), Math
.random()],
20 attribute vec4 aVertexPosition;
21 attribute vec4 aColor;
25 uniform mat4 uModelViewMatrix;
26 uniform mat4 uProjectionMatrix;
30 gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;
37 precision mediump float;
42 gl_FragColor = vColor;
46 // Properties: Animation
50 // Runs on load, Initializes WebGL and starts the animation loop.
55 const canvas
= internals
.initializeCanvas();
56 const {gl
, programInfo
, buffers
} = internals
.initializeWebGL(canvas
);
58 window
.requestAnimationFrame(internals
.animate
.bind(this, gl
, programInfo
, buffers
));
61 // Gets a canvas element and sets up resizing events.
65 const canvas
= document
.getElementById(internals
.kEntrypointElementId
);
66 internals
.resizeCanvas(canvas
);
67 window
.addEventListener('resize', () => internals
.resizeCanvas(canvas
));
72 // Given a canvas, it will initialize the webgl context and set up the shaders.
74 initializeWebGL(canvas
) {
76 const gl
= canvas
.getContext('webgl', {
77 preserveDrawingBuffer: true
79 const shaderProgram
= internals
.initializeShaderProgram(gl
, internals
.kVertexShader
, internals
.kFragmentShader
);
82 program: shaderProgram
,
84 vertexPosition: gl
.getAttribLocation(shaderProgram
, 'aVertexPosition'),
85 vertexColor: gl
.getAttribLocation(shaderProgram
, 'aColor')
88 projectionMatrix: gl
.getUniformLocation(shaderProgram
, 'uProjectionMatrix'),
89 modelViewMatrix: gl
.getUniformLocation(shaderProgram
, 'uModelViewMatrix')
93 const buffers
= internals
.initializeBuffers(gl
);
95 return { gl
, programInfo
, buffers
};
100 resizeCanvas(canvas
) {
102 let width
= window
.innerWidth
;
103 let height
= Math
.round(width
* internals
.kHeightRatio
/ internals
.kWidthRatio
);
105 if (window
.innerHeight
< height
) {
106 height
= window
.innerHeight
;
107 width
= Math
.round(height
* internals
.kWidthRatio
/ internals
.kHeightRatio
);
108 console
.log(width
, height
);
111 canvas
.style
.width
= `${width}px`;
112 canvas
.style
.height
= `${height}px`;
114 canvas
.width
= internals
.kTargetVerticalResolution
* internals
.kWidthRatio
;
115 canvas
.height
= internals
.kTargetVerticalResolution
;
117 canvas
.width
= width
;
118 canvas
.height
= height
;
121 // Methods: Shader / GL Related
123 initializeShaderProgram(gl
, vertexShaderSource
, fragmentShaderSource
) {
125 const vertexShader
= internals
.loadShader(gl
, gl
.VERTEX_SHADER
, vertexShaderSource
);
126 const fragmentShader
= internals
.loadShader(gl
, gl
.FRAGMENT_SHADER
, fragmentShaderSource
);
128 const shaderProgram
= gl
.createProgram();
129 gl
.attachShader(shaderProgram
, vertexShader
);
130 gl
.attachShader(shaderProgram
, fragmentShader
);
132 gl
.linkProgram(shaderProgram
);
134 if (!gl
.getProgramParameter(shaderProgram
, gl
.LINK_STATUS
)) {
135 alert(`Unable to initialize shader program: ${gl.getProgramInfoLog(shaderProgram)}`);
139 return shaderProgram
;
142 loadShader(gl
, type
, source
) {
144 const shader
= gl
.createShader(type
);
145 gl
.shaderSource(shader
, source
);
146 gl
.compileShader(shader
);
148 if (!gl
.getShaderParameter(shader
, gl
.COMPILE_STATUS
)) {
149 alert(`Unable to compile shader: ${gl.getShaderInfoLog(shader)}`);
150 gl
.deleteShader(shader
);
157 initializeBuffers(gl
) {
159 const positionBuffer
= gl
.createBuffer();
161 gl
.bindBuffer(gl
.ARRAY_BUFFER
, positionBuffer
);
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
180 gl
.bufferData(gl
.ARRAY_BUFFER
,
181 new Float32Array(positions
),
185 position: positionBuffer
193 const matrix
= mat4
.create();
204 // Methods: Animation
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]);
213 drawScene(gl
, programInfo
, buffers
) {
215 gl
.clearColor(...internals
.kBackgroundColor
);
217 gl
.enable(gl
.DEPTH_TEST
);
218 gl
.depthFunc(gl
.LEQUAL
);
220 const fieldOfView
= internals
.kFieldOfView
* Math
.PI
/ 180;
221 const aspectRatio
= internals
.kWidthRatio
/ internals
.kHeightRatio
;
222 const projectionMatrix
= mat4
.create();
228 internals
.kNearLimit
,
232 internals
.modelViewMatrix
= internals
.modelViewMatrix
|| internals
.createMatrix();
234 internals
.rotate(internals
.modelViewMatrix
);
237 const numberOfComponents
= 3;
238 const type
= gl
.FLOAT
;
239 const normalize
= false;
243 gl
.bindBuffer(gl
.ARRAY_BUFFER
, buffers
.position
);
244 gl
.vertexAttribPointer(
245 programInfo
.attribLocations
.vertexPosition
,
252 gl
.enableVertexAttribArray(programInfo
.attribLocations
.vertexPosition
);
256 // ATTEMPT TO SEND COLOR DATA
258 const colorBuffer
= gl
.createBuffer();
260 gl
.bindBuffer(gl
.ARRAY_BUFFER
, colorBuffer
);
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
279 gl
.bufferData(gl
.ARRAY_BUFFER
,
280 new Float32Array(colors
),
283 const numberOfComponents
= 4;
284 const type
= gl
.FLOAT
;
285 const normalize
= false;
289 gl
.bindBuffer(gl
.ARRAY_BUFFER
, colorBuffer
);
290 gl
.vertexAttribPointer(
291 programInfo
.attribLocations
.vertexColor
,
298 gl
.enableVertexAttribArray(programInfo
.attribLocations
.vertexColor
);
303 gl
.useProgram(programInfo
.program
);
306 programInfo
.uniformLocations
.projectionMatrix
,
311 programInfo
.uniformLocations
.modelViewMatrix
,
313 internals
.modelViewMatrix
318 const vertexCount
= 14;
319 gl
.drawArrays(gl
.TRIANGLE_STRIP
, offset
, vertexCount
);
323 animate(gl
, programInfo
, buffers
, time
) {
325 const delta
= time
- internals
.currentTime
;
326 const interval
= 1000 / internals
.kFPS
;
328 if (delta
>= interval
) {
329 internals
.drawScene(gl
, programInfo
, buffers
, delta
);
330 internals
.currentTime
= time
;
333 window
.requestAnimationFrame(internals
.animate
.bind(this, gl
, programInfo
, buffers
));
337 window
.addEventListener('load', internals
.onLoad
);