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;
' +
            'uniform vec4 u_Translation;
' +
            'void main() {
' +
            '  gl_Position = a_Position + u_Translation;
' +
            '}
';

        //片元着色器
        var FSHADER_SOURCE =
            'void main() {
' +
            '  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.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;
        }



        // 清除指定<画布>的颜色
        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;
' +
            'uniform float u_CosB, u_SinB;
' +
            'void main() {
' +
            '  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;
' +
            '  gl_Position.z = a_Position.z;
' +
            '  gl_Position.w = 1.0;
' +
            '}
';

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

        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;
' +
            'uniform mat4 u_xformMatrix;
' +
            'void main() {
' +
            '  gl_Position = u_xformMatrix * a_Position;
' +
            '}
';

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

        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>

写在最后

  新博客

原文地址:https://www.cnblogs.com/chenmo-xpw/p/7466587.html