We have improved the structure of the code examples in this chapter. As the complexity of our WebGL applications increases, it is wise to have a good, maintainable, and clear design. We have left this section at the end of the chapter so you can use it as a reference when working on the exercises.
Just like in previous exercises, our entry point is the runWebGLApp
function which is called when the page is loaded. There we create an instance of WebGLApp
, as shown in the previous diagram.
This class encapsulates some of the utility functions that were present in our examples in previous chapters. It also declares a clear and simple life cycle for a WebGL application. WebGLApp
has three function hooks that we can map to functions in our web page. These hooks determine what functions will be called for each stage in the life cycle of the app. In the examples of this chapter, we have created the following mappings:
configureGLHook:
which points to the configure
function in the web pageloadSceneHook:
which is mapped to the load
function in the webpagedrawSceneHook:
which corresponds to the draw
function in the webpageA function hook can be described as a pointer to a function. In JavaScript, you can write:
function foo(){alert("function foo invoked");} var hook = foo; hook()
;
This fragment of code will execute foo
when hook()
is executed. This allows a pluggable behavior that is more difficult to express in fully typed languages.
WebGLApp
will use the function hooks to call configure, load
, and draw
in our page in that order.
After setting these hooks, the run
method is invoked.
We have created the following objects, each one in its own file:
Globals.js:
Contains the global variables used in the example.Program.js:
Creates the program using the shader definitions. Provides the mapping between JavaScript variables (prg.*
) and program attributes and uniforms.Scene.js:
Maintains a list of objects to be rendered. Contains the AJAX/JSON functionality to retrieve remote objects. It also allows adding local objects to the scene.Floor.js:
Defines a grid on the X-Z plane. This object is added to the Scene
to have a reference of where the floor is.Axis.js:
Represents the axis in world space. When added to the scene, we will have a reference of where the origin is.WebGLApp.js:
Represents a WebGL application. It has three function hooks that define the configuration stage, the scene loading stage, and the rendering stage. These hooks can be connected to functions in our web page.Utils.js:
Utility functions such as obtaining a gl
context.The following are the functions that define the life-cycle of a WebGLApp
application:
The configure
function sets some parameters of our gl
context, such as the color for clearing the canvas, and then it calls the initTransforms
function.
The following are the functions that initialize, update, and pass matrices to the shaders:
As you can see, the Model-View matrix, the Camera matrix, the Perspective matrix, and the Normal matrix are set up here:
function initTransforms(){ mat4.identity(mvMatrix); mat4.translate(mvMatrix, home); displayMatrix(mvMatrix); mat4.identity(cMatrix); mat4.inverse(mvMatrix,cMatrix); mat4.identity(pMatrix); mat4.perspective(30, c_width / c_height, 0.1, 1000.0, pMatrix); mat4.identity(nMatrix); mat4.set(mvMatrix, nMatrix); mat4.inverse(nMatrix); mat4.transpose(nMatrix); coords = COORDS_WORLD; }
In updateTransforms
, we use the contents of the global variables position
and rotation
to update the matrices. This is, of course, if the requestUpdate
variable is set to true
. We set requestUpdate
to true
from the GUI controls. The code for these is located at the bottom of the webpage (for instance, check the file ch4_ModelView_Rotation.html).
function updateTransforms(){ mat4.perspective(30, c_width / c_height, 0.1, 1000.0, pMatrix); if (coords == COORDS_WORLD){ mat4.identity(mvMatrix); mat4.translate(mvMatrix, position); mat4.rotateX(mvMatrix,rotation[0]*Math.PI/180); mat4.rotateY(mvMatrix,rotation[1]*Math.PI/180); mat4.rotateZ(mvMatrix,rotation[2]*Math.PI/180); } else{ mat4.identity(cMatrix); mat4.rotateX(cMatrix,rotation[0]*Math.PI/180); mat4.rotateY(cMatrix,rotation[1]*Math.PI/180); mat4.rotateZ(cMatrix,rotation[2]*Math.PI/180); mat4.translate(cMatrix,position); } }
This function performs the mapping:
function setMatrixUniforms(){ if (coords == COORDS_WORLD){ mat4.inverse(mvMatrix, cMatrix); displayMatrix(mvMatrix); gl.uniformMatrix4fv(prg.uMVMatrix, false, mvMatrix); } else{ mat4.inverse(cMatrix, mvMatrix); displayMatrix(cMatrix); } gl.uniformMatrix4fv(prg.uPMatrix, false, pMatrix); gl.uniformMatrix4fv(prg.uMVMatrix, false, mvMatrix); mat4.transpose(cMatrix, nMatrix); gl.uniformMatrix4fv(prg.uNMatrix, false, nMatrix); }
18.221.222.47