WebGL进阶(八)绘制正方体

基础知识:

绘制基础正方体:

 构成正方体的基础单元为三角形,顶点默认逆时针连接,此时的面为正面,顺时针点连接的面为背面。

Q:为什么使用三角形?

A:1、简单 2、生成模型拟合度高较光滑 3、图形处理的高效性

多边形和曲面可能具有复杂的几何形状,但是由于三角形具有逼近性,通过合理的三角剖分可以很好地逼近复杂形状。在每个小三角形内部可以进行插值计算,从而实现光滑的渐变效果,提高渲染质量。计算机图形学中很多技术和算法都是基于三角形的,如光栅化、像素填充、着色和纹理映射等。通过使用三角形作为基本元素,这些算法可以更加高效地运行,从而加速图像处理和渲染过程。(Imagination官方博客-优快云博客)

背面剔除:

绘制简单纯色正方体:

绘制贴图正方体:

添加事件: 

效果:

源码:

绘制正方形(initBuffer)

            //    v6----- v5
            //   /|      /|
            //  v1------v0|
            //  | |     | |
            //  | |v7---|-|v4
            //  |/      |/
            //  v2------v3
// 初始化缓冲区并设置矩阵
function initBuffer() {

    // 定义立方体的顶点数据,每个顶点包含4个分量(x, y, z, w),其中w通常用于齐次坐标
    let arr = [
        // 前面
        1, 1, 1, 1,  -1, 1, 1, 1,  -1, -1, 1, 1,  1, 1, 1, 1,  -1, -1, 1, 1,  1, -1, 1, 1,
        // 右面
        1, 1, -1, 1,  1, 1, 1, 1,  1, -1, 1, 1,  1, 1, -1, 1,  1, -1, 1, 1,  1, -1, -1, 1,
        // 后面
        -1, 1, -1, 1,  1, 1, -1, 1,  1, -1, -1, 1,  -1, 1, -1, 1,  1, -1, -1, 1,  -1, -1, -1, 1,
        // 左面
        -1, 1, 1, 1,  -1, 1, -1, 1,  -1, -1, -1, 1,  -1, 1, 1, 1,  -1, -1, -1, 1,  -1, -1, 1, 1,
        // 上面
        -1, 1, -1, 1,  -1, 1, 1, 1,  1, 1, 1, 1,  -1, 1, -1, 1,  1, 1, 1, 1,  1, 1, -1, 1,
        // 下面
        -1, -1, 1, 1,  -1, -1, -1, 1,  1, -1, -1, 1,  -1, -1, 1, 1,  1, -1, -1, 1,  1, -1, 1, 1
    ]

    // 创建一个Float32Array类型的数组来存储顶点数据
    let pointPosition = new Float32Array(arr);

    // 获取顶点着色器中位置属性的位置
    let aPosition = webgl.getAttribLocation(webgl.program, "a_position");

    // 创建一个缓冲区对象
    let triangleBuffer = webgl.createBuffer();
    webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer);
    webgl.bufferData(webgl.ARRAY_BUFFER, pointPosition, webgl.STATIC_DRAW);
    webgl.enableVertexAttribArray(aPosition);
    webgl.vertexAttribPointer(aPosition, 4, webgl.FLOAT, false, 4 * 4, 0);

    // 初始化投影矩阵
    let ProjMatrix = glMatrix.mat4.create();
    glMatrix.mat4.identity(ProjMatrix);
    // 设置透视投影矩阵,参数为:矩阵、角度(转换为弧度)、宽高比、近剪裁面、远剪裁面
    glMatrix.mat4.perspective(ProjMatrix, angle * Math.PI / 180, webglDiv.clientWidth / webglDiv.clientHeight, 1, 1000);

    // 获取uniform变量u_formMatrix的位置
    let uniformMatrix1 = webgl.getUniformLocation(webgl.program, "u_formMatrix");

    // 初始化模型矩阵
    let ModelMatrix = glMatrix.mat4.create();
    glMatrix.mat4.identity(ModelMatrix);
    // 沿x轴平移模型
    glMatrix.mat4.translate(ModelMatrix, ModelMatrix, [1, 0, 0]);

    // 初始化视图矩阵
    let ViewMatrix = glMatrix.mat4.create();
    glMatrix.mat4.identity(ViewMatrix);
    // 设置视图矩阵,参数为:矩阵、相机位置、目标位置、上方向
    glMatrix.mat4.lookAt(ViewMatrix, [5, 0, 0], [0, 0, 0], [0, 1, 0]);

    // 计算模型视图矩阵
    let mvMatrix = glMatrix.mat4.create();
    glMatrix.mat4.identity(mvMatrix);
    glMatrix.mat4.multiply(mvMatrix, ViewMatrix, ModelMatrix);

    // 计算模型视图投影矩阵
    let mvpMatrix = glMatrix.mat4.create();
    glMatrix.mat4.identity(mvpMatrix);
    glMatrix.mat4.multiply(mvpMatrix, ProjMatrix, mvMatrix);
    // 将模型视图投影矩阵传递给着色器
    webgl.uniformMatrix4fv(uniformMatrix1, false, mvpMatrix);

    // 设置清除颜色为黑色,并清除颜色缓冲区和深度缓冲区
    webgl.clearColor(0, 0, 0, 1);
    webgl.clear(webgl.COLOR_BUFFER_BIT | webgl.DEPTH_BUFFER_BIT);
    // 启用深度测试
    webgl.enable(webgl.DEPTH_TEST);
    // 绘制36个顶点的三角形
    webgl.drawArrays(webgl.TRIANGLES, 0, 36);
}

