Jump to content

Let's create WebGL examples for practice


8Observer8
 Share

Recommended Posts

WebGL 1.0. Square translation using WASD and arrow keys

https://jsfiddle.net/tqnfyy53/

025_square_translation_using_keys.gif.fd3fa5d0b832905cc796aeea056f3fc5.gif

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

<head>
    <meta charset="UTF-8">
    <title>WebGL 1.0. Square translation using WASD and arrow keys</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.4.0/gl-matrix-min.js"></script>
    <style>
        #renderCanvas {
            border: 5px solid #aaaaaa;
        }
    </style>
</head>

<body>
    <p>Click here to active the window</p>
    <p>Use WASD or arrow keys</p>
    <canvas id="renderCanvas" width="250" height="250"></canvas>

    <script>
        var vertexShaderSource =
            `attribute vec2 a_Position;
            uniform mat4 u_ModelMatrix;

            void main()
            {
                gl_Position = u_ModelMatrix * vec4(a_Position, 0.0, 1.0);
            }`;

        var fragmentShaderSource =
            `precision mediump float;
            uniform vec3 u_Color;

            void main()
            {
                gl_FragColor = vec4(u_Color, 1.0);
            }`;

        var gl = document.getElementById("renderCanvas").getContext("webgl");

        var vShader = gl.createShader(gl.VERTEX_SHADER);
        gl.shaderSource(vShader, vertexShaderSource);
        gl.compileShader(vShader);

        var fShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(fShader, fragmentShaderSource);
        gl.compileShader(fShader);

        var program = gl.createProgram();
        gl.attachShader(program, vShader);
        gl.attachShader(program, fShader);
        gl.linkProgram(program);
        gl.useProgram(program);

        var vertices = new Float32Array([
            -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, -0.5
        ]);

        var vbo = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
        gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

        var a_Position = gl.getAttribLocation(program, "a_Position");
        gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(a_Position);

        var u_Color = gl.getUniformLocation(program, "u_Color");
        gl.uniform3f(u_Color, 0.635, 0.450, 0.125);

        var modelMatrix = mat4.create();
        var pos = { x: 0.1, y: 0.1 };
        var step = 0.2;

        window.addEventListener('keydown', function (event)
        {
            if (event.keyCode === 87 || event.keyCode === 38) // W, Up
                pos.y += step;
            else if (event.keyCode === 65 || event.keyCode === 37) // A, Left
                pos.x -= step;
            else if (event.keyCode === 83 || event.keyCode === 40) // S, Down
                pos.y -= step;
            else if (event.keyCode === 68 || event.keyCode === 39) // D, Right
                pos.x += step;
            draw(pos);
        });

        draw(pos);

        function draw(pos)
        {
            mat4.identity(modelMatrix);
            mat4.translate(modelMatrix, modelMatrix, vec3.fromValues(pos.x, pos.y, 0.0));
            mat4.scale(modelMatrix, modelMatrix, vec3.fromValues(0.2, 0.2, 0.2));

            var u_ModelMatrix = gl.getUniformLocation(program, "u_ModelMatrix");
            gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix);

            gl.clearColor(0.898, 0.984, 0.905, 1.0);
            gl.clear(gl.COLOR_BUFFER_BIT);

            gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
        }
    </script>
</body>

</html>

 

Link to comment
Share on other sites

WebGL 2.0. Square translation using WASD and arrow keys

https://jsfiddle.net/14z5m5hh/

025_square_translation_using_keys.gif.84898fbef854266f216fc41524a8ba1e.gif

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

<head>
    <meta charset="UTF-8">
    <title>WebGL 2.0. Square translation using WASD and arrow keys</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.4.0/gl-matrix-min.js"></script>
    <style>
        #renderCanvas {
            border: 5px solid #aaaaaa;
        }
    </style>
</head>

<body>
    <p>Click here to active the window</p>
    <p>Use WASD or arrow keys</p>
    <canvas id="renderCanvas" width="250" height="250"></canvas>

    <script>
        var vertexShaderSource =
            `#version 300 es
            
            in vec2 a_Position;
            uniform mat4 u_ModelMatrix;

            void main()
            {
                gl_Position = u_ModelMatrix * vec4(a_Position, 0.0, 1.0);
            }`;

        var fragmentShaderSource =
            `#version 300 es
            
            precision mediump float;
            uniform vec3 u_Color;
            out vec4 fragColor;

            void main()
            {
                fragColor = vec4(u_Color, 1.0);
            }`;

        var gl = document.getElementById("renderCanvas").getContext("webgl2");

        var vShader = gl.createShader(gl.VERTEX_SHADER);
        gl.shaderSource(vShader, vertexShaderSource);
        gl.compileShader(vShader);

        var fShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(fShader, fragmentShaderSource);
        gl.compileShader(fShader);

        var program = gl.createProgram();
        gl.attachShader(program, vShader);
        gl.attachShader(program, fShader);
        gl.linkProgram(program);
        gl.useProgram(program);

        var vertices = new Float32Array([
            -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, -0.5
        ]);

        var vbo = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
        gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

        var a_Position = gl.getAttribLocation(program, "a_Position");
        gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(a_Position);

        var u_Color = gl.getUniformLocation(program, "u_Color");
        gl.uniform3f(u_Color, 0.635, 0.450, 0.125);

        var modelMatrix = mat4.create();
        var pos = { x: 0.1, y: 0.1 };
        var step = 0.2;

        window.addEventListener('keydown', function (event)
        {
            if (event.keyCode === 87 || event.keyCode === 38) // W, Up
                pos.y += step;
            else if (event.keyCode === 65 || event.keyCode === 37) // A, Left
                pos.x -= step;
            else if (event.keyCode === 83 || event.keyCode === 40) // S, Down
                pos.y -= step;
            else if (event.keyCode === 68 || event.keyCode === 39) // D, Right
                pos.x += step;
            draw(pos);
        });

        draw(pos);

        function draw(pos)
        {
            mat4.identity(modelMatrix);
            mat4.translate(modelMatrix, modelMatrix, vec3.fromValues(pos.x, pos.y, 0.0));
            mat4.scale(modelMatrix, modelMatrix, vec3.fromValues(0.2, 0.2, 0.2));

            var u_ModelMatrix = gl.getUniformLocation(program, "u_ModelMatrix");
            gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix);

            gl.clearColor(0.898, 0.984, 0.905, 1.0);
            gl.clear(gl.COLOR_BUFFER_BIT);

            gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
        }
    </script>
</body>

</html>

 

Link to comment
Share on other sites

WebGL 1.0. Applying a texture to a square

https://jsfiddle.net/zjydm1ev/

026_applying_a_texture_to_a_square.png.61a92dc9f4031ebd13a184620a71d98d.png

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

<head>
    <meta charset="UTF-8">
    <title>WebGL 1.0. Applying a texture to a square</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.4.0/gl-matrix-min.js"></script>
    <style>
        #renderCanvas {
            border: 5px solid #aaaaaa;
        }
    </style>
</head>

<body>
    <canvas id="renderCanvas" width="250" height="250"></canvas>

    <script>
        var vertexShaderSource =
            `
            attribute vec2 a_Position;
            attribute vec2 a_TexCoord;
            uniform mat4 u_ModelMatrix;
            varying vec2 v_TexCoord;

            void main()
            {
                gl_Position = u_ModelMatrix * vec4(a_Position, 0.0, 1.0);
                v_TexCoord = a_TexCoord;
            }`;

        var fragmentShaderSource =
            `
            precision mediump float;
            uniform sampler2D u_Sampler;
            varying vec2 v_TexCoord;

            void main()
            {
                gl_FragColor = texture2D(u_Sampler, v_TexCoord);
            }`;

        var gl = document.getElementById("renderCanvas").getContext("webgl");

        var vShader = gl.createShader(gl.VERTEX_SHADER);
        gl.shaderSource(vShader, vertexShaderSource);
        gl.compileShader(vShader);

        var fShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(fShader, fragmentShaderSource);
        gl.compileShader(fShader);

        var program = gl.createProgram();
        gl.attachShader(program, vShader);
        gl.attachShader(program, fShader);
        gl.linkProgram(program);
        gl.useProgram(program);

        var verticesAndTexCoords = new Float32Array([
            -0.5, 0.5, 0.0, 1.0,    // (x, y), (u, v)
            -0.5, -0.5, 0.0, 0.0,
            0.5, 0.5, 1.0, 1.0,
            0.5, -0.5, 1.0, 0.0
        ]);

        var vbo = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
        gl.bufferData(gl.ARRAY_BUFFER, verticesAndTexCoords, gl.STATIC_DRAW);

        var FSIZE = verticesAndTexCoords.BYTES_PER_ELEMENT;

        var a_Position = gl.getAttribLocation(program, "a_Position");
        gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 4 * FSIZE, 0);
        gl.enableVertexAttribArray(a_Position);

        var a_TexCoord = gl.getAttribLocation(program, "a_TexCoord");
        gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, 4 * FSIZE, 2 * FSIZE);
        gl.enableVertexAttribArray(a_TexCoord);

        var image = new Image();

        image.onload = function ()
        {
            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
            gl.activeTexture(gl.TEXTURE0);

            var texture = gl.createTexture();
            gl.bindTexture(gl.TEXTURE_2D, texture);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);

            var u_Sampler = gl.getUniformLocation(program, "u_Sampler");
            gl.uniform1i(u_Sampler, 0);

            var modelMatrix = mat4.create();
            mat4.scale(modelMatrix, modelMatrix, vec3.fromValues(1.5, 1.5, 1.5));

            var u_ModelMatrix = gl.getUniformLocation(program, "u_ModelMatrix");
            gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix);

            gl.clearColor(0.898, 0.984, 0.905, 1.0);
            gl.clear(gl.COLOR_BUFFER_BIT);

            gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
        }
        image.crossOrigin = "";
        image.src = 'https://dl.dropboxusercontent.com/s/xi091ya34qqzda2/lightblueflower.jpg';
    </script>
</body>

</html>

 

Link to comment
Share on other sites

WebGL 2.0. Applying a texture to a square

https://jsfiddle.net/gd2uo3jg/

026_applying_a_texture_to_a_square.png.701a7c799df8e118d3e907b4c717930f.png

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

<head>
    <meta charset="UTF-8">
    <title>WebGL 2.0. Applying a texture to a square</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.4.0/gl-matrix-min.js"></script>
    <style>
        #renderCanvas {
            border: 5px solid #aaaaaa;
        }
    </style>
</head>

<body>
    <canvas id="renderCanvas" width="250" height="250"></canvas>

    <script>
        var vertexShaderSource =
            `#version 300 es

            in vec2 a_Position;
            in vec2 a_TexCoord;
            uniform mat4 u_ModelMatrix;
            out vec2 v_TexCoord;

            void main()
            {
                gl_Position = u_ModelMatrix * vec4(a_Position, 0.0, 1.0);
                v_TexCoord = a_TexCoord;
            }`;

        var fragmentShaderSource =
            `#version 300 es

            precision mediump float;
            uniform sampler2D u_Sampler;
            in vec2 v_TexCoord;
            out vec4 fragColor;

            void main()
            {
                fragColor = texture(u_Sampler, v_TexCoord);
            }`;

        var gl = document.getElementById("renderCanvas").getContext("webgl2");

        var vShader = gl.createShader(gl.VERTEX_SHADER);
        gl.shaderSource(vShader, vertexShaderSource);
        gl.compileShader(vShader);

        var fShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(fShader, fragmentShaderSource);
        gl.compileShader(fShader);

        var program = gl.createProgram();
        gl.attachShader(program, vShader);
        gl.attachShader(program, fShader);
        gl.linkProgram(program);
        gl.useProgram(program);

        var verticesAndTexCoords = new Float32Array([
            -0.5, 0.5, 0.0, 1.0,    // (x, y), (u, v)
            -0.5, -0.5, 0.0, 0.0,
            0.5, 0.5, 1.0, 1.0,
            0.5, -0.5, 1.0, 0.0
        ]);

        var vbo = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
        gl.bufferData(gl.ARRAY_BUFFER, verticesAndTexCoords, gl.STATIC_DRAW);

        var FSIZE = verticesAndTexCoords.BYTES_PER_ELEMENT;

        var a_Position = gl.getAttribLocation(program, "a_Position");
        gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 4 * FSIZE, 0);
        gl.enableVertexAttribArray(a_Position);

        var a_TexCoord = gl.getAttribLocation(program, "a_TexCoord");
        gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, 4 * FSIZE, 2 * FSIZE);
        gl.enableVertexAttribArray(a_TexCoord);

        var image = new Image();

        image.onload = function ()
        {
            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
            gl.activeTexture(gl.TEXTURE0);

            var texture = gl.createTexture();
            gl.bindTexture(gl.TEXTURE_2D, texture);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
            gl.texImage2D(gl.TEXTURE_2D , 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);

            var u_Sampler = gl.getUniformLocation(program, "u_Sampler");
            gl.uniform1i(u_Sampler, 0);

            var modelMatrix = mat4.create();
            mat4.scale(modelMatrix, modelMatrix, vec3.fromValues(1.5, 1.5, 1.5));

            var u_ModelMatrix = gl.getUniformLocation(program, "u_ModelMatrix");
            gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix);

            gl.clearColor(0.898, 0.984, 0.905, 1.0);
            gl.clear(gl.COLOR_BUFFER_BIT);

            gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
        }
        image.crossOrigin = "";
        image.src = 'https://dl.dropboxusercontent.com/s/xi091ya34qqzda2/lightblueflower.jpg';
    </script>
</body>

</html>

 

Link to comment
Share on other sites

  • 2 weeks later...

WebGL 1.0. Rotation animation

https://jsfiddle.net/8Observer8/gLpowbe2/

27_rotation_animation.gif.b1930dbb4733e834ca378924bcddad03.gif

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

<head>
    <meta charset="UTF-8">
    <title>WebGL 1.0. Rotation animation</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.4.0/gl-matrix-min.js"></script>
    <style>
        #renderCanvas {
            border: 5px solid #a8bdc4;
        }
    </style>
</head>

<body>
    <canvas id="renderCanvas" width="250" height="250"></canvas>

    <script>
        var vertexShaderSource =
            `attribute vec2 a_Position;
            uniform mat4 u_ModelMatrix;

            void main()
            {
                gl_Position = u_ModelMatrix * vec4(a_Position, 0.0, 1.0);
            }`;

        var fragmentShaderSource =
            `precision mediump float;
            uniform vec3 u_Color;

            void main()
            {
                gl_FragColor = vec4(u_Color, 1.0);
            }`;

        var canvas = document.getElementById("renderCanvas");
        var gl = canvas.getContext("webgl");

        var vShader = gl.createShader(gl.VERTEX_SHADER);
        gl.shaderSource(vShader, vertexShaderSource);
        gl.compileShader(vShader);

        var fShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(fShader, fragmentShaderSource);
        gl.compileShader(fShader);

        var program = gl.createProgram();
        gl.attachShader(program, vShader);
        gl.attachShader(program, fShader);
        gl.linkProgram(program);
        gl.useProgram(program);

        var vertices = new Float32Array([
            -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, -0.5
        ]);

        var vbo = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
        gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

        var a_Position = gl.getAttribLocation(program, "a_Position");
        gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(a_Position);

        var u_Color = gl.getUniformLocation(program, "u_Color");
        gl.uniform3f(u_Color, 0.207, 0.635, 0.125);

        var u_ModelMatrix = gl.getUniformLocation(program, "u_ModelMatrix");

        gl.clearColor(0.894, 0.976, 0.886, 1.0);

        var ANGLE_STEP = 45.0; // Rotation angle (degrees/second)
        var g_last = Date.now();

        var currentAngle = 0.0;
        var modelMatrix = mat4.create();

        var tick = function ()
        {
            currentAngle = animate(currentAngle);  // Update the rotation angle
            draw(4, currentAngle, modelMatrix, u_ModelMatrix);   // Draw the triangle
            requestAnimationFrame(tick, canvas); // Request that the browser calls tick
        };
        tick();

        function draw(n, currentAngle, modelMatrix, u_ModelMatrix)
        {
            mat4.identity(modelMatrix);
            mat4.rotateZ(modelMatrix, modelMatrix, currentAngle * Math.PI / 180);
            gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix);
            gl.clear(gl.COLOR_BUFFER_BIT);
            gl.drawArrays(gl.TRIANGLE_STRIP, 0, n);
        }

        function animate(angle)
        {
            // Calculate the elapsed time
            var now = Date.now();
            var elapsed = now - g_last;
            g_last = now;
            // Update the current rotation angle (adjusted by the elapsed time)
            var newAngle = angle + (ANGLE_STEP * elapsed) / 1000.0;
            return newAngle %= 360;
        }
    </script>
</body>

</html>

 

Link to comment
Share on other sites

WebGL 2.0. Rotation animation

https://jsfiddle.net/8Observer8/fLumroxa/

27_rotation_animation.gif.59e50fcfbc368276bec110ab11d1e575.gif

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

<head>
    <meta charset="UTF-8">
    <title>WebGL 2.0. Rotation animation</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.4.0/gl-matrix-min.js"></script>
    <style>
        #renderCanvas {
            border: 5px solid #a8bdc4;
        }
    </style>
</head>

<body>
    <canvas id="renderCanvas" width="250" height="250"></canvas>

    <script>
        var vertexShaderSource =
            `#version 300 es

            in vec2 a_Position;
            uniform mat4 u_ModelMatrix;

            void main()
            {
                gl_Position = u_ModelMatrix * vec4(a_Position, 0.0, 1.0);
            }`;

        var fragmentShaderSource =
            `#version 300 es
            
            precision mediump float;
            uniform vec3 u_Color;
            out vec4 fragColor;

            void main()
            {
                fragColor = vec4(u_Color, 1.0);
            }`;

        var canvas = document.getElementById("renderCanvas");
        var gl = canvas.getContext("webgl2");

        var vShader = gl.createShader(gl.VERTEX_SHADER);
        gl.shaderSource(vShader, vertexShaderSource);
        gl.compileShader(vShader);

        var fShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(fShader, fragmentShaderSource);
        gl.compileShader(fShader);

        var program = gl.createProgram();
        gl.attachShader(program, vShader);
        gl.attachShader(program, fShader);
        gl.linkProgram(program);
        gl.useProgram(program);

        var vertices = new Float32Array([
            -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, -0.5
        ]);

        var vbo = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
        gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

        var a_Position = gl.getAttribLocation(program, "a_Position");
        gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(a_Position);

        var u_Color = gl.getUniformLocation(program, "u_Color");
        gl.uniform3f(u_Color, 0.207, 0.635, 0.125);

        var u_ModelMatrix = gl.getUniformLocation(program, "u_ModelMatrix");

        gl.clearColor(0.894, 0.976, 0.886, 1.0);

        var ANGLE_STEP = 45.0; // Rotation angle (degrees/second)
        var g_last = Date.now();

        var currentAngle = 0.0;
        var modelMatrix = mat4.create();

        var tick = function ()
        {
            currentAngle = animate(currentAngle);  // Update the rotation angle
            draw(4, currentAngle, modelMatrix, u_ModelMatrix);   // Draw the triangle
            requestAnimationFrame(tick, canvas); // Request that the browser calls tick
        };
        tick();

        function draw(n, currentAngle, modelMatrix, u_ModelMatrix)
        {
            mat4.identity(modelMatrix);
            mat4.rotateZ(modelMatrix, modelMatrix, currentAngle * Math.PI / 180);
            gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix);
            gl.clear(gl.COLOR_BUFFER_BIT);
            gl.drawArrays(gl.TRIANGLE_STRIP, 0, n);
        }

        function animate(angle)
        {
            // Calculate the elapsed time
            var now = Date.now();
            var elapsed = now - g_last;
            g_last = now;
            // Update the current rotation angle (adjusted by the elapsed time)
            var newAngle = angle + (ANGLE_STEP * elapsed) / 1000.0;
            return newAngle %= 360;
        }
    </script>
</body>

</html>

 

Link to comment
Share on other sites

  • 1 month later...
  • 7 months later...
  • 3 months later...
I know how to improve workflow, productive of coding and code quality of our web Applications and Games. We can write specifications by Jasmine framework. I wrote a simple example how to write specs for Kata from CodeWars in TypeScript. It may be usefull for JS-developers too. See my short description and project on GitHub: https://goo.gl/DsuLXY This is an example how to run Jasmine Unit Tests in TS on Playground: https://goo.gl/Jrk6Zk I will rewrite my Snake Game to 3D with Unit Tests. I will give you a link on GitHub. Happy Coding!
grasshopper-summation-tdd-ts-200x500.png.da699ed9a483519f95dba238fa0faffe.png
Link to comment
Share on other sites

  • 1 month later...

Textured Rectangle with Transforms using ES5, WebGL 1.0, glMatrix

Playground

textured-rect-with-transforms-webgl-es5-webgl.png.fbbfe189461679d608a73760632aabec.png

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Textured Rectangle with Transforms using WebGL 1.0, ES5</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.8.1/gl-matrix-min.js"></script>
    <style>
        #renderCanvas {
            border: 5px solid #aaaaaa;
        }
    </style>
</head>

