webgl立方体纹理旋转

开始

  • 初学webgl,刚学了纹理,然后就想像使用css制作立方体照片效果
  • 开始做了六个面都是一样的,没有达到目的,然后就想做六个面不同的
  • 谁知道,这一做,做完后头都晕了,但究其原因,就是那些基本的矩阵作用没搞懂,比如这个模型矩阵,就仅仅是操作传入的坐标,而且就算是绘制六个面,使用六组不同的坐标,也只需要传入一个矩阵就可以了,我之前还每次绘制都传了,反而导致了一些问题
  • 再就是纹理,按照书上的做法,每次加载完图片后,然后激活纹理单元 绑定纹理对象 配置纹理对象 接着给纹理源数据u_Sampler绑定纹理单元,这一系列操作都是在imge.onload的处理函数中进行的,所以一直没有分开,这就永远没法旋转了,因为旋转必须在外部再使用该纹理对象,并绑定纹理单元,总不可能每次都重新加载图片把,那也是不可能实现的
  • 最后旋转,只需要传递一次矩阵,也不知道怎么想的,之前每次绘制都传递矩阵,就出了问题,为什么会出问题之后再看看吧

效果

在这里插入图片描述

代码

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>立方体纹理</title>
</head>

<body onload="init()">
    <canvas id="canvas" width="600" height="600"></canvas>
    <script src="../cuon-matrix.js"></script>
    <script type="x-shader/x-vertex" id="shader-vs">
        precision lowp float;
        uniform   mat4 u_MvpMatrix;
        attribute vec4 a_Position;
        attribute vec2 a_TexCoord;
        varying   vec2 v_TexCoord;
        void main(){
            gl_Position = u_MvpMatrix * a_Position;
            v_TexCoord = a_TexCoord;
        }
    </script>
    <script type="x-shader/x-fragment" id="shader-fs">
        precision mediump   float;
        varying   vec2      v_TexCoord;
        uniform   sampler2D u_Sampler;
        void main(){
            gl_FragColor=texture2D(u_Sampler,v_TexCoord);
        }
    </script>
    <script>
        function init() {
            startWebgl()
        }
        function startWebgl() {
            const canvas = document.getElementById('canvas')
            const gl = canvas.getContext('webgl')
            if (!gl) {
                alert('浏览器不支持webgl')
            }
            gl.enable(gl.DEPTH_TEST)
            gl.enable(gl.CULL_FACE)
            gl.clearColor(0, 0, 0, 1)
            gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)

            const vs = document.getElementById('shader-vs').innerText;
            const fs = document.getElementById('shader-fs').innerText;

            const program = initProgram(gl, vs, fs)

            const a_Position = gl.getAttribLocation(program, 'a_Position')
            const a_TexCoord = gl.getAttribLocation(program, 'a_TexCoord')
            const u_Sampler = gl.getUniformLocation(program, "u_Sampler")

            const u_MvpMatrix = gl.getUniformLocation(program, 'u_MvpMatrix')

            const mvpMatrix = new Matrix4() // 模型视图投影矩阵

            // 纹理坐标的buffer
            const textureArray = [
                0, 1,
                0, 0,
                1, 1,
                1, 0,
            ]
            const textureBuffer = initVerTexBuffer(gl, textureArray)

            // 索引buffer
            const indexArray = new Uint8Array([
                0, 1, 2, 3, // 前
            ])
            const indexBuffer = gl.createBuffer()
            gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer)
            gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indexArray, gl.STATIC_DRAW)

            // 六个面的buffer
            const facesBuffer = []
            const facesArray = [
                [
                    // 前面四个
                    -1, 1, 1,     // v0
                    -1, -1, 1,    // v1
                    1, 1, 1,      // v2
                    1, -1, 1,     // v3
                ],
                [
                    // 左面
                    -1, 1, -1,    // v4
                    -1, -1, -1,   // v5
                    -1, 1, 1,     // v6
                    -1, -1, 1,    // v7
                ],
                [
                    // 右面
                    1, 1, 1,      // v8
                    1, -1, 1,     // v9
                    1, 1, -1,     // v10
                    1, -1, -1,    // v11
                ],
                [
                    // 上面
                    -1, 1, -1,    // v12
                    -1, 1, 1,     // v13
                    1, 1, -1,     // v14
                    1, 1, 1,      // v15
                ], [
                    // 下面
                    -1, -1, 1,   // v16
                    -1, -1, -1,  // v17
                    1, -1, 1,    // v18
                    1, -1, -1,   // v19
                ], [
                    // 后面四个
                    1, 1, -1,    // v20
                    1, -1, -1,   // v21
                    -1, 1, -1,   // v22
                    -1, -1, -1,  // v23
                ]
            ]
            for (let i = 0; i < facesArray.length; i++) {
                facesBuffer[i] = initVerTexBuffer(gl, facesArray[i])
            }

            // count用来指示6张图片是否全部加载完毕
            let count = 0;
            // 保存所有的纹理对象
            const textures = []
            for (let i = 0; i < 6; i++) {
                textures[i] = loadTexture(gl, `../img/${i + 1}.jpg`, facesBuffer[i])
            }

            // 初始化模型视图矩阵
            initMatrix(gl, u_MvpMatrix, mvpMatrix)
            let deg = 1
            // rotate函数在所有图片加载完毕后执行
            function rotate() {
                // 围绕该点旋转
                mvpMatrix.rotate(deg, 1, 1, -1)
                // 给模型视图矩阵重新赋值
                changeMatrix(gl, u_MvpMatrix, mvpMatrix)
                // 绘制所有纹理
                drawAllTexture(textures)
                requestAnimationFrame(rotate)
            }

            // 创建纹理对象,并返回该纹理对象
            function loadTexture(gl, src, buffer) {
                const texture = gl.createTexture()
                // textures[i]=texture
                const img = new Image()
                img.src = src
                texture.img = img
                img.onload = () => {
                    handleTexture(gl, texture, buffer)
                }
                return texture
            }

            // 图片加载后的处理
            function handleTexture(gl, texture, buffer) {
                // 指示纹理加载数量
                count++
                gl.bindTexture(gl.TEXTURE_2D, texture)
                gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1)
                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
                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, texture.img)
                // count为6,全部加载完毕
                if (count === 6) {
                    console.log('count: ', count);
                    // rotate()
                    drawAllTexture(textures)
                }
                gl.bindTexture(gl.TEXTURE_2D, null)
            }

            function drawAllTexture(textures) {
                gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
                for (let i = 0; i < textures.length; i++) {
                    drawTexture(facesBuffer[i], textures[i], a_Position, a_TexCoord)
                }
            }

            function changeMatrix(gl, u_MvpMatrix, mvpMatrix) {
                gl.uniformMatrix4fv(u_MvpMatrix, false, mvpMatrix.elements)
            }

            // 绘制单张纹理
            function drawTexture(buffer, texture, a_Position, a_TexCoord) {
                gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
                gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, 0, 0)
                gl.enableVertexAttribArray(a_Position)

                gl.bindBuffer(gl.ARRAY_BUFFER, textureBuffer)
                gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, 0, 0)
                gl.enableVertexAttribArray(a_TexCoord)

                gl.activeTexture(gl.TEXTURE0)
                gl.bindTexture(gl.TEXTURE_2D, texture)
                gl.uniform1i(u_Sampler, 0)

                gl.drawElements(gl.TRIANGLE_STRIP, 4, gl.UNSIGNED_BYTE, 0)
            }
        }

        // 初始化模型视图矩阵矩阵
        function initMatrix(gl, u_MvpMatrix, mvpMatrix) {
            mvpMatrix.setPerspective(30, 1, 1, 100)
            mvpMatrix.lookAt(6, 6, 6, 0, 0, 0, 0, 1, 0)
            mvpMatrix.rotate(0, 0, 1, 0)

            gl.uniformMatrix4fv(u_MvpMatrix, false, mvpMatrix.elements)
        }

        // 产生某个顶点的buffer
        function initVerTexBuffer(gl, bufferArray) {
            const buffer = gl.createBuffer()
            gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
            gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(bufferArray), gl.STATIC_DRAW)
            return buffer
        }

        // 初始化程序
        function initProgram(gl, vs, fs) {
            const shaderVs = gl.createShader(gl.VERTEX_SHADER)
            const shaderFs = gl.createShader(gl.FRAGMENT_SHADER)

            gl.shaderSource(shaderVs, vs)
            gl.compileShader(shaderVs)
            const successVs = gl.getShaderParameter(shaderVs, gl.COMPILE_STATUS)
            if (!successVs) {
                const error = gl.getShaderInfoLog(shaderVs)
                console.log('error: ', error);
                alert('shaderVs 创建失败: ', error)
                return;
            }
            gl.shaderSource(shaderFs, fs)
            gl.compileShader(shaderFs)
            const successFs = gl.getShaderParameter(shaderFs, gl.COMPILE_STATUS)
            if (!successFs) {
                const error = gl.getShaderInfoLog(shaderFs)
                console.log('error: ', error);
                alert('shaderFs 创建失败: ', error)
                return;
            }
            const program = gl.createProgram()
            gl.attachShader(program, shaderVs)
            gl.attachShader(program, shaderFs)
            gl.linkProgram(program)
            const successPm = gl.getProgramParameter(program, gl.LINK_STATUS)
            if (!successPm) {
                alert('program 创建失败')
                return;
            }
            gl.useProgram(program)
            gl.program = program
            return program;
        }
    </script>
</body>

</html>
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值