简单矩形


let aColor = webgl.getAttribLocation(webgl.program, "a_color");
webgl.enableVertexAttribArray(aColor);
webgl.vertexAttribPointer(aColor, 4, webgl.FLOAT, false, 8 * 4, 4 * 4);

vertexAttribPointer(index, size, type, normalized, stride, offset)

告诉显卡从当前绑定的缓冲区(bindBuffer() 指定的缓冲区)中读取顶点数据。WebGL API 的 WebGLRenderingContext.vertexAttribPointer() 方法绑定当前缓冲区范围到gl.ARRAY_BUFFER,成为当前顶点缓冲区对象的通用顶点属性并指定它的布局 (缓冲区对象中的偏移量)。

index

指定要修改的顶点属性的索引。

size

指定每个顶点属性的组成数量,必须是 1,2,3 或 4。

type

指定数组中每个元素的数据类型可能是:

  • gl.BYTE:  有符号的 8 位整数,范围 [-128, 127]

  • gl.SHORT: 有符号的 16 位整数,范围 [-32768, 32767]

  • gl.UNSIGNED_BYTE:无符号的 8 位整数,范围 [0, 255]

  • gl.UNSIGNED_SHORT: 无符号的 16 位整数,范围 [0, 65535]

  • gl.FLOAT:  32 位 IEEE 标准的浮点数

  • 使用 WebGL2 版本的还可以使用以下值:

    • gl.HALF_FLOAT: 16 位 IEEE 标准的浮点数

normalized

当转换为浮点数时是否应该将整数数值归一化到特定的范围。

  •  对于类型gl.BYTEgl.SHORT,如果是 true 则将值归一化为 [-1, 1]
  •  对于类型gl.UNSIGNED_BYTEgl.UNSIGNED_SHORT,如果是 true 则将值归一化为 [0, 1]
  • 对于类型gl.FLOATgl.HALF_FLOAT,此参数无效

stride

一个 GLsizei,以字节为单位指定连续顶点属性开始之间的偏移量 (即数组中一行长度)。不能大于 255。如果 stride 为 0,则假定该属性是紧密打包的,即不交错属性,每个属性在一个单独的块中,下一个顶点的属性紧跟当前顶点之后。

offset

GLintptr指定顶点属性数组中第一部分的字节偏移量。必须是类型的字节长度的倍数。

