Loading a cube from gltf 2.0. WebGL, JavaScript

Published December 14, 2021
Advertisement

Sandbox: https://plnkr.co/edit/BYseznZdUBTrUmRa?preview

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Loading a cube from gltf 2.0. WebGL, JavaScript</title>
    <script src="https://cdn.jsdelivr.net/npm/gl-matrix@3.4.3/gl-matrix-min.js"></script>
</head>

<body>
    <canvas id="renderCanvas" width="400" height="400"></canvas>
    <script>
        loadFile("assets/BoxBlender3.gltf", (content) =>
        {
            const gltf = JSON.parse(content);

            loadBin("assets/BoxBlender3.bin", (binData) =>
            {
                const canvas = document.getElementById("renderCanvas");
                const gl = canvas.getContext("webgl");

                gl.enable(gl.DEPTH_TEST);

                const vertShaderSource =
                    `attribute vec4 aPosition;
                    attribute vec4 aNormal;
                    uniform mat4 uMvpMatrix;
                    uniform mat4 uModelMatrix;
                    uniform mat4 uNormalMatrix;
                    varying vec3 vPosition;
                    varying vec3 vNormal;
                    void main()
                    {
                        gl_Position = uMvpMatrix * aPosition;
                        vPosition = vec3(uModelMatrix * aPosition);
                        vNormal = normalize(vec3(uNormalMatrix * aNormal));
                    }`;

                const fragShaderSource =
                    `precision mediump float;
                    const vec3 lightColor = vec3(1.0, 1.0, 1.0);
                    const vec3 ambientLight = vec3(0.2, 0.2, 0.2);
                    uniform vec3 uLightPosition;
                    varying vec3 vPosition;
                    varying vec3 vNormal;
                    void main()
                    {
                        vec4 color = vec4(0.5, 1.0, 0.5, 1.0);
                        vec3 normal = normalize(vNormal);
                        vec3 lightDirection = normalize(uLightPosition - vPosition);
                        float nDotL = max(dot(lightDirection, normal), 0.0);
                        vec3 diffuse = lightColor * color.rgb * nDotL;
                        vec3 ambient = ambientLight * color.rgb;
                        gl_FragColor = vec4(diffuse + ambient, color.a);
                    }`;

                const vShader = gl.createShader(gl.VERTEX_SHADER);
                gl.shaderSource(vShader, vertShaderSource);
                gl.compileShader(vShader);
                let ok = gl.getShaderParameter(vShader, gl.COMPILE_STATUS);
                if (!ok) { console.log("vert: " + gl.getShaderInfoLog(vShader)); };

                const fShader = gl.createShader(gl.FRAGMENT_SHADER);
                gl.shaderSource(fShader, fragShaderSource);
                gl.compileShader(fShader);
                ok = gl.getShaderParameter(vShader, gl.COMPILE_STATUS);
                if (!ok) { console.log("frag: " + gl.getShaderInfoLog(fShader)); };

                const program = gl.createProgram();
                gl.attachShader(program, vShader);
                gl.attachShader(program, fShader);
                gl.bindAttribLocation(program, 0, "aPosition");
                gl.bindAttribLocation(program, 1, "aNormal");
                gl.linkProgram(program);
                ok = gl.getProgramParameter(program, gl.LINK_STATUS);
                if (!ok) { console.log("link: " + gl.getProgramInfoLog(program)); };
                gl.useProgram(program);

                // Create a cube
                //    v6----- v5
                //   /|      /|
                //  v1------v0|
                //  | |     | |
                //  | |v7---|-|v4
                //  |/      |/
                //  v2------v3

                // const vertPositions = [
                //     0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, // v0-v1-v2-v3 front
                //     0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, // v0-v3-v4-v5 right
                //     0.5, 0.5, 0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, // v0-v5-v6-v1 up
                //     -0.5, 0.5, 0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, // v1-v6-v7-v2 left
                //     -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5, -0.5, -0.5, 0.5, // v7-v4-v3-v2 down
                //     0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5 // v4-v7-v6-v5 back
                // ];
                const vertPosBuffer = gl.createBuffer();
                gl.bindBuffer(gl.ARRAY_BUFFER, vertPosBuffer);
                // gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertPositions), gl.STATIC_DRAW);
                // const vertPosData = new Uint8Array(binData, 0, 288);
                const vertPosData = new Float32Array(binData, 0, 288 / Float32Array.BYTES_PER_ELEMENT);
                gl.bufferData(gl.ARRAY_BUFFER, vertPosData, gl.STATIC_DRAW);
                gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
                gl.enableVertexAttribArray(0);

                // const normals = [
                //     0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, // v0-v1-v2-v3 front
                //     1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, // v0-v3-v4-v5 right
                //     0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, // v0-v5-v6-v1 up
                //     -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, // v1-v6-v7-v2 left
                //     0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, // v7-v4-v3-v2 down
                //     0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0 // v4-v7-v6-v5 back  
                // ];
                const normalBuffer = gl.createBuffer();
                gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);
                // gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(normals), gl.STATIC_DRAW);
                // const normalData = new Uint8Array(binData, 288, 288);
                const normalData = new Float32Array(binData, 288, 288 / Float32Array.BYTES_PER_ELEMENT);
                gl.bufferData(gl.ARRAY_BUFFER, normalData, gl.STATIC_DRAW);
                gl.vertexAttribPointer(1, 3, gl.FLOAT, false, 0, 0);
                gl.enableVertexAttribArray(1);

                // const indices = [
                //     0, 1, 2, 0, 2, 3,       // front
                //     4, 5, 6, 4, 6, 7,       // right
                //     8, 9, 10, 8, 10, 11,    // up
                //     12, 13, 14, 12, 14, 15, // left
                //     16, 17, 18, 16, 18, 19, // down
                //     20, 21, 22, 20, 22, 23  // back 
                // ];
                const indexBuffer = gl.createBuffer();
                gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
                // const indexData = new Uint8Array(binData, 576, 72);
                const indexData = new Uint16Array(binData, 576, 36);
                gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indexData, gl.STATIC_DRAW);

                const projMatrix = glMatrix.mat4.create();
                glMatrix.mat4.perspective(projMatrix, 55 * Math.PI / 180, 1, 0.1, 500);
                const viewMatrix = glMatrix.mat4.create();
                glMatrix.mat4.lookAt(viewMatrix, [10, 15, 20], [0, 0, 0], [0, 1, 0]);
                const projViewMatrix = glMatrix.mat4.create();
                glMatrix.mat4.mul(projViewMatrix, projMatrix, viewMatrix);

                const modelMatrix = glMatrix.mat4.create();
                glMatrix.mat4.fromTranslation(modelMatrix, [0, 0, 0]);
                glMatrix.mat4.rotate(modelMatrix, modelMatrix, 0 * Math.PI / 180, [1, 0, 0]);
                glMatrix.mat4.scale(modelMatrix, modelMatrix, [5, 5, 5]);
                const mvpMatrix = glMatrix.mat4.create();
                glMatrix.mat4.mul(mvpMatrix, projViewMatrix, modelMatrix);
                const uMvpMatrixLocation = gl.getUniformLocation(program, "uMvpMatrix");
                gl.uniformMatrix4fv(uMvpMatrixLocation, false, mvpMatrix);
                const uModelMatrixLocation = gl.getUniformLocation(program, "uModelMatrix");
                gl.uniformMatrix4fv(uModelMatrixLocation, false, modelMatrix);

                const normalMatrix = glMatrix.mat4.create();
                glMatrix.mat4.invert(normalMatrix, modelMatrix);
                glMatrix.mat4.transpose(normalMatrix, normalMatrix);
                const uNormalMatrixLocation = gl.getUniformLocation(program, "uNormalMatrix");
                gl.uniformMatrix4fv(uNormalMatrixLocation, false, normalMatrix);

                const lightPosition = glMatrix.vec3.fromValues(7, 8, 9);
                const uLightPositionLocation = gl.getUniformLocation(program, "uLightPosition");
                gl.uniform3fv(uLightPositionLocation, lightPosition);

                gl.clearColor(0.2, 0.2, 0.2, 1);
                gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
                gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);
            });
        });

        function loadFile(path, callback)
        {
            const xhr = new XMLHttpRequest();
            xhr.onreadystatechange = () =>
            {
                if (xhr.readyState === 4 && xhr.status != 404)
                {
                    callback(xhr.responseText);
                }
            };
            xhr.open("GET", path, true);
            xhr.send();
        }

        function loadBin(path, callback)
        {
            const xhr = new XMLHttpRequest();

            xhr.onreadystatechange = () =>
            {
                if (xhr.readyState === 4 && xhr.status != 404)
                {
                    callback(xhr.response);
                }
            };

            xhr.open("GET", path, true);
            xhr.responseType = "arraybuffer";
            xhr.send();
        }
    </script>
</body>

</html>
0 likes 0 comments

Comments

Nobody has left a comment. You can be the first!
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Advertisement