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


寫在前面

建議先閱讀下前面我的兩篇文章。

webgl學習筆記一-繪圖單點

webgl學習筆記二-繪圖多點

平移

1、關鍵點說明

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

  • 頂點坐標位置 : gl_Position = a_Position + u_Translation

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

2、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>

旋轉

1、關鍵點說明

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

x1 = xcosβ - ysinβ

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);

2、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>

縮放

1、關鍵點說明

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

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

  • 縮放API : gl.uniformMatrix4fv(u_xformMatrix, false, xformMatrix);

    • u_xformMatrix : 縮放因子
    • xformMatrix : 原始坐標

2、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>

寫在最后

  新博客


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM