webgl學習筆記三-平移旋轉縮放

寫在前面html

建議先閱讀下前面個人兩篇文章。web

webgl學習筆記一-繪圖單點canvas

webgl學習筆記二-繪圖多點函數

平移學習

一、關鍵點說明

  • 頂點着色器須要加上 uniform vec4 u_Translation, 存儲平移的座標矢量。webgl

  • 頂點座標位置 : gl_Position = a_Position + u_Translation.net

  • 平移API : gl.uniform4f(u_Translation, Tx, Ty, Tz, 0.0);code

二、demo

  • html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<canvas id="canvas" width="200px" height="200px"></canvas>


</body>
</html>
  • JavaScript
<script>
    function main() {
        //頂點着色器程序
        var VSHADER_SOURCE =
            'attribute vec4 a_Position;\n' +
            'uniform vec4 u_Translation;\n' +
            'void main() {\n' +
            '  gl_Position = a_Position + u_Translation;\n' +
            '}\n';

        //片元着色器
        var FSHADER_SOURCE =
            'void main() {\n' +
            '  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' +
            '}\n';


        //獲取canvas元素
        var canvas = document.getElementById('canvas');
        //獲取繪製二維上下文
        var gl = canvas.getContext('webgl');
        if (!gl) {
            console.log("Failed");
            return;
        }
        //編譯着色器
        var vertShader = gl.createShader(gl.VERTEX_SHADER);
        gl.shaderSource(vertShader, VSHADER_SOURCE);
        gl.compileShader(vertShader);

        var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(fragShader, FSHADER_SOURCE);
        gl.compileShader(fragShader);
        //合併程序
        var shaderProgram = gl.createProgram();
        gl.attachShader(shaderProgram, vertShader);
        gl.attachShader(shaderProgram, fragShader);
        gl.linkProgram(shaderProgram);
        gl.useProgram(shaderProgram);

        //獲取座標點
        var a_Position = gl.getAttribLocation(shaderProgram, 'a_Position');

        if (a_Position < 0) {
            console.log('Failed to get the storage location of a_Position');
            return;
        }

        var n = initBuffers(gl, shaderProgram);

        if (n < 0) {
            console.log('Failed to set the positions');
            return;
        }



        // 清除指定<畫布>的顏色
        gl.clearColor(0.0, 0.0, 0.0, 1.0);

        // 清空 <canvas>
        gl.clear(gl.COLOR_BUFFER_BIT);

        gl.drawArrays(gl.TRIANGLES, 0, n);
    }

    function opt(gl, shaderProgram) {
        var Tx = 0.5, Ty = 0.5, Tz = 0.0;

        var u_Translation = gl.getUniformLocation(shaderProgram, 'u_Translation');
        if (!u_Translation) {
            console.log('Failed to get the storage location of u_Translation');
            return;
        }
        gl.uniform4f(u_Translation, Tx, Ty, Tz, 0.0);

    }

    function initBuffers(gl, shaderProgram) {
        var vertices = new Float32Array([
            0, 0.5,   -0.5, -0.5,   0.5, -0.5
        ]);
        var n = 3;//點的個數
        //建立緩衝區對象
        var vertexBuffer = gl.createBuffer();
        if (!vertexBuffer) {
            console.log("Failed to create the butter object");
            return -1;
        }
        //將緩衝區對象綁定到目標
        gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
        //向緩衝區寫入數據
        gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
        //獲取座標點
        var a_Position = gl.getAttribLocation(shaderProgram, 'a_Position');
        //將緩衝區對象分配給a_Position變量
        gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
        //鏈接a_Position變量與分配給它的緩衝區對象
        gl.enableVertexAttribArray(a_Position);
        return n;

    }

    main();
</script>

旋轉orm

一、關鍵點說明

  • 座標P(x,y,z) , 繞Z軸旋轉β角度變成 p1(x1, y1, z1)
    則根據數據三角函數公式可得:

x1 = xcosβ - ysinβhtm

y1 = xsinβ + ycosβ

z1=z

  • 頂點着色器須要加上 uniform float u_CosB, u_SinB 存儲旋轉角度。

  • 頂點座標位置 :
    • gl_Position.x = a_Position.x * u_CosB - a_Position.y * u_SinB
    • gl_Position.y = a_Position.x * u_SinB + a_Position.y * u_CosB
  • 旋轉API :
    • gl.uniform1f(u_CosB, cosB)
    • gl.uniform1f(u_sinB, sinB);

二、demo

  • JavaScript
<script>
    function main() {
        //頂點着色器程序
        var VSHADER_SOURCE =
            'attribute vec4 a_Position;\n' +
            'uniform float u_CosB, u_SinB;\n' +
            'void main() {\n' +
            '  gl_Position.x = a_Position.x * u_CosB - a_Position.y * u_SinB;\n' +
            '  gl_Position.y = a_Position.x * u_SinB + a_Position.y * u_CosB;\n' +
            '  gl_Position.z = a_Position.z;\n' +
            '  gl_Position.w = 1.0;\n' +
            '}\n';

        //片元着色器程序
        var FSHADER_SOURCE =
            'void main() {\n' +
            '  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' +
            '}\n';

        var Tx = 0.5, Ty = 0.5, Tz = 0.0;

        //獲取canvas元素
        var canvas = document.getElementById('canvas');
        //獲取繪製二維上下文
        var gl = canvas.getContext('webgl');
        if (!gl) {
            console.log("Failed");
            return;
        }
        //編譯着色器
        var vertShader = gl.createShader(gl.VERTEX_SHADER);
        gl.shaderSource(vertShader, VSHADER_SOURCE);
        gl.compileShader(vertShader);

        var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(fragShader, FSHADER_SOURCE);
        gl.compileShader(fragShader);
        //合併程序
        var shaderProgram = gl.createProgram();
        gl.attachShader(shaderProgram, vertShader);
        gl.attachShader(shaderProgram, fragShader);
        gl.linkProgram(shaderProgram);
        gl.useProgram(shaderProgram);

        //獲取座標點
        var a_Position = gl.getAttribLocation(shaderProgram, 'a_Position');

        if (a_Position < 0) {
            console.log('Failed to get the storage location of a_Position');
            return;
        }

        var n = initBuffers(gl, shaderProgram);

        if (n < 0) {
            console.log('Failed to set the positions');
            return;
        }

        opt(gl, shaderProgram);

        // 清除指定<畫布>的顏色
        gl.clearColor(0.0, 0.0, 0.0, 1.0);

        // 清空 <canvas>
        gl.clear(gl.COLOR_BUFFER_BIT);

        gl.drawArrays(gl.TRIANGLES, 0, n);
    }

    function opt(gl, program) {
        // 旋轉角度
        var ANGLE = 90.0;

        var radian = Math.PI * ANGLE / 180.0;
        var cosB = Math.cos(radian);
        var sinB = Math.sin(radian);

        var u_CosB = gl.getUniformLocation(program, 'u_CosB');
        var u_sinB = gl.getUniformLocation(program, 'u_SinB');

        gl.uniform1f(u_CosB, cosB);
        gl.uniform1f(u_sinB, sinB);
    }

    function initBuffers(gl, shaderProgram) {
        var vertices = new Float32Array([
            0, 0.5,   -0.5, -0.5,   0.5, -0.5
        ]);
        var n = 3;//點的個數
        //建立緩衝區對象
        var vertexBuffer = gl.createBuffer();
        if (!vertexBuffer) {
            console.log("Failed to create the butter object");
            return -1;
        }
        //將緩衝區對象綁定到目標
        gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
        //向緩衝區寫入數據
        gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
        //獲取座標點
        var a_Position = gl.getAttribLocation(shaderProgram, 'a_Position');
        //將緩衝區對象分配給a_Position變量
        gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
        //鏈接a_Position變量與分配給它的緩衝區對象
        gl.enableVertexAttribArray(a_Position);
        return n;

    }

    main();
</script>

縮放

一、關鍵點說明

  • 頂點着色器須要加上 uniform mat4 u_xformMatrix, 存儲縮放因子的座標矢量。

  • 頂點座標位置 : gl_Position = u_xformMatrix * a_Position

  • 縮放API : gl.uniformMatrix4fv(u_xformMatrix, false, xformMatrix);
    • u_xformMatrix : 縮放因子
    • xformMatrix : 原始座標

二、demo

  • JavaScript
<script>
    function main() {
        //頂點着色器程序
        var VSHADER_SOURCE =
            'attribute vec4 a_Position;\n' +
            'uniform mat4 u_xformMatrix;\n' +
            'void main() {\n' +
            '  gl_Position = u_xformMatrix * a_Position;\n' +
            '}\n';

        //片元着色器程序
        var FSHADER_SOURCE =
            'void main() {\n' +
            '  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' +
            '}\n';

        var Tx = 0.5, Ty = 0.5, Tz = 0.0;

        //獲取canvas元素
        var canvas = document.getElementById('canvas');
        //獲取繪製二維上下文
        var gl = canvas.getContext('webgl');
        if (!gl) {
            console.log("Failed");
            return;
        }
        //編譯着色器
        var vertShader = gl.createShader(gl.VERTEX_SHADER);
        gl.shaderSource(vertShader, VSHADER_SOURCE);
        gl.compileShader(vertShader);

        var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(fragShader, FSHADER_SOURCE);
        gl.compileShader(fragShader);
        //合併程序
        var shaderProgram = gl.createProgram();
        gl.attachShader(shaderProgram, vertShader);
        gl.attachShader(shaderProgram, fragShader);
        gl.linkProgram(shaderProgram);
        gl.useProgram(shaderProgram);

        //獲取座標點
        var a_Position = gl.getAttribLocation(shaderProgram, 'a_Position');

        if (a_Position < 0) {
            console.log('Failed to get the storage location of a_Position');
            return;
        }

        var n = initBuffers(gl, shaderProgram);

        if (n < 0) {
            console.log('Failed to set the positions');
            return;
        }

        opt(gl, shaderProgram);

        // 清除指定<畫布>的顏色
        gl.clearColor(0, 0, 0, 1);

        // 清空 <canvas>
        gl.clear(gl.COLOR_BUFFER_BIT);

        // Draw the rectangle
        gl.drawArrays(gl.TRIANGLES, 0, n);
    }

    // 縮放
    function opt(gl, program) {
        // 縮放因子

        var Sx = 1.0, Sy = 1.5, Sz = 1.0;
        var xformMatrix = new Float32Array([
            Sx,   0.0,  0.0,  0.0,
            0.0,  Sy,   0.0,  0.0,
            0.0,  0.0,  Sz,   0.0,
            0.0,  0.0,  0.0,  1.0
        ]);

        var u_xformMatrix = gl.getUniformLocation(program, 'u_xformMatrix');

        gl.uniformMatrix4fv(u_xformMatrix, false, xformMatrix);
    }

    // 構建緩衝區
    function initBuffers(gl, shaderProgram) {
        var vertices = new Float32Array([
            0, 0.5,   -0.5, -0.5,   0.5, -0.5
        ]);
        var n = 3;//點的個數
        //建立緩衝區對象
        var vertexBuffer = gl.createBuffer();
        if (!vertexBuffer) {
            console.log("Failed to create the butter object");
            return -1;
        }
        //將緩衝區對象綁定到目標
        gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
        //向緩衝區寫入數據
        gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
        //獲取座標點
        var a_Position = gl.getAttribLocation(shaderProgram, 'a_Position');
        //將緩衝區對象分配給a_Position變量
        gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
        //鏈接a_Position變量與分配給它的緩衝區對象
        gl.enableVertexAttribArray(a_Position);
        return n;
    }

    // 主方法調用
    main();
</script>

寫在最後

  新博客

相關文章
相關標籤/搜索