<body>
    <canvas id="renderCanvas" width="250" height="250"></canvas>

    <script>
        var vertexShaderSource =
            `
            attribute vec2 a_Position;
            attribute vec2 a_TexCoord;
            uniform mat4 u_ModelMatrix;
            varying vec2 v_TexCoord;

            void main()
            {
                gl_Position = u_ModelMatrix * vec4(a_Position, 0.0, 1.0);
                v_TexCoord = a_TexCoord;
            }`;

        var fragmentShaderSource =
            `
            precision mediump float;
            uniform sampler2D u_Sampler;
            varying vec2 v_TexCoord;

            void main()
            {
                gl_FragColor = texture2D(u_Sampler, v_TexCoord);
            }`;

        var gl = document.getElementById("renderCanvas").getContext("webgl");

        var vShader = gl.createShader(gl.VERTEX_SHADER);
        gl.shaderSource(vShader, vertexShaderSource);
        gl.compileShader(vShader);

        var fShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(fShader, fragmentShaderSource);
        gl.compileShader(fShader);

        var program = gl.createProgram();
        gl.attachShader(program, vShader);
        gl.attachShader(program, fShader);
        gl.linkProgram(program);
        gl.useProgram(program);

        var verticesAndTexCoords = new Float32Array([
            -0.5, 0.5, 0.0, 1.0,    // (x, y), (u, v)
            -0.5, -0.5, 0.0, 0.0,
            0.5, 0.5, 1.0, 1.0,
            0.5, -0.5, 1.0, 0.0
        ]);

        var vbo = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
        gl.bufferData(gl.ARRAY_BUFFER, verticesAndTexCoords, gl.STATIC_DRAW);

        var FSIZE = verticesAndTexCoords.BYTES_PER_ELEMENT;

        var a_Position = gl.getAttribLocation(program, "a_Position");
        gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 4 * FSIZE, 0);
        gl.enableVertexAttribArray(a_Position);

        var a_TexCoord = gl.getAttribLocation(program, "a_TexCoord");
        gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, 4 * FSIZE, 2 * FSIZE);
        gl.enableVertexAttribArray(a_TexCoord);

        gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);

        // Allows transperency with textures.
        gl.enable(gl.BLEND);
        gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);

        var image = new Image();

        image.onload = function()
        {
            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
            gl.activeTexture(gl.TEXTURE0);

            var texture = gl.createTexture();
            gl.bindTexture(gl.TEXTURE_2D, texture);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);

            var u_Sampler = gl.getUniformLocation(program, "u_Sampler");
            gl.uniform1i(u_Sampler, 0);

            var modelMatrix = mat4.create();
            mat4.translate(modelMatrix, modelMatrix, vec3.fromValues(0, 0.5, 0));
            mat4.rotateZ(modelMatrix, modelMatrix, 20.0 * Math.PI / 180.0);
            mat4.scale(modelMatrix, modelMatrix, vec3.fromValues(1 * 2.0, 1, 1));

            var u_ModelMatrix = gl.getUniformLocation(program, "u_ModelMatrix");
            gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix);

            gl.clearColor(0.898, 0.984, 0.905, 1.0);
            gl.clear(gl.COLOR_BUFFER_BIT);

            gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
        }
        image.crossOrigin = "";
        image.src = "https://dl.dropboxusercontent.com/s/nxvziah1a7n9txd/256px-WebGL_Logo.svg.png";
    </script>
</body>

</html>

 

Link to comment
Share on other sites

Textured Rectangle with Transforms using Webgl2, glMatrix, and TypeScript

Playground: https://plnkr.co/edit/OxENcZjrW1SeaGi3ncy9?p=preview

Source code: textured-rect-with-transforms-webgl2-typescript.zip

textured-rect-with-transforms-webgl-es5-webgl.png.4be7928c3195e9da7472967225a59a37.png

index.html

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Textured Rectangle with Transforms using WebGL 2.0, glMatrix, and TypeScript</title>
    <script data-main="dist/RequireConfig" src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js"></script>
    <link rel="stylesheet" href="css/style.css">
</head>

<body>
    <canvas id="renderCanvas" width="250" height="250"></canvas>
</body>

</html>

style.css

#renderCanvas {
    border: 5px solid #aaaaaa;
}

Program.ts

import { Scene } from "./Scene";

class Program
{
    public static Main(): void
    {
        let scene = new Scene("renderCanvas");
    }
}
Program.Main();

RequireConfig.ts

requirejs.config({
    baseUrl: "dist",
    paths: {
        "gl-matrix": "https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.8.1/gl-matrix-min"
    }
});

requirejs(["Program"], (Program) =>
{

});

Scene.ts

import { ShaderProgram } from "./ShaderProgram";
import { mat4, vec3 } from "gl-matrix";

export class Scene
{
    private _shaderProgram: ShaderProgram;

    public constructor(canvasName: string)
    {
        this._shaderProgram = new ShaderProgram(canvasName);
        let gl = this._shaderProgram.GetGL();

        this.Init();
    }

    private Init()
    {
        var verticesAndTexCoords = new Float32Array([
            -0.5, 0.5, 0.0, 1.0,    // (x, y), (u, v)
            -0.5, -0.5, 0.0, 0.0,
            0.5, 0.5, 1.0, 1.0,
            0.5, -0.5, 1.0, 0.0
        ]);

        let gl = this._shaderProgram.GetGL();
        let program = this._shaderProgram.GetProgram();

        let vbo = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
        gl.bufferData(gl.ARRAY_BUFFER, verticesAndTexCoords, gl.STATIC_DRAW);

        let FSIZE = verticesAndTexCoords.BYTES_PER_ELEMENT;

        let a_Position = gl.getAttribLocation(program, "a_Position");
        gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 4 * FSIZE, 0);
        gl.enableVertexAttribArray(a_Position);

        let a_TexCoord = gl.getAttribLocation(program, "a_TexCoord");
        gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, 4 * FSIZE, 2 * FSIZE);
        gl.enableVertexAttribArray(a_TexCoord);

        gl.enable(gl.BLEND);
        gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);

        let image = new Image();
        image.onload = () => { this.OnImageLoaded(image); };
        image.crossOrigin = "";
        image.src = "https://dl.dropboxusercontent.com/s/nxvziah1a7n9txd/256px-WebGL_Logo.svg.png";
    }

    private OnImageLoaded(image: HTMLImageElement)
    {
        let gl = this._shaderProgram.GetGL();
        let program = this._shaderProgram.GetProgram();

        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
        gl.activeTexture(gl.TEXTURE0);

        var texture = gl.createTexture();
        gl.bindTexture(gl.TEXTURE_2D, texture);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);

        var u_Sampler = gl.getUniformLocation(program, "u_Sampler");
        gl.uniform1i(u_Sampler, 0);

        var modelMatrix = mat4.create();
        mat4.translate(modelMatrix, modelMatrix, vec3.fromValues(0, 0.5, 0));
        mat4.rotateZ(modelMatrix, modelMatrix, 20.0 * Math.PI / 180.0);
        mat4.scale(modelMatrix, modelMatrix, vec3.fromValues(1 * 2.0, 1, 1));

        var u_ModelMatrix = gl.getUniformLocation(program, "u_ModelMatrix");
        gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix);

        gl.clearColor(0.898, 0.984, 0.905, 1.0);
        gl.clear(gl.COLOR_BUFFER_BIT);

        gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
    }
}

ShaderProgram.ts


export class ShaderProgram
{
    private _gl: WebGLRenderingContext;
    private _program: WebGLProgram;

    private _vertexShaderSource =
    `#version 300 es

    in vec2 a_Position;
    in vec2 a_TexCoord;
    uniform mat4 u_ModelMatrix;
    out vec2 v_TexCoord;

    void main()
    {
        gl_Position = u_ModelMatrix * vec4(a_Position, 0.0, 1.0);
        v_TexCoord = a_TexCoord;
    }`;