贴图矩形

  let attribOutUV = webgl.getAttribLocation(webgl.program, "a_outUV");
            webgl.enableVertexAttribArray(attribOutUV);
            webgl.vertexAttribPointer(attribOutUV, 2, webgl.FLOAT, false, 6 * 4, 4 * 4);
            //矩阵变换
            let ProjMatrix = glMatrix.mat4.create();
            glMatrix.mat4.identity(ProjMatrix);
            //角度小,看到的物体大,角度大,看到的物体小。
            glMatrix.mat4.perspective(ProjMatrix, angle * Math.PI / 180, webglDiv.clientWidth / webglDiv.clientHeight, 1, 1000)    //修改可视域范围

            let uniformMatrix1 = webgl.getUniformLocation(webgl.program, "u_formMatrix");

            let ModelMatrix = glMatrix.mat4.create();
            glMatrix.mat4.identity(ModelMatrix);
            glMatrix.mat4.translate(ModelMatrix, ModelMatrix, [0, 0, 0]);

            let ViewMatrix = glMatrix.mat4.create();
            glMatrix.mat4.identity(ViewMatrix);
            glMatrix.mat4.lookAt(ViewMatrix, [5, 5, 5], [0, 0, 0], [0, 1, 0]);

            let mvMatrix = glMatrix.mat4.create();
            glMatrix.mat4.identity(mvMatrix);
            glMatrix.mat4.multiply(mvMatrix, ViewMatrix, ModelMatrix);

            let mvpMatrix = glMatrix.mat4.create();
            glMatrix.mat4.identity(mvpMatrix);
            glMatrix.mat4.multiply(mvpMatrix, ProjMatrix, mvMatrix);
            webgl.uniformMatrix4fv(uniformMatrix1, false, mvpMatrix)
            //纹理绘制
            uniformTexture = webgl.getUniformLocation(webgl.program, "texture");

            texture = initTexture("container2_specular.png");

 

交互事件

// 初始化缓冲区并设置矩阵变换
function initBuffer() {
    // 顶点数据准备,包含顶点位置和UV坐标
    let arr = [
        // 前面
        1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 0, 1, -1, -1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 0, 0, 1, -1, 1, 1, 1, 0,
        // 右面
        1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, -1, 1, 1, 0, 0, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 0, 0, 1, -1, -1, 1, 1, 0,
        // 后面
        -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 0, 1, 1, -1, -1, 1, 0, 0, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 0, 0, -1, -1, -1, 1, 1, 0,
        // 左面
        -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 0, -1, -1, -1, 1, 0, 0, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 0, 0, -1, -1, 1, 1, 1, 0,
        // 上面
        -1, 1, -1, 1, 0, 1, -1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, -1, 1, -1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, -1, 1, 1, 1,
        // 下面
        -1, -1, 1, 1, 0, 1, -1, -1, -1, 1, 0, 0, 1, -1, -1, 1, 1, 0, -1, -1, 1, 1, 0, 1, 1, -1, -1, 1, 1, 0, 1, -1, 1, 1, 1, 1
    ]

    // 创建一个Float32Array类型的数组来存储顶点数据
    let pointPosition = new Float32Array(arr);

    // 获取顶点着色器中位置属性的位置
    let aPosition = webgl.getAttribLocation(webgl.program, "a_position");
    // 创建一个缓冲区对象
    let triangleBuffer = webgl.createBuffer();
    webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer);
    webgl.bufferData(webgl.ARRAY_BUFFER, pointPosition, webgl.STATIC_DRAW);
    webgl.enableVertexAttribArray(aPosition);
    webgl.vertexAttribPointer(aPosition, 4, webgl.FLOAT, false, 6 * 4, 0);

    // 获取顶点着色器中UV坐标属性的位置
    let attribOutUV = webgl.getAttribLocation(webgl.program, "a_outUV");
    webgl.enableVertexAttribArray(attribOutUV);
    webgl.vertexAttribPointer(attribOutUV, 2, webgl.FLOAT, false, 6 * 4, 4 * 4);

    // 矩阵变换
    let ProjMatrix = glMatrix.mat4.create();
    glMatrix.mat4.identity(ProjMatrix);
    // 设置透视投影矩阵
    glMatrix.mat4.perspective(ProjMatrix, angle * Math.PI / 180, webglDiv.clientWidth / webglDiv.clientHeight, 1, 1000);

    let uniformMatrix1 = webgl.getUniformLocation(webgl.program, "u_formMatrix");

    // 模型矩阵的旋转
    let ModelMatrixx = glMatrix.mat4.create();
    glMatrix.mat4.identity(ModelMatrixx);
    glMatrix.mat4.rotate(ModelMatrixx, ModelMatrixx, offsetX * Math.PI / 180, [0, 1, 0]);

    let ModelMatrixy = glMatrix.mat4.create();
    glMatrix.mat4.identity(ModelMatrixy);
    glMatrix.mat4.rotate(ModelMatrixy, ModelMatrixy, offsetY * Math.PI / 180, [1, 0, 0]);

    let ModelMatrixxy = glMatrix.mat4.create();
    glMatrix.mat4.identity(ModelMatrixxy);
    glMatrix.mat4.multiply(ModelMatrixxy, ModelMatrixx, ModelMatrixy);

    // 模型矩阵的平移
    let ModelMatrixWheel = glMatrix.mat4.create();
    glMatrix.mat4.identity(ModelMatrixWheel);
    console.log(wheelMove);
    glMatrix.mat4.translate(ModelMatrixWheel, ModelMatrixWheel, [0, 0, wheelMove]);
    glMatrix.mat4.multiply(ModelMatrixWheel, ModelMatrixWheel, ModelMatrixxy);

    // 视图矩阵
    let ViewMatrix = glMatrix.mat4.create();
    glMatrix.mat4.identity(ViewMatrix);
    glMatrix.mat4.lookAt(ViewMatrix, [0, 0, 10], [0, 0, 0], [0, 1, 0]);

    // 模型视图矩阵
    let mvMatrix = glMatrix.mat4.create();
    glMatrix.mat4.identity(mvMatrix);
    glMatrix.mat4.multiply(mvMatrix, ViewMatrix, ModelMatrixWheel);

    // 模型视图投影矩阵
    let mvpMatrix = glMatrix.mat4.create();
    glMatrix.mat4.identity(mvpMatrix);
    glMatrix.mat4.multiply(mvpMatrix, ProjMatrix, mvMatrix);
    webgl.uniformMatrix4fv(uniformMatrix1, false, mvpMatrix);

    // 纹理绘制
    let uniformTexture = webgl.getUniformLocation(webgl.program, "texture");
    let texture = initTexture("container2_specular.png");
}

