- Real-Time 3D Graphics with WebGL 2
- Farhad Ghayour Diego Cantor
- 489字
- 2021-06-10 19:43:01
Architecture Updates
Let's cover some useful functions that we can refactor for use in later chapters:
- Open common/js/utils.js in your editor to see the following changes.
- We have added two additional methods, autoResizeCanvas and getShader, to utils.js that look very similar to the code we implemented earlier in this chapter:
'use strict';
// A set of utility functions for /common operations across our
// application
const utils = {
// Find and return a DOM element given an ID
getCanvas(id) {
// ...
},
// Given a canvas element, return the WebGL2 context
getGLContext(canvas) {
// ...
},
// Given a canvas element, expand it to the size of the window
// and ensure that it automatically resizes as the window changes
autoResizeCanvas(canvas) {
const expandFullScreen = () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
};
expandFullScreen();
window.addEventListener('resize', expandFullScreen);
},
// Given a WebGL context and an id for a shader script,
// return a compiled shader
getShader(gl, id) {
const script = document.getElementById(id);
if (!script) {
return null;
}
const shaderString = script.text.trim();
let shader;
if (script.type === 'x-shader/x-vertex') {
shader = gl.createShader(gl.VERTEX_SHADER);
}
else if (script.type === 'x-shader/x-fragment') {
shader = gl.createShader(gl.FRAGMENT_SHADER);
}
else {
return null;
}
gl.shaderSource(shader, shaderString);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.error(gl.getShaderInfoLog(shader));
return null;
}
return shader;
}
};
- The autoResizeCanvas method takes a canvas element and dynamically resizes it to be fullscreen by watching browser-resizing events.
- The getShader function takes a gl instance and an id script to compile and return the shader source. Internally, getShader reads the source code of the script and stores it in a local variable. Then, it creates a new shader by using the WebGL createShader function. After that, it will add the source code to it using the shaderSource function. Finally, it will try to compile the shader using the compileShader function.
- Open ch02_09_ajax-car-final.html in your editor to see the following changes.
- Scroll to the init function where the necessary changes were made to use the utils.autoResizeCanvas method:
function init() {
const canvas = utils.getCanvas('webgl-canvas');
// Handle automatic resizing
utils.autoResizeCanvas(canvas);
// Retrieve a valid WebGL2 context
gl = utils.getGLContext(canvas);
gl.clearColor(0, 0, 0, 1);
gl.enable(gl.DEPTH_TEST);
initProgram();
// We are no longer blocking the render until `load` has
// resolved, as we're not returning a Promise.
load();
render();
}
- Scroll to the initProgram function inside of ch02_09_ajax-car-final.html, where the necessary changes were made to use the utils.getShader method:
function initProgram() {
// Retrieve shaders based on the shader script IDs
const vertexShader = utils.getShader(gl, 'vertex-shader');
const fragmentShader = utils.getShader(gl, 'fragment-shader');
program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
console.error('Could not initialize shaders');
}
gl.useProgram(program);
program.aVertexPosition = gl.getAttribLocation(program,
'aVertexPosition');
program.uProjectionMatrix = gl.getUniformLocation(program,
'uProjectionMatrix');
program.uModelViewMatrix = gl.getUniformLocation(program,
'uModelViewMatrix');
}
- Open ch02_09_ajax-car-final.html in a browser to see these changes in action.