    private _fragmentShaderSource =
    `#version 300 es

    precision mediump float;
    uniform sampler2D u_Sampler;
    in vec2 v_TexCoord;
    out vec4 fragColor;

    void main()
    {
        fragColor = texture(u_Sampler, v_TexCoord);
    }`;

    public constructor(canvasName: string)
    {
        let canvas = document.getElementById(canvasName) as HTMLCanvasElement;
        this._gl = canvas.getContext("webgl2") as WebGLRenderingContext;

        let gl = this._gl;

        let vShader = gl.createShader(gl.VERTEX_SHADER);
        gl.shaderSource(vShader, this._vertexShaderSource);
        gl.compileShader(vShader);

        let fShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(fShader, this._fragmentShaderSource);
        gl.compileShader(fShader);

        this._program = gl.createProgram();
        gl.attachShader(this._program, vShader);
        gl.attachShader(this._program, fShader);
        gl.linkProgram(this._program);
        gl.useProgram(this._program);
    }

    public GetGL(): WebGLRenderingContext
    {
        return this._gl;
    }

    public GetProgram(): WebGLProgram
    {
        return this._program;
    }
}

package.json

{
  "name": "textured-rect-with-transforms-webgl2-typescript",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@types/gl-matrix": "^2.4.4",
    "@types/requirejs": "^2.1.31"
  }
}

tsconfig.json

{
    "compilerOptions": {
        "module": "amd",
        "sourceMap": true,
        "outDir": "dist",
        "target": "es5"
    },
    "exclude": [
        "node_modules"
    ]
}

 

Link to comment
Share on other sites

  • 1 year later...

Draw line. WebGL 1.0, TypeScript, glMatrix, jQuery, TypeScript

Playground: https://plnkr.co/edit/maq1F4JpXXulm9R8?preview
Source Code: draw-line-webgl10-ts.rar

draw-line-webgl10-ts.png.5ba996c86bbadd3c05ccf5c7ad7f1a47.png

index.html

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Line. WebGL 1.0, TypeScript</title>

    <script data-main="js/RequireConfig"
        src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js"></script>
</head>

<body>
    <canvas id="renderCanvas" width="300" height="300"></canvas>
</body>

</html>

Main.ts


import * as $ from "jquery";
import { mat4 } from "gl-matrix";

$(() =>
{
    // Get WebGL context
    let canvas = document.getElementById("renderCanvas") as HTMLCanvasElement;
    let gl = canvas.getContext("webgl");

    let vShaderSource = [
        "attribute vec3 aPosition;",
        "uniform mat4 uProjMatrix;",
        "void main()",
        "{",
        "    gl_Position = uProjMatrix * vec4(aPosition, 1.0);",
        "}"
    ].join("\n");

    let fShaderSource = [
        "void main()",
        "{",
        "    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);",
        "}"
    ].join("\n");

    let vShader = gl.createShader(gl.VERTEX_SHADER);
    gl.shaderSource(vShader, vShaderSource);
    gl.compileShader(vShader);
    let vMessage = gl.getShaderInfoLog(vShader);
    if (vMessage.length > 0) console.log("Verex Shader Error: " + vMessage);

    let fShader = gl.createShader(gl.FRAGMENT_SHADER);
    gl.shaderSource(fShader, fShaderSource);
    gl.compileShader(fShader);
    let fMessage = gl.getShaderInfoLog(fShader);
    if (fMessage.length > 0) console.log("Fragment Shader Error: " + fMessage);

    let program = gl.createProgram();
    gl.attachShader(program, vShader);
    gl.attachShader(program, fShader);
    gl.linkProgram(program);
    let progMessage = gl.getProgramInfoLog(program);
    if (progMessage.length > 0) console.log("Failed to link a program: " + progMessage);
    gl.useProgram(program);

    let vertexPositions = [
        0.0, 0.0, 0.0,
        70, 70, 0.0
    ];
    
    let vertexBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexPositions), gl.STATIC_DRAW);

    let aPositionLocation = gl.getAttribLocation(program, "aPosition");
    if (aPositionLocation < 0) console.log ("Failed to get a aPosition location");
    gl.vertexAttribPointer(aPositionLocation, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(aPositionLocation);

    let aProjMatrixLocation = gl.getUniformLocation(program, "uProjMatrix");
    if (!aProjMatrixLocation) console.log("Failed to get a uProjMatrix location");
    let projMatrix = mat4.ortho(mat4.create(), -100, 100, -100, 100, 10, -10);
    gl.uniformMatrix4fv(aProjMatrixLocation, false, projMatrix);

    gl.clearColor(0.9, 0.9, 0.9, 1.0);
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.drawArrays(gl.LINES, 0, 2);
});

RequireConfig.ts

requirejs.config({
    baseUrl: "js",
    paths: {
        "jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.0/jquery.min",
        "gl-matrix": "https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.8.1/gl-matrix-min"
    }
});

requirejs(["Main"], () => { });

tsconfig.json

{
    "compilerOptions": {
        "target": "ES5",
        "module": "AMD",
        "sourceMap": true,
        "outDir": "public/js"
    },
    "include": [
        "src/**/*.ts"
    ],
    "exclude": [
        "node_modules/*"
    ]
}

package.json

{
  "name": "draw-line-webgl10-ts",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "tsc -p tsconfig.json"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@types/gl-matrix": "^2.4.5",
    "@types/jquery": "^3.3.35",
    "@types/requirejs": "^2.1.31"
  }
}

 

Link to comment
Share on other sites

Draw line. WebGL 2.0, TypeScript, glMatrix, jQuery, TypeScript

Playground: https://plnkr.co/edit/6LDFAX2e8Dc0QCIo?preview
Source Code: draw-line-webgl20-ts.rar

draw-line-webgl20-ts.png.c05bc782f9c5558853c4fa0be1c9e159.png

index.html

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Line. WebGL 2.0, TypeScript</title>

    <script data-main="js/RequireConfig"
        src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js"></script>
</head>

<body>
    <canvas id="renderCanvas" width="300" height="300"></canvas>
</body>

</html>

Main.ts


import * as $ from "jquery";
import { mat4 } from "gl-matrix";

$(() =>
{
    // Get WebGL context
    let canvas = document.getElementById("renderCanvas") as HTMLCanvasElement;
    let gl = canvas.getContext("webgl2");

    let vShaderSource = [
        "#version 300 es",
        "layout(location = 0) in vec3 aPosition;",
        "uniform mat4 uProjMatrix;",
        "void main()",
        "{",
        "    gl_Position = uProjMatrix * vec4(aPosition, 1.0);",
        "}"
    ].join("\n");

    let fShaderSource = [
        "#version 300 es",
        "precision mediump float;",
        "out vec4 fragColor;",
        "void main()",
        "{",
        "    fragColor = vec4(1.0, 0.0, 0.0, 1.0);",
        "}"
    ].join("\n");

    let vShader = gl.createShader(gl.VERTEX_SHADER);
    gl.shaderSource(vShader, vShaderSource);
    gl.compileShader(vShader);
    let vMessage = gl.getShaderInfoLog(vShader);
    if (vMessage.length > 0) console.log("Verex Shader Error: " + vMessage);

    let fShader = gl.createShader(gl.FRAGMENT_SHADER);
    gl.shaderSource(fShader, fShaderSource);
    gl.compileShader(fShader);
    let fMessage = gl.getShaderInfoLog(fShader);
    if (fMessage.length > 0) console.log("Fragment Shader Error: " + fMessage);

    let program = gl.createProgram();
    gl.attachShader(program, vShader);
    gl.attachShader(program, fShader);
    gl.linkProgram(program);
    let progMessage = gl.getProgramInfoLog(program);
    if (progMessage.length > 0) console.log("Failed to link a program: " + progMessage);
    gl.useProgram(program);

    let vertexPositions = [
        0.0, 0.0, 0.0,
        70, 70, 0.0
    ];
    
    let vertexBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexPositions), gl.STATIC_DRAW);

    let aPositionLocation = gl.getAttribLocation(program, "aPosition");
    if (aPositionLocation < 0) console.log ("Failed to get a aPosition location");
    gl.vertexAttribPointer(aPositionLocation, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(aPositionLocation);

    let aProjMatrixLocation = gl.getUniformLocation(program, "uProjMatrix");
    if (!aProjMatrixLocation) console.log("Failed to get a uProjMatrix location");
    let projMatrix = mat4.ortho(mat4.create(), -100, 100, -100, 100, 10, -10);
    gl.uniformMatrix4fv(aProjMatrixLocation, false, projMatrix);

    gl.clearColor(0.9, 0.9, 0.9, 1.0);
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.drawArrays(gl.LINES, 0, 2);
});

RequireConfig.ts

requirejs.config({
    baseUrl: "js",
    paths: {
        "jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.0/jquery.min",
        "gl-matrix": "https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.8.1/gl-matrix-min"
    }
});

requirejs(["Main"], () => { });

tsconfig.json

{
    "compilerOptions": {
        "target": "ES5",
        "module": "AMD",
        "sourceMap": true,
        "outDir": "public/js"
    },
    "include": [
        "src/**/*.ts"
    ],
    "exclude": [
        "node_modules/*"
    ]
}

package.json

{
  "name": "draw-line-webgl10-ts",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "tsc -p tsconfig.json"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@types/gl-matrix": "^2.4.5",
    "@types/jquery": "^3.3.35",
    "@types/requirejs": "^2.1.31"
  }
}

 

Link to comment
Share on other sites

  • 1 year later...

Loading a cube from gltf 2.0 and draw it in pure WebGL

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

Source code: load-cube-from-gltf2-webgl-js.zip

image.png.5035fe687cf0ddc7c6d50dc49aa9f7c3.png

index.html

<!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/[email protected]/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>

BoxBlender3.gltf

{
    "asset" : {
        "generator" : "Khronos glTF Blender I/O v1.7.33",
        "version" : "2.0"
    },
    "scene" : 0,
    "scenes" : [
        {
            "name" : "Scene",
            "nodes" : [
                0
            ]
        }
    ],
    "nodes" : [
        {
            "mesh" : 0,
            "name" : "Cube"
        }
    ],
    "materials" : [
        {
            "doubleSided" : true,
            "name" : "Material",
            "pbrMetallicRoughness" : {
                "baseColorFactor" : [
                    0.800000011920929,
                    0.800000011920929,
                    0.800000011920929,
                    1
                ],
                "metallicFactor" : 0,
                "roughnessFactor" : 0.4000000059604645
            }
        }
    ],
    "meshes" : [
        {
            "name" : "Cube",
            "primitives" : [
                {
                    "attributes" : {
                        "POSITION" : 0,
                        "NORMAL" : 1
                    },
                    "indices" : 2,
                    "material" : 0
                }
            ]
        }
    ],
    "accessors" : [
        {
            "bufferView" : 0,
            "componentType" : 5126,
            "count" : 24,
            "max" : [
                1,
                1,
                1
            ],
            "min" : [
                -1,
                -1,
                -1
            ],
            "type" : "VEC3"
        },
        {
            "bufferView" : 1,
            "componentType" : 5126,
            "count" : 24,
            "type" : "VEC3"
        },
        {
            "bufferView" : 2,
            "componentType" : 5123,
            "count" : 36,
            "type" : "SCALAR"
        }
    ],
    "bufferViews" : [
        {
            "buffer" : 0,
            "byteLength" : 288,
            "byteOffset" : 0
        },
        {
            "buffer" : 0,
            "byteLength" : 288,
            "byteOffset" : 288
        },
        {
            "buffer" : 0,
            "byteLength" : 72,
            "byteOffset" : 576
        }
    ],
    "buffers" : [
        {
            "byteLength" : 648,
            "uri" : "BoxBlender3.bin"
        }
    ]
}

 

Edited by 8Observer8
Link to comment
Share on other sites

Simple example of sprite animation in WebGL 2.0:

fang-sprite-animation.gif.f75c5b9a391581b8526a75a8d64157de.gif

Sprite sheet: fang-idle.png.2b846a6ee482fd7f88d6317f26f32026.png

GIMP project: fang-idle.xcf

JavaScript version, GitHub: https://github.com/8Observer8/fang-idle-sprite-animation-webgl2-js
JavaScript version, Sandbox: https://plnkr.co/edit/deINAH86rUcDgry4?preview

TypeScript version, GitHub: https://github.com/8Observer8/fang-idle-sprite-animation-webgl2-ts
TypeScript version, Sandbox: https://plnkr.co/edit/lpEfcivRWP2tKUI2?preview

index.html

<!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>Fang Idle Sprite Animation. WebGL 2.0, JavaScript</title>

    <script src="https://cdn.jsdelivr.net/npm/[email protected]/gl-matrix-min.js"></script>
</head>