// 初始化纹理
function initTexture(imageFile) {
    let textureHandle = webgl.createTexture();
    textureHandle.image = new Image();
    textureHandle.image.src = imageFile;
    textureHandle.image.onload = function () {
        handleLoadedTexture(textureHandle);
    }
    return textureHandle;
}

// 处理加载完成的纹理
function handleLoadedTexture(texture) {
    webgl.bindTexture(webgl.TEXTURE_2D, texture);
    webgl.pixelStorei(webgl.UNPACK_FLIP_Y_WEBGL, true);

    webgl.texImage2D(webgl.TEXTURE_2D, 0, webgl.RGBA, webgl.RGBA, webgl.UNSIGNED_BYTE, texture.image);
    webgl.texParameteri(webgl.TEXTURE_2D, webgl.TEXTURE_MAG_FILTER, webgl.LINEAR); // 纹理放大方式
    webgl.texParameteri(webgl.TEXTURE_2D, webgl.TEXTURE_MIN_FILTER, webgl.LINEAR); // 纹理缩小方式
    webgl.texParameteri(webgl.TEXTURE_2D, webgl.TEXTURE_WRAP_S, webgl.CLAMP_TO_EDGE); // 纹理水平填充方式
    webgl.texParameteri(webgl.TEXTURE_2D, webgl.TEXTURE_WRAP_T, webgl.CLAMP_TO_EDGE); // 纹理垂直填充方式

    // 清除颜色缓冲区和深度缓冲区
    webgl.clearColor(0, 0, 0, 1);
    webgl.clear(webgl.COLOR_BUFFER_BIT | webgl.DEPTH_BUFFER_BIT);
    // 启用深度测试
    webgl.enable(webgl.DEPTH_TEST);
    // 激活纹理单元
    webgl.activeTexture(webgl.TEXTURE0);
    // 绑定纹理
    webgl.bindTexture(webgl.TEXTURE_2D, texture);
    // 将纹理传递给着色器
    webgl.uniform1i(uniformTexture, 0);
    // 绘制三角形
    webgl.drawArrays(webgl.TRIANGLES, 0, 36);
}

WebGL API 的 WebGLRenderingContext.bindTexture() 方法将给定的 WebGLTexture 绑定到目标(绑定点)。

复盘:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值