javascripthtmlwebglgl-matrix

gl-matrix is not included properly in webgl application


I'm trying to learn the basics of webgl and following the MDN tutorial here.

However, my rendering script (render.js) does not recognize the included gl-matrix script. Running index.html in Chrome(Version 88.0.4324.150 (Official Build) (64-bit)) I expect to see a red square against a black background. Instead, I get a black background and the following console error:

render.js:80 Uncaught ReferenceError: mat4 is not defined
    at DrawScene (render.js:80)
    at main (render.js:177)

Here are the corresponding files.

index.html

<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
<canvas id="canvas" width=640 height=480></canvas>
<script type="text/javascript" src="gl-matrix.js"></script>
<script type="text/javascript" src="render.js" ></script>
</body>
</html>

render.js


let loadShader= (gl,type,src) =>
{
    const shader = gl.createShader(type);
    gl.shaderSource(shader,src);
    gl.compileShader(shader);

    if(!gl.getShaderParameter(shader,gl.COMPILE_STATUS))
    {
        alert("An error occured during shader compilation: "+ gl.getShaderInfoLog(shader))
        gl.deleteShader(shader);
        return null;
    }

    return shader;
}


let initShaderProgram= (gl,vertShaderSrc,fragShaderSrc) =>
{
    const vertexShader=loadShader(gl,gl.VERTEX_SHADER ,vertShaderSrc);
    const fragShader=loadShader(gl,gl.FRAGMENT_SHADER, fragShaderSrc);

    const shaderProgram = gl.createProgram();
    gl.attachShader(shaderProgram,vertexShader);
    gl.attachShader(shaderProgram,fragShader);
    gl.linkProgram(shaderProgram);

    if(!gl.getProgramParameter(shaderProgram,gl.LINK_STATUS))
    {
          alert('Unable to initialize the shader program: ' + gl.getProgramInfoLog(shaderProgram));
          return null;
    }

    return shaderProgram;
}

let initBuffers = (gl) =>
{
    const positionBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);

    const positions = [
                       1.0,1.0,
                       1.0,-1.0,
                       -1.0,1.0,
                       -1.0,-1.0
                      ];


    gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(positions),gl.STATIC_DRAW);
    return {positions:positionBuffer};
} 




 let DrawScene = (gl,programInfo,buffers) =>
{
    gl.clearColor(0.0,0.0,0.0,1.0);
    gl.clearDepth(1.0);
    gl.enable(gl.DEPTH_TEST);
    gl.depthFunc(gl.LEQUAL);

    gl.clear(gl.COLOR_BUFFER_BIT| gl.DEPTH_BUFFER_BIT);


    const fieldOfView = 45*Math.PI/180;
    const aspectRatio = gl.canvas.clientWidth/gl.canvas.clientHeight;
    const zNear = 0.1;
    const zFar = 100;
    const projectionMatrix = mat4.create();

    mat4.perspective(projectionMatrix,
                     fieldOfView,
                     aspectRatio,
                     zNear,
                     zFar);

    let modelViewMatrix = mat4.create();
    mat4.translate(modelViewMatrix,
                   modelViewMatrix,
                    [0.0,0.0,-6.0]);


    {
        const numComponents = 2;
        const type = gl.FLOAT;
        const normalize=false;
        const stride=0;
        const offset=0;
        gl.vertexAttribPointer(programInfo.attribLocations.vertexPosition,
            numComponents,
            type,
            normalize,
            stride,
            offset
            );
        gl.enableVertexAttribArray(programInfo.attribLocations.vertexPosition);
    }

    gl.useProgram(programInfo.program);
    gl.uniformMatrix4fv(programInfo.uniformLocations.projectionMatrix,
        false,
        projectionMatrix);
    gl.uniformMatrix4fv(programInfo.uniformLocations.modelViewMatrix,
        false,
        modelViewMatrix);

    {
        const offset = 0;
        const vertexCount=4;
        gl.drawArrays(gl.TRIANGLE_STRIP,offset,vertexCount);
    }


};  



 let main = () =>
{
    const canvas =document.querySelector("#canvas")
    const gl =canvas.getContext("webgl")
    if(gl==null)
    {
        alert("gl is null")
        return;
    }



const  vsSource = 
`
attribute vec4 aVertexPosition;

uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;
void main()
{
    gl_Position=uProjectionMatrix*uModelViewMatrix*aVertexPosition;
} 
`;


const  fsSource = 
`
void main()
{
    gl_FragColor=vec4(0.7,0.0,0.11,1);
} 
`;

const shaderProgram=initShaderProgram(gl,vsSource,fsSource);


const ProgramInfo={
    program:shaderProgram,
    attribLocations: {vertexPosition:gl.getAttribLocation(shaderProgram,'aVertexPosition')},
    uniformLocations:{projectionMatrix: gl.getUniformLocation(shaderProgram,'uProjectionMatrix'),
                      modelViewMatrix: gl.getUniformLocation(shaderProgram,'uModelViewMatrix')
                      }
};



    buffers= initBuffers(gl);

    DrawScene(gl,ProgramInfo,buffers);

}

 window.onload=main

Solution

  • If I remember correctly newer versions of glMatrix only expose the glMatrix namespace rather than the individual classes. So in your case I think it's easiest if you make them available by destructuring it at the top of your render.js:

    const { vec2, vec3, mat3, mat4 } = glMatrix;