<body>
    <canvas id="renderCanvas" width="300" height="300"></canvas>

    <script>
        const canvas = document.getElementById("renderCanvas");
        const gl = canvas.getContext("webgl2");

        const vertShaderSrc =
            `#version 300 es
            in vec2 aPosition;
            in vec2 aTexCoord;
            uniform mat4 uMvpMatrix;
            out vec2 vTexCoord;
            void main()
            {
                gl_Position = uMvpMatrix * vec4(aPosition, 0.0, 1.0);
                vTexCoord = aTexCoord;
            }`;

        const fragShaderSrc =
            `#version 300 es
            precision mediump float;
            uniform sampler2D uSampler;
            in vec2 vTexCoord;
            out vec4 fragColor;
            void main()
            {
                fragColor = texture(uSampler, vTexCoord);
            }`;

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

        const fShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(fShader, fragShaderSrc);
        gl.compileShader(fShader);
        ok = gl.getShaderParameter(fShader, gl.COMPILE_STATUS);
        if (!ok) { console.log(gl.getShaderInfoLog(fShader));; }

        const program = gl.createProgram();
        gl.attachShader(program, vShader);
        gl.attachShader(program, fShader);
        gl.linkProgram(program);
        ok = gl.getProgramParameter(program, gl.LINK_STATUS);
        if (!ok) { console.log(gl.getProgramInfoLog(program)); }
        gl.useProgram(program);

        const aPositionLocation = gl.getAttribLocation(program, "aPosition");
        const aTexCoordLocation = gl.getAttribLocation(program, "aTexCoord");

        const vertPositions = [
            -0.5, -0.5, // frame 00
            0.5, -0.5,
            -0.5, 0.5,
            0.5, 0.5,
            -0.5, -0.5, // frame 01
            0.5, -0.5,
            -0.5, 0.5,
            0.5, 0.5,
            -0.5, -0.5, // frame 02
            0.5, -0.5,
            -0.5, 0.5,
            0.5, 0.5,
            -0.5, -0.5, // frame 03
            0.5, -0.5,
            -0.5, 0.5,
            0.5, 0.5
        ];
        const vertPosVBO = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vertPosVBO);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertPositions), gl.STATIC_DRAW);
        gl.vertexAttribPointer(aPositionLocation, 2, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(aPositionLocation);

        const texCoords = [
            0, 1, // frame 00
            1 / 4, 1,
            0, 0,
            1 / 4, 0,
            1 / 4, 1, // frame 01
            2 / 4, 1,
            1 / 4, 0,
            2 / 4, 0,
            2 / 4, 1, // frame 02
            3 / 4, 1,
            2 / 4, 0,
            3 / 4, 0,
            3 / 4, 1, // frame 03
            1, 1,
            3 / 4, 0,
            1, 0
        ];
        const texCoordVBO = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, texCoordVBO);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(texCoords), gl.STATIC_DRAW);
        gl.vertexAttribPointer(aTexCoordLocation, 2, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(aTexCoordLocation);

        const projMatrix = glMatrix.mat4.create();
        glMatrix.mat4.ortho(projMatrix, 0, 100, 0, 100, 100, -100);

        const viewMatrix = glMatrix.mat4.create();
        glMatrix.mat4.lookAt(viewMatrix, [0, 0, 90], [0, 0, 0], [0, 1, 0]);

        const projViewMatrix = glMatrix.mat4.create();
        const mvpMatrix = glMatrix.mat4.create();
        const modelMatrix = glMatrix.mat4.create();

        glMatrix.mat4.mul(projViewMatrix, projMatrix, viewMatrix);

        const uMvpMatrixLocation = gl.getUniformLocation(program, "uMvpMatrix");
        const uSamplerLocation = gl.getUniformLocation(program, "uSampler");
        gl.uniform1i(uSamplerLocation, 0);

        gl.enable(gl.BLEND);
        gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
        gl.clearColor(0.93, 0.95, 0.98, 1);

        let currentTime, lastTime, deltaTime;
        let animationTime = 0;
        const timePeriod = 250;
        let drawingIndex = 0;

        const image = new Image();
        image.onload =
            () =>
            {
                gl.activeTexture(gl.TEXTURE0);

                const texture = gl.createTexture();
                gl.bindTexture(gl.TEXTURE_2D, texture);
                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
                gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);

                glMatrix.mat4.identity(modelMatrix);
                glMatrix.mat4.translate(modelMatrix, modelMatrix, [50, 50, 0]);
                // glMatrix.mat4.rotateZ(modelMatrix, modelMatrix, 30 * Math. PI / 180);
                glMatrix.mat4.scale(modelMatrix, modelMatrix, [40, 50, 1]);
                glMatrix.mat4.mul(mvpMatrix, projViewMatrix, modelMatrix);
                gl.uniformMatrix4fv(uMvpMatrixLocation, false, mvpMatrix);

                lastTime = Date.now();
                animationLoop();
            };
        image.src = "assets/fang-idle.png";

        function animationLoop()
        {
            requestAnimationFrame(() => animationLoop());

            currentTime = Date.now();
            deltaTime = currentTime - lastTime;
            lastTime = currentTime;

            animationTime += deltaTime;
            if (animationTime >= timePeriod)
            {
                animationTime = 0;

                gl.clear(gl.COLOR_BUFFER_BIT);
                gl.drawArrays(gl.TRIANGLE_STRIP, drawingIndex, 4);

                drawingIndex += 4;
                if (drawingIndex >= 16) { drawingIndex = 0; }
            }
        }
    </script>
</body>

</html>

 

Edited by 8Observer8
Link to comment
Share on other sites

  • 2 months later...
  • 1 month later...
  • 5 months later...

Using glMatrix as an ES6 module

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

<head>
    <meta charset="UTF-8">
    <title>Example</title>
</head>

<body>
    <script type="importmap">
        {
            "imports": {
                "gl-matrix": "https://cdn.skypack.dev/[email protected]"
            }
        }
    </script>

    <script type="module">
        import { mat4, vec3, glMatrix } from "gl-matrix";

        function main() {
            // Conversion from degrees to radians
            const rad = glMatrix.toRadian(180);
            console.log(`radians = ${rad}`);
            // output: radians = 3.141592653589793

            // Identity matrix
            const m = mat4.create();
            console.log(`matrix = ${m}`);
            // output: matrix = 1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1

            // Vector addition
            const a = vec3.fromValues(1, 2, 3);
            const b = vec3.fromValues(4, 5, 6);
            const result = vec3.create();
            vec3.add(result, a, b);
            console.log(`result = ${result}`);
            // output: result = 5,7,9
        }
        main();
    </script>
</body>

</html>

 

Edited by 8Observer8
Link to comment
Share on other sites

  • 4 weeks later...

Load a texture using Promise, draw a triangle and import glMatrix as ES6-module

 

image.png.e1640087dde061eb1f8203406523e1c8.png

index.html

<!DOCTYPE html>

<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Example</title>
</head>

<body>
    <canvas id="renderCanvas" width="400" height="400"></canvas>

    <script type="importmap">
        {
            "imports": {
                "gl-matrix": "https://cdn.skypack.dev/[email protected]"
            }
        }
    </script>

    <script type="module">
        import { vec3 } from "gl-matrix";

        const gl = document.getElementById("renderCanvas").getContext("webgl");
        gl.clearColor(0.2, 0.2, 0.2, 1);

        const vertShaderSrc =
            `attribute vec3 aPosition;
            attribute vec2 aTexCoord;
            varying vec2 vTexCoord;
            void main() {
                gl_Position = vec4(aPosition, 1.0);
                vTexCoord = aTexCoord;
            }`;

        const fragShaderSrc =
            `precision mediump float;
            uniform sampler2D uSampler;
            varying vec2 vTexCoord;
            void main() {
                gl_FragColor = texture2D(uSampler, vTexCoord);
            }`;

        const vShader = gl.createShader(gl.VERTEX_SHADER);
        gl.shaderSource(vShader, vertShaderSrc);
        gl.compileShader(vShader);
        // console.log(gl.getShaderInfoLog(vShader));
        const fShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(fShader, fragShaderSrc);
        gl.compileShader(fShader);
        // console.log(gl.getShaderInfoLog(fShader));
        const program = gl.createProgram();
        gl.attachShader(program, vShader);
        gl.attachShader(program, fShader);
        gl.bindAttribLocation(program, 0, "aPosition");
        gl.bindAttribLocation(program, 1, "aTexCoord");
        gl.linkProgram(program);
        // console.log(gl.getProgramInfoLog(program));
        gl.useProgram(program);

        const vertPositions = [
            -0.5, -0.5, 0,
            0.5, -0.5, 0,
            0, 0.5, 0
        ];
        const vertPosBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vertPosBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertPositions),
            gl.STATIC_DRAW);
        gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(0);

        const texCoords = [
            0, 1,
            1, 1,
            0.5, 0
        ];
        const texCoordBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(texCoords),
            gl.STATIC_DRAW);
        gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(1);

        function loadImage(url) {
            return new Promise(resolve => {
                const image = new Image();
                image.onload = () => {
                    resolve(image);
                };
                image.src = url;
            });
        }

        function draw() {
            gl.clear(gl.COLOR_BUFFER_BIT);
            gl.drawArrays(gl.TRIANGLES, 0, 3);
        }

        async function load() {
            const path = "TexturesCom_Wood_ParquetStrip_512_albedo.png";
            const image = await loadImage(path);
            const texture = gl.createTexture();
            gl.bindTexture(gl.TEXTURE_2D, texture);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE,
                image);

            draw();
        }

        load();
    </script>
</body>

</html>

 

Edited by 8Observer8
Link to comment
Share on other sites

Load Ammo.js and a texture using Promise. WebGL, JavaScript

index.html

<!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>Load Ammo.js and a texture using Promise. Rollup, WebGL, JavaScript</title>
</head>

<body>
    <canvas id="renderCanvas" width="300" height="300"></canvas>

    <script type="importmap">
        {
            "imports": {
                "gl-matrix": "https://cdn.skypack.dev/[email protected]",
                "ammo-es": "https://dl.dropboxusercontent.com/s/1os9vvoo1pa3ajk/ammo-es.js"
            }
        }
    </script>

    <script type="module" src="./js/main.js"></script>
</body>

</html>

init-ammo.js

import AmmoLib from "ammo-es";

export let Ammo = null;
export let world = null;

export function initAmmo() {
    return new Promise(resolve => {
        AmmoLib().then((re) => {
            Ammo = re;

            const collisionConfiguration = new Ammo.btDefaultCollisionConfiguration();
            const dispatcher = new Ammo.btCollisionDispatcher(collisionConfiguration);
            const overlappingPairCache = new Ammo.btDbvtBroadphase();
            const solver = new Ammo.btSequentialImpulseConstraintSolver();

            world = new Ammo.btDiscreteDynamicsWorld(dispatcher, overlappingPairCache,
                solver, collisionConfiguration);
            world.setGravity(new Ammo.btVector3(0, -10, 0));

            resolve();
        });
    });
}

load-texture.js

import { gl } from "./webgl-context.js";

export default function loadTexture(url) {
    return new Promise(resolve => {
        const image = new Image();
        image.onload = () => {
            const texture = gl.createTexture();
            gl.bindTexture(gl.TEXTURE_2D, texture);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);
            resolve(texture);
        };
        image.src = url;
    });
}

main.js

import { vec3, mat4 } from "gl-matrix";
import { gl, initWebGLContext } from "./webgl-context.js";
import { Ammo, world, initAmmo } from "./init-ammo.js";
import loadTexture from "./load-texture.js";

async function init() {
    // Initialize the WebGL context
    if (!initWebGLContext("renderCanvas")) return;
    gl.clearColor(0.2, 0.2, 0.4, 1);
    gl.clear(gl.COLOR_BUFFER_BIT);

    // Init Ammo.js and print a gravity
    await initAmmo();
    const gravity = world.getGravity();
    console.log(gravity.x(), gravity.y(), gravity.z());

    // Load a texture
    const texture = await loadTexture("./assets/floor.png");
    console.log(texture);

    // Create a vector and a matrix
    const v = vec3.fromValues(1, 2, 3);
    console.log("v =", v);
    const m = mat4.create();
    console.log("m =", m);
}

init();

webgl-context.js

export let gl = null;

export function initWebGLContext(canvasName) {
    const canvas = document.getElementById(canvasName);
    if (canvas === null) {
        console.log(`Failed to get a canvas element with the name "${canvasName}"`);
        return false;
    }
    gl = canvas.getContext("webgl", { alpha: false, premultipliedAlpha: false });
    return true;
}

 

Edited by 8Observer8
Link to comment
Share on other sites

  • 2 weeks later...

Five-pointed star in WebGL1 and JavaScript

Playground: https://plnkr.co/edit/W49ndxcQemMgkAoP

image.png.ede77d643d0fd72d6ac1f09e7d9273a2.png

assets/shaders/devault.vert

attribute vec2 aPosition;
uniform mat4 uMvpMatrix;

void main() {
    gl_Position = uMvpMatrix * vec4(aPosition, 0.0, 1.0);
}

assets/shaders/devault.frag

precision mediump float;
uniform vec3 uColor;

void main() {
    gl_FragColor = vec4(uColor, 1.0);
}

index.html

<!DOCTYPE html>

<html>

<head>
    <meta charset="UTF-8">
    <title>Example</title>
</head>

<body>
    <canvas id="renderCanvas" width="300" height="300"></canvas>

    <script type="importmap">
        {
            "imports": {
                "gl-matrix": "https://cdn.skypack.dev/[email protected]"
            }
        }
    </script>

    <script type="module">
        import { mat4, vec3 } from "gl-matrix";

        let gl, program;

        function initWebGLContext(canvasName) {
            const canvas = document.getElementById(canvasName);
            if (canvas === null) {
                console.log(`Failed to get a canvas element with the name "${canvasName}"`);
                return false;
            }
            gl = canvas.getContext("webgl", { alpha: false, premultipliedAlpha: false });
            return true;
        }

        async function createShaderProgram(path, vertShaderFileName, fragShaderFileName) {
            let response = await fetch(path + vertShaderFileName);
            const vertShaderSource = await response.text();
            response = await fetch(path + fragShaderFileName);
            const fragShaderSource = await response.text();

            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));
                return null;
            };

            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));
                return null;
            };

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

            return program;
        }

        async function init() {
            if (!initWebGLContext("renderCanvas")) return;

            gl.clearColor(0.8, 0.8, 0.95, 1);
            gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);

            program = await createShaderProgram("assets/shaders/",
                "default.vert", "default.frag");

            const vertPositions = [
                0, 0, // 0
                0.1123, 0.1545,
                0, 0.5,
                0, 0, // 1
                0, 0.5,
                -0.1123, 0.1545
            ];
            const vertPosBuffer = gl.createBuffer();
            gl.bindBuffer(gl.ARRAY_BUFFER, vertPosBuffer);
            gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertPositions), gl.STATIC_DRAW);

            const aPositionLocation = gl.getAttribLocation(program, "aPosition");
            gl.vertexAttribPointer(aPositionLocation, 2, gl.FLOAT, false, 0, 0);
            gl.enableVertexAttribArray(aPositionLocation);

            const projMatrix = mat4.create();
            mat4.ortho(projMatrix, -50, 50, -50, 50, -10, 10);

            const viewMatrix = mat4.create();
            mat4.lookAt(viewMatrix, [0, 0, 10], [0, 0, 0], [0, 1, 0]);

            const projViewMatrix = mat4.create();
            mat4.mul(projViewMatrix, projMatrix, viewMatrix);

            const modelMatrix = mat4.create();
            const mvpMatrix = mat4.create();
            const uMvpMatrixLocation = gl.getUniformLocation(program, "uMvpMatrix");

            const uColorLocation = gl.getUniformLocation(program, "uColor");

            gl.clear(gl.COLOR_BUFFER_BIT);

            // Star
            const radStep = 2 * Math.PI / 5;
            for (let rad = 0; rad < 2 * Math.PI; rad += radStep) {
                mat4.fromTranslation(modelMatrix, [0, 0, 0]);
                mat4.rotateZ(modelMatrix, modelMatrix, rad);
                mat4.scale(modelMatrix, modelMatrix, [50, 50, 1]);
                mat4.mul(mvpMatrix, projViewMatrix, modelMatrix);
                gl.uniformMatrix4fv(uMvpMatrixLocation, false, mvpMatrix);
                gl.uniform3fv(uColorLocation, [0.5, 0, 0]);
                gl.drawArrays(gl.TRIANGLES, 0, 6);
            }
        }

        init();
    </script>
</body>

</html>

 

Edited by 8Observer8
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...