webGL-初识[保姆级文章、每节都有全部代码及在线演示]

1个月前 (06-03) 151次浏览 已收录 0个评论

导读

顶点着色器、图元装配、光栅化、attribute、uniform、片元着色器、webgl绘制单个点、线、动态绘制点、绘制多边形、顶点缓冲区、索引缓冲区、图形动态变化、平移、缩放、旋转、控制移动、多重纹理映射原理图、坐标对应关系、单纹理、


顶点着色器

它是逐顶点处理顶点数据。webgl顶点着色器程序在js中以字符串形式存在,通过编译后传递给顶点着色器执行,主要作用就是执行顶点着色器程序对顶点进行变换计算,比如

  • 顶点位置坐标执行进行旋转
  • 平移等矩阵变换,变换后新的顶点坐标然后赋值给内置变量,作为顶点着色器的输出
  • 图元装配和光栅化环节的输入

常用内置变量

  • gl_Position //点
  • gl_FrontFacing
  • gl_PointSize

图元装配

顶点变换后的操作就是图元装配,绘制函数drawArrays()或drawElements()的第一个参数绘制模式mode控制顶点如何装配图元,gl.Lines定义的是把两个顶点装配一个线条图元。

光栅化

把一个图形分解成一个个小的像素

常用变量

attribute

attribute vec4 a_position
存储限定符  类型  变量名

  • 必须是全局声明
  • 数据是从着色器外部(js代码)传过来的
  • vec4是矩阵
  • 只能在顶点着色器上使用

uniform

uniform vec4 u_FragColor

  • 不限制着色器
  • 全局声明


片元着色器

它是逐片元处理片元数据,通过内置变量gl_FragColor赋值可以给每一片元进行着色(换肤),还可以通过关键字discard指定哪些片元丢弃,被丢弃的片元不会出现帧缓冲区里。


绘制简单图形

绘制单个点

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

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
    </style>
    <script src="../glMatrix-0.9.6.min.js"></script>
    <script>
        //----顶点着色器
        // attribute vec4 a_position创建容器放入要绘制的坐标点 
        //uniform mat4 proj 承接投影坐标系,这样webgl的坐标就会像屏幕坐标系一样,即投影
        //void mian(){} shader入口函数
        // gl_Position 最终绘制点的坐标 
        //vec4 需要4个数的矩阵
        let vertextString = `
        attribute vec4 a_position;
        uniform mat4 proj;
        void main(void){
            gl_Position=proj * a_position;
            gl_PointSize=60.0;
        }
        `

        //----片元着色器
        let fragmentString = `
        void main(void){
            gl_FragColor = vec4(0,0,1.0,1.0);
        }
        `
        let webgl;
        let projMat4 = mat4.create()//创建4*4矩阵
        //入口函数
        function init() {
            initWebgl();
            initShader();
            initBuffer();
            draw();
        }
        //webgl初始化函数
        function initWebgl() {
            //获取webgl容器
            let webglDiv = document.getElementById('webglCanvas')
            //获取webgl对象
            webgl = webglDiv.getContext("webgl")
            //设置webgl的视觉区域
            webgl.viewport(0, 0, webglDiv.clientWidth, webglDiv.clientHeight)//00原点、以及xy轴的距离
            //通过插件设置webgl的投影坐标系
            mat4.ortho(0, webglDiv.clientWidth, webglDiv.clientHeight, 0, -1.0, 1.0, projMat4)//-1,1是z轴,projMat4是自定义的投影矩阵变量
        }
        //shader初始化函数,字符串转代码
        function initShader() {
            //创建一个顶点shader容器
            let vsshader = webgl.createShader(webgl.VERTEX_SHADER);
            // 创建一个片元shader容器
            let fsshader = webgl.createShader(webgl.FRAGMENT_SHADER);

            // 将各个文本对容器进行一对一的绑定
            webgl.shaderSource(vsshader, vertextString)
            webgl.shaderSource(fsshader, fragmentString)

            //编译打包容器、
            webgl.compileShader(vsshader)
            webgl.compileShader(fsshader)

            //创建项目容器
            let program = webgl.createProgram();
            //项目容器与shader绑定
            webgl.attachShader(program, vsshader)
            webgl.attachShader(program, fsshader)

            //连接与使用这个项目
            webgl.linkProgram(program)
            webgl.useProgram(program)

            //最后把这个构建的项目赋值给全局变量webgl的program属性里
            webgl.program = program
        }
        //数据缓冲区初始化函数 :数据传到shader
        function initBuffer() {
            let pointPosition = new Float32Array([100.0, 100.0, 0.0, 1.0])//x100,y100,z0,1.0矩阵分量

            //获取shader变量(通过js把shader里面的变量转化成能识别的js对象)
            let aPosition = webgl.getAttribLocation(webgl.program, "a_position")
            //把准备的 “一个” 数据赋值到shader里面
            webgl.vertexAttrib4fv(aPosition, pointPosition)
            //获取投影坐标系
            let uniformProj = webgl.getUniformLocation(webgl.program, "proj")
            webgl.uniformMatrix4fv(uniformProj, false, projMat4)
        }
        //webgl的绘制函数
        function draw() {
            webgl.clearColor(0.0, 0.0, 0.0, 1.0);
            webgl.clear(webgl.COLOR_BUFFER_BIT | webgl.DEPTH_BUFFER_BIT);
            //att: 点域 开始索引 绘制几个点
            webgl.drawArrays(webgl.POINTS, 0, 1)
        }
    </script>
</head>

<body onload="init()">
    <canvas id="webglCanvas" width="500" height="500"></canvas>
</body>

</html>
结果演示

动态绘制点

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

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
    </style>
    <script src="../glMatrix-0.9.6.min.js"></script>
    <script>
        //----顶点着色器
        // attribute vec4 a_position创建容器放入要绘制的坐标点 
        //uniform mat4 proj 承接投影坐标系,
        //void mian(){} shader入口函数
        // gl_Position 最终绘制点的坐标 
        let vertextString = `
        attribute vec3 a_position;
        void main(void){
            gl_Position=vec4(a_position,1.0) ;
            gl_PointSize=60.0;
        }
        `

        //----片元着色器
        let fragmentString = `
        precision mediump float;
        void main(void){
          gl_FragColor = vec4(0.0,0.0,1.0,1.0);
        }
        `
        let webgl;
        let projMat4 = mat4.create()
        //入口函数
        function init() {
            initWebgl();
            initShader();
            initBuffer();
            draw()
        }
        //webgl初始化函数
        function initWebgl() {
            //获取webgl容器
            let webglDiv = document.getElementById('webglCanvas')
            //获取webgl对象
            webgl = webglDiv.getContext("webgl")
            //设置webgl的视觉区域
            webgl.viewport(0, 0, webglDiv.clientWidth, webglDiv.clientHeight)//00原点、以及xy轴的距离
            //通过插件设置webgl的投影坐标系
            mat4.ortho(0, webglDiv.clientWidth, webglDiv.clientHeight, 0, -1.0, 1.0, projMat4)//-1,1是z轴,projMat4是自定义的投影矩阵变量
        }
        //shader初始化函数,字符串转代码
        function initShader() {
            //创建一个顶点shader容器
            let vsshader = webgl.createShader(webgl.VERTEX_SHADER);
            // 创建一个片元shader容器
            let fsshader = webgl.createShader(webgl.FRAGMENT_SHADER);

            // 将各个文本对容器进行一对一的绑定
            webgl.shaderSource(vsshader, vertextString)
            webgl.shaderSource(fsshader, fragmentString)

            //编译打包容器、
            webgl.compileShader(vsshader)
            webgl.compileShader(fsshader)

            //创建项目容器
            let program = webgl.createProgram();
            //项目容器与shader绑定
            webgl.attachShader(program, vsshader)
            webgl.attachShader(program, fsshader)

            //连接与使用这个项目
            webgl.linkProgram(program)
            webgl.useProgram(program)

            //最后把这个构建的项目赋值给全局变量webgl的program属性里
            webgl.program = program
        }
        let points = []
        //数据缓冲区初始化函数 :数据传到shader
        function initBuffer() {
            //获取shader变量
            let aPosition = webgl.getAttribLocation(webgl.program, "a_position")
            document.addEventListener("mousedown",function(e){
                let x=e.clientX
                let y=e.clientY
                
                let rect=e.target.getBoundingClientRect()
                
                //根据屏幕坐标、canvas坐标以及webgl坐标关系进行下边的转换(即倒推,也就是投影的工作)
                let canvasBoxLeft=1024/2
                let pointx=((x-rect.left)-canvasBoxLeft)/canvasBoxLeft
                let canvasBoxTop=700/2
                let pointy=(canvasBoxTop-(y-rect.top))/canvasBoxTop
                points.push(pointx)
                points.push(pointy)
                points.push(0)
                let pointPosition = new Float32Array(points)

                // 创建缓冲区,解决只能赋值一个数据的问题
                let pointBuffer=webgl.createBuffer()
                //绑定类型为数组的缓冲区
                webgl.bindBuffer(webgl.ARRAY_BUFFER,pointBuffer)
                //缓冲区类型 赋值内容 数据类型:静态绘制,即只绘制一次
                webgl.bufferData(webgl.ARRAY_BUFFER,pointPosition,webgl.STATIC_DRAW)
                //启用
                webgl.enableVertexAttribArray(aPosition)
                //把准备的 "所有" 数据赋值给shader里面
                //shader变量  一个点需要绘制几个数:xyz 数的类型 是否转置 字节数:Float32Array是4字节 从第几个偏移算起
                webgl.vertexAttribPointer(aPosition,3,webgl.FLOAT,false,0,0)

                //draw
                webgl.clearColor(0.0, 0.0, 0.0, 1.0);
                webgl.clear(webgl.COLOR_BUFFER_BIT | webgl.DEPTH_BUFFER_BIT);
                //att: 点域 开始索引 绘制几个点
                webgl.drawArrays(webgl.POINTS, 0, points.length/3)
                
            })
            //获取投影坐标系(坐标转换)
            let uniformProj = webgl.getUniformLocation(webgl.program, "proj")
            webgl.uniformMatrix4fv(uniformProj, false, projMat4)
        }
        function draw() {
            webgl.clearColor(0.0, 0.0, 0.0, 1.0);
            webgl.clear(webgl.COLOR_BUFFER_BIT | webgl.DEPTH_BUFFER_BIT);
        }
    </script>
</head>

<body onload="init()">
    <canvas id="webglCanvas" width="1024" height="700"></canvas>
</body>

</html>
结果演示

顶点缓冲区-ARRAY_BUFFER

绘制线

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

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../glMatrix-0.9.6.min.js"></script>
    <script>
        /**
         * gl.LINES 两点一线(必须成对出现的点)
         * gl.LINE_STRIP 所有的点连成的线
         * gl.LINE_LOOP 所有点闭合连成的线(首尾相连)
         **/
        let vertextString = `
        attribute vec4 a_position;
        uniform mat4 proj;
        void main(void){
            gl_Position=proj * a_position;
            gl_PointSize=60.0;
        }
        `

        //----片元着色器
        let fragmentString = `
        void main(void){
            gl_FragColor = vec4(0,0,1.0,1.0);
        }
        `
        let webgl;
        let projMat4 = mat4.create()
        //入口函数
        function init() {
            initWebgl();
            initShader();
            initBuffer();
            draw();
        }
        //webgl初始化函数
        function initWebgl() {
            //获取webgl容器
            let webglDiv = document.getElementById('webglCanvas')
            //获取webgl对象
            webgl = webglDiv.getContext("webgl")
            //设置webgl的视觉区域
            webgl.viewport(0, 0, webglDiv.clientWidth, webglDiv.clientHeight)//00原点、以及xy轴的距离
            //通过插件设置webgl的投影坐标系
            mat4.ortho(0, webglDiv.clientWidth, webglDiv.clientHeight, 0, -1.0, 1.0, projMat4)//-1,1是z轴,projMat4是自定义的投影矩阵变量
        }
        //shader初始化函数,字符串转代码
        function initShader() {
            //创建一个顶点shader容器
            let vsshader = webgl.createShader(webgl.VERTEX_SHADER);
            // 创建一个片元shader容器
            let fsshader = webgl.createShader(webgl.FRAGMENT_SHADER);

            // 将各个文本对容器进行一对一的绑定
            webgl.shaderSource(vsshader, vertextString)
            webgl.shaderSource(fsshader, fragmentString)

            //编译打包容器、
            webgl.compileShader(vsshader)
            webgl.compileShader(fsshader)
            //预检
            if (!webgl.getShaderParameter(vsshader, webgl.COMPILE_STATUS)) {
                var err = webgl.getShaderInfoLog(vsshader);
                alert(err);
                return;
            }
            if (!webgl.getShaderParameter(fsshader, webgl.COMPILE_STATUS)) {
                var err = webgl.getShaderInfoLog(fsshader);
                alert(err);
                return;
            }

            //创建项目容器
            let program = webgl.createProgram();
            //项目容器与shader绑定
            webgl.attachShader(program, vsshader)
            webgl.attachShader(program, fsshader)

            //连接与使用这个项目
            webgl.linkProgram(program)
            // 预检连接
            if(!webgl.getProgramParameter(program,webgl.LINK_STATUS)){
                let err=webgl.getProgramInfoLog(program)
                alert(err)
                return
            }
            webgl.useProgram(program)

            //最后把这个构建的项目赋值给全局变量webgl的program属性里
            webgl.program = program
        }
        //数据缓冲区初始化函数 :数据传到shader
        function initBuffer() {
            //获取shader变量
            let aPosition = webgl.getAttribLocation(webgl.program, "a_position")
            let arr = [
                100.0, 100.0, 0,
                200.0, 200.0, 0,
                300.0,200.0,0,
                400.0,600.0,0
            ]
            let pointPosition = new Float32Array(arr)//x100,y100,z0 1.0矩阵分量
            //顶点数据的配置
            let lineBuffer = webgl.createBuffer()
            //绑定类型为数组的缓冲区
            webgl.bindBuffer(webgl.ARRAY_BUFFER, lineBuffer)
            //缓冲区类型 赋值内容 数据类型:静态绘制
            webgl.bufferData(webgl.ARRAY_BUFFER, pointPosition, webgl.STATIC_DRAW)
            //启用
            webgl.enableVertexAttribArray(aPosition)
            //把准备的 "所有" 数据赋值给shader里面
            //shader变量  一个点需要绘制几个数:xyz 数的类型 是否转置 字节数 从第几个偏移算起
            webgl.vertexAttribPointer(aPosition, 3, webgl.FLOAT, false, 3*4, 0)

            //获取投影坐标系
            let uniformProj = webgl.getUniformLocation(webgl.program, "proj")
            webgl.uniformMatrix4fv(uniformProj, false, projMat4)
        }
        //webgl的绘制函数
        function draw() {
            webgl.clearColor(0.0, 0.0, 0.0, 1.0);
            webgl.clear(webgl.COLOR_BUFFER_BIT | webgl.DEPTH_BUFFER_BIT);
            //att: 点域 开始索引 绘制几个点
            // webgl.drawArrays(webgl.LINES, 0, 4)
            // webgl.drawArrays(webgl.LINE_STRIP, 0, 4)
            webgl.drawArrays(webgl.LINE_LOOP, 0, 4)

            //绘制三角形
            // webgl.drawArrays(webgl.TRIANGLES, 0, 3)
            // webgl.drawArrays(webgl.TRIANGLE_STRIP, 0, 4)
        }
    </script>
</head>

<body onload="init()">
    <canvas id="webglCanvas" width="1024" height="700"></canvas>
</body>

</html>
结果演示

绘制多边形-五角星

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

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../glMatrix-0.9.6.min.js"></script>
    <script>
        // gl_Position = vec4(a_position,1.0) 因为五角星处在中间,所以不使用投影坐标转换会更简单
        let vertextString = `
        attribute vec3 a_position;
        void main(void){
            gl_Position=vec4(a_position,1.0);
            gl_PointSize=60.0;
        }
        `

        //----片元着色器
        let fragmentString = `
        void main(void){
            gl_FragColor = vec4(0,0,1.0,1.0);
        }
        `
        let webgl;
        let projMat4 = mat4.create()
        //入口函数
        function init() {
            initWebgl();
            initShader();
            initBuffer();
            draw();
        }
        //webgl初始化函数
        function initWebgl() {
            //获取webgl容器
            let webglDiv = document.getElementById('webglCanvas')
            //获取webgl对象
            webgl = webglDiv.getContext("webgl")
            //设置webgl的视觉区域
            webgl.viewport(0, 0, webglDiv.clientWidth, webglDiv.clientHeight)//00原点、以及xy轴的距离
            //通过插件设置webgl的投影坐标系
            mat4.ortho(0, webglDiv.clientWidth, webglDiv.clientHeight, 0, -1.0, 1.0, projMat4)//-1,1是z轴,projMat4是自定义的投影矩阵变量
        }
        //shader初始化函数,字符串转代码
        function initShader() {
            //创建一个顶点shader容器
            let vsshader = webgl.createShader(webgl.VERTEX_SHADER);
            // 创建一个片元shader容器
            let fsshader = webgl.createShader(webgl.FRAGMENT_SHADER);

            // 将各个文本对容器进行一对一的绑定
            webgl.shaderSource(vsshader, vertextString)
            webgl.shaderSource(fsshader, fragmentString)

            //编译打包容器、
            webgl.compileShader(vsshader)
            webgl.compileShader(fsshader)

            //创建项目容器
            let program = webgl.createProgram();
            //项目容器与shader绑定
            webgl.attachShader(program, vsshader)
            webgl.attachShader(program, fsshader)

            //连接与使用这个项目
            webgl.linkProgram(program)
            webgl.useProgram(program)

            //最后把这个构建的项目赋值给全局变量webgl的program属性里
            webgl.program = program
        }
        //数据缓冲区初始化函数 :数据传到shader
        function initBuffer() {
            //获取shader变量
            let aPosition = webgl.getAttribLocation(webgl.program, "a_position")
            let arr = [
                0, 0.5, 0,
                0.17, 0.17, 0,
                0.5, 0, 0,
                0.17, -0.17, 0,

                0.33, -0.67, 0,
                0, -0.33, 0,

                -0.33, -0.67, 0,
                -0.17, -0.17, 0,

                -0.5, 0, 0,
                -0.17, 0.17, 0,
            ]
            let pointPosition = new Float32Array(arr)//x100,y100,z0 1.0矩阵分量
            let lineBuffer = webgl.createBuffer()
            //绑定类型为数组的缓冲区
            webgl.bindBuffer(webgl.ARRAY_BUFFER, lineBuffer)
            //缓冲区类型 赋值内容 数据类型:静态绘制
            webgl.bufferData(webgl.ARRAY_BUFFER, pointPosition, webgl.STATIC_DRAW)
            //启用
            webgl.enableVertexAttribArray(aPosition)
            //把准备的 "所有" 数据赋值给shader里面
            //shader变量  一个点需要绘制几个数:xyz 数的类型 是否转置 字节数 从第几个偏移算起
            webgl.vertexAttribPointer(aPosition, 3, webgl.FLOAT, false, 0, 0)

            //获取投影坐标系
            let uniformProj = webgl.getUniformLocation(webgl.program, "proj")
            webgl.uniformMatrix4fv(uniformProj, false, projMat4)
        }
        //webgl的绘制函数
        function draw() {
            webgl.clearColor(0.0, 0.0, 0.0, 1.0);
            webgl.clear(webgl.COLOR_BUFFER_BIT | webgl.DEPTH_BUFFER_BIT);
            webgl.drawArrays(webgl.LINE_LOOP, 0, 10)
        }
    </script>
</head>

<body onload="init()">
    <canvas id="webglCanvas" width="1024" height="700"></canvas>
</body>

</html>
结果演示

索引缓冲区-ELEMENT_ARRAY_BUFFER

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

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../glMatrix-0.9.6.min.js"></script>
    <script>
        /**
         * gl.LINES 两点一线(必须成对出现的点)
         * gl.LINE_STRIP 所有的点连成的线
         * gl.LINE_LOOP 所有点闭合连成的线(首尾相连)
         **/
        let vertextString = `
        attribute vec4 a_position;
        uniform mat4 proj;
        void main(void){
            gl_Position=proj * a_position;
            gl_PointSize=60.0;
        }
        `

        //----片元着色器
        let fragmentString = `
        void main(void){
            gl_FragColor = vec4(0,0,1.0,1.0);
        }
        `
        let webgl;
        let projMat4 = mat4.create()
        //入口函数
        function init() {
            initWebgl();
            initShader();
            initBuffer();
            draw();
        }
        //webgl初始化函数
        function initWebgl() {
            //获取webgl容器
            let webglDiv = document.getElementById('webglCanvas')
            //获取webgl对象
            webgl = webglDiv.getContext("webgl")
            //设置webgl的视觉区域
            webgl.viewport(0, 0, webglDiv.clientWidth, webglDiv.clientHeight)//00原点、以及xy轴的距离
            //通过插件设置webgl的投影坐标系
            mat4.ortho(0, webglDiv.clientWidth, webglDiv.clientHeight, 0, -1.0, 1.0, projMat4)//-1,1是z轴,projMat4是自定义的投影矩阵变量
        }
        //shader初始化函数,字符串转代码
        function initShader() {
            //创建一个顶点shader容器
            let vsshader = webgl.createShader(webgl.VERTEX_SHADER);
            // 创建一个片元shader容器
            let fsshader = webgl.createShader(webgl.FRAGMENT_SHADER);

            // 将各个文本对容器进行一对一的绑定
            webgl.shaderSource(vsshader, vertextString)
            webgl.shaderSource(fsshader, fragmentString)

            //编译打包容器、
            webgl.compileShader(vsshader)
            webgl.compileShader(fsshader)

            //创建项目容器
            let program = webgl.createProgram();
            //项目容器与shader绑定
            webgl.attachShader(program, vsshader)
            webgl.attachShader(program, fsshader)

            //连接与使用这个项目
            webgl.linkProgram(program)
            webgl.useProgram(program)

            //最后把这个构建的项目赋值给全局变量webgl的program属性里
            webgl.program = program
        }
        //数据缓冲区初始化函数 :数据传到shader
        function initBuffer() {
            //获取shader变量
            let aPosition = webgl.getAttribLocation(webgl.program, "a_position")
            //索引数组
            //共用顶点100.0, 100.0, 0,
            //适合无符号类型
            let arrindex=[
                0,1,2,
                0,3,4,
            ]
            let arr = [
                100.0, 100.0, 0,
                200.0, 200.0, 0,
                300.0,200.0,0,

                400.0,600.0,0,
                500.0,700.0,0
            ]
            let pointPosition = new Float32Array(arr)//x100,y100,z0 1.0矩阵分量
            //顶点数据的配置
            let lineBuffer = webgl.createBuffer()
            //绑定类型为数组的缓冲区
            webgl.bindBuffer(webgl.ARRAY_BUFFER, lineBuffer)
            //缓冲区类型 赋值内容 数据类型:静态绘制
            webgl.bufferData(webgl.ARRAY_BUFFER, pointPosition, webgl.STATIC_DRAW)
            //启用
            webgl.enableVertexAttribArray(aPosition)
            //把准备的 "所有" 数据赋值给shader里面
            //shader变量  一个点需要绘制几个数:xyz 数的类型 是否转置 字节数 从第几个偏移算起
            webgl.vertexAttribPointer(aPosition, 3, webgl.FLOAT, false, 3*4, 0)

            //顶点索引的配置
            //创建索引数组
            let indexArr=new Uint16Array(arrindex)
            //创建索引缓冲区
            let indexBuffer=webgl.createBuffer()
            webgl.bindBuffer(webgl.ELEMENT_ARRAY_BUFFER,indexBuffer)
            webgl.bufferData(webgl.ELEMENT_ARRAY_BUFFER,indexArr,webgl.STATIC_DRAW)
            
            //获取投影坐标系
            let uniformProj = webgl.getUniformLocation(webgl.program, "proj")
            webgl.uniformMatrix4fv(uniformProj, false, projMat4)
        }
        //webgl的绘制函数
        function draw() {
            webgl.clearColor(0.0, 0.0, 0.0, 1.0);
            webgl.clear(webgl.COLOR_BUFFER_BIT | webgl.DEPTH_BUFFER_BIT);

            //绘制什么 绘制几个点:arrindex.length 无符号的short类型 开始索引
            webgl.drawElements(webgl.TRIANGLES, 6,webgl.UNSIGNED_SHORT, 0)
        }
    </script>
</head>

<body onload="init()">
    <canvas id="webglCanvas" width="1024" height="700"></canvas>
</body>

</html>
结果演示

图形动态变化

矩阵

平移

旋转

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script>
        let webgl;
        //angle旋转角度
        let vsString=`
        attribute vec3 a_position;
        uniform float angle;//旋转
        uniform float move;//平移
        void main(){
            //gl_Position=move * a_position 平移矩阵*原始坐标
            gl_Position=vec4(a_position.x*cos(angle)-a_position.y*sin(angle),a_position.x*sin(angle)+a_position.y*cos(angle),0,1.0);
        }
        `
        let fsString=`
        void main(){
            gl_FragColor=vec4(0.0,0.0,1.0,1.0);
        }
        `
        function init(){
            initWebgl();
            initShader();
            initBuffer();
            draw()
        }
        function initWebgl(){
            let webglDiv=document.getElementById('webgl_canvas')
            webgl = webglDiv.getContext("webgl")
            webgl.viewport(0,0,webglDiv.clientWidth,webglDiv.clientHeight)
        }
        function initShader(){
            let shaderVS=webgl.createShader(webgl.VERTEX_SHADER)
            let shaderFS=webgl.createShader(webgl.FRAGMENT_SHADER)
            webgl.shaderSource(shaderVS,vsString)
            webgl.shaderSource(shaderFS,fsString)

            webgl.compileShader(shaderVS)
            webgl.compileShader(shaderFS)

            if (!webgl.getShaderParameter(shaderVS, webgl.COMPILE_STATUS)) {
                var err = webgl.getShaderInfoLog(shaderVS);
                alert(err);
                return;
            }
            if (!webgl.getShaderParameter(shaderFS, webgl.COMPILE_STATUS)) {
                var err = webgl.getShaderInfoLog(shaderFS);
                alert(err);
                return;
            }

            let program=webgl.createProgram()
            webgl.attachShader(program,shaderVS)
            webgl.attachShader(program,shaderFS)

            webgl.linkProgram(program)
            webgl.useProgram(program)
            webgl.program=program
        }
        function initBuffer(){
            let arr=[
                0.1,0.4,0,
                0.1,0.5,0,
                0.2,0.4,0,
            ]
            let float=new Float32Array(arr)
            let buffer=webgl.createBuffer()
            webgl.bindBuffer(webgl.ARRAY_BUFFER,buffer)
            webgl.bufferData(webgl.ARRAY_BUFFER,float,webgl.STATIC_DRAW)

            let aPosition=webgl.getAttribLocation(webgl.program,"a_position")
            webgl.vertexAttribPointer(aPosition,3,webgl.FLOAT,false,0,0)
            webgl.enableVertexAttribArray(aPosition)

            //获取uAngle变量
            let uAngle=webgl.getUniformLocation(webgl.program,"angle")
            // 旋转90度并求出弧度值
            let angle1= 90*Math.PI/180
            //给这个变量赋值  uniform1f:赋值一个float数
            webgl.uniform1f(uAngle,angle1)
        }
        function draw(){
            webgl.clearColor(1.0,0.0,0.0,0.5)
            webgl.clear(webgl.COLOR_BUFFER_BIT)
            webgl.drawArrays(webgl.TRIANGLES,0,3)
        }
    </script>
</head>
<body onload="init()">
    <canvas id="webgl_canvas" width="500" height="500"></canvas>
</body>
</html>
结果演示

缩放

控制移动

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script>
        let webgl;
        //angle旋转角度
        let vsString=`
        attribute vec3 a_position;
        uniform float anglex;
        uniform float angley;
        void main(){
            gl_Position=vec4(a_position.x+anglex,a_position.y+angley,0,1.0);
        }
        `
        let fsString=`
        void main(){
            gl_FragColor=vec4(0.0,0.0,1.0,1.0);
        }
        `
        function init(){
            initWebgl();
            initShader();
            initBuffer();
            draw()
            initEvent()
        }
        function initWebgl(){
            let webglDiv=document.getElementById('webgl_canvas')
            webgl = webglDiv.getContext("webgl")
            webgl.viewport(0,0,webglDiv.clientWidth,webglDiv.clientHeight)
        }
        function initShader(){
            let shaderVS=webgl.createShader(webgl.VERTEX_SHADER)
            let shaderFS=webgl.createShader(webgl.FRAGMENT_SHADER)
            webgl.shaderSource(shaderVS,vsString)
            webgl.shaderSource(shaderFS,fsString)

            webgl.compileShader(shaderVS)
            webgl.compileShader(shaderFS)

            if (!webgl.getShaderParameter(shaderVS, webgl.COMPILE_STATUS)) {
                var err = webgl.getShaderInfoLog(shaderVS);
                alert(err);
                return;
            }
            if (!webgl.getShaderParameter(shaderFS, webgl.COMPILE_STATUS)) {
                var err = webgl.getShaderInfoLog(shaderFS);
                alert(err);
                return;
            }

            let program=webgl.createProgram()
            webgl.attachShader(program,shaderVS)
            webgl.attachShader(program,shaderFS)

            webgl.linkProgram(program)
            webgl.useProgram(program)
            webgl.program=program
        }
        let countx=0
        let county=0
        function initEvent(){
            document.onkeydown=handleKeyDown
        }
        function handleKeyDown(event){
            switch (String.fromCharCode(event.keyCode)){
                case 'W':
                    county+=0.01
                    break
                case 'S':
                    county-=0.01
                    break
                case 'A':
                    countx-=0.01
                    break
                case 'D':
                    countx+=0.01
                    break
            }
        }
        function initBuffer(){
            let arr=[
                0.1,0.4,0,
                0.1,0.5,0,
                0.2,0.4,0,
            ]
            let float=new Float32Array(arr)
            let buffer=webgl.createBuffer()
            webgl.bindBuffer(webgl.ARRAY_BUFFER,buffer)
            webgl.bufferData(webgl.ARRAY_BUFFER,float,webgl.STATIC_DRAW)

            let aPosition=webgl.getAttribLocation(webgl.program,"a_position")
            webgl.vertexAttribPointer(aPosition,3,webgl.FLOAT,false,0,0)
            webgl.enableVertexAttribArray(aPosition)

            //获取uAngle变量
            let xAngle=webgl.getUniformLocation(webgl.program,"anglex")
            let yAngle=webgl.getUniformLocation(webgl.program,"angley")
            //给这个变量赋值  uniform1f:赋值一个float数
            webgl.uniform1f(xAngle,countx)
            webgl.uniform1f(yAngle,county )
        }
        function onLoad(){
            init()
            window.requestAnimationFrame(onLoad)
        }
        function draw(){
            webgl.clearColor(1.0,0.0,0.0,0.5)
            webgl.clear(webgl.COLOR_BUFFER_BIT)
            webgl.drawArrays(webgl.TRIANGLES,0,3)
        }
    </script>
</head>
<body onload="onLoad()">
    <canvas id="webgl_canvas" width="500" height="500"></canvas>
</body>
</html>
结果演示

纹理

多重纹理(重点)

多重纹理映射原理图

坐标系对应关系

多重纹理案例

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

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>绘制点精灵</title>
    <script src="../glMatrix-0.9.6.min.js"></script>
    <script>
        let vertexString = `
        attribute vec4 a_position;
        uniform     mat4    proj;
        attribute vec2 outUV;
        varying vec2 inUV;
        void main(void){
            gl_Position = proj *  a_position;
            inUV = outUV;
        }
        `;
        let fragmentString = `
        precision mediump float;
        uniform sampler2D texture;
        uniform sampler2D texture1;
        uniform float anim;
        varying vec2 inUV;
        void main(void){
          vec4 color1 =texture2D(texture,inUV);
          vec4 color2 =texture2D(texture1,vec2(inUV.x+anim,inUV.y));
          gl_FragColor = color1+color2;
        }
        `;
        var projMat4 = mat4.create();
        var webgl;
        let uniformTexture = 0;
        let uniformTexture1 = 0;
        let uniformAnim = 0
        let count = 0
        let texture0
        let texture1
        function webglStart() {
            init()
            tick()
        }
        function tick() {
            requestAnimationFrame(tick)
            draw()
        }
        function init() {
            initWebgl();
            initShader();
            initBuffer();
        }
        function initWebgl() {
            let webglDiv = document.getElementById('myCanvas');
            webgl = webglDiv.getContext("webgl");
            webgl.viewport(0, 0, webglDiv.clientWidth, webglDiv.clientHeight);
            mat4.ortho(0, webglDiv.clientWidth, webglDiv.clientHeight, 0, -1.0, 1.0, projMat4)
        }
        function initShader() {

            let vsshader = webgl.createShader(webgl.VERTEX_SHADER);
            let fsshader = webgl.createShader(webgl.FRAGMENT_SHADER);

            webgl.shaderSource(vsshader, vertexString);
            webgl.shaderSource(fsshader, fragmentString);

            webgl.compileShader(vsshader);
            webgl.compileShader(fsshader);
            if (!webgl.getShaderParameter(vsshader, webgl.COMPILE_STATUS)) {
                var err = webgl.getShaderInfoLog(vsshader);
                alert(err);
                return;
            }
            if (!webgl.getShaderParameter(fsshader, webgl.COMPILE_STATUS)) {
                var err = webgl.getShaderInfoLog(fsshader);
                alert(err);
                return;
            }
            let program = webgl.createProgram();
            webgl.attachShader(program, vsshader);
            webgl.attachShader(program, fsshader)

            webgl.linkProgram(program);
            webgl.useProgram(program);

            webgl.program = program
        }
        function initBuffer() {
            // 坐标系  ,  纹理坐标系
            let arr = [
                0, 0, 0, 1, 0, 0,
                0, 500, 0, 1, 0, 1,
                500, 0, 0, 1, 1, 0,

                500, 0, 0, 1, 1, 0,
                0, 500, 0, 1, 0, 1,
                500, 500, 0, 1, 1, 1,
            ]
            let index = [
                0, 1, 2,
                2, 0, 3
            ]
            let pointPosition = new Float32Array(arr);
            let aPsotion = 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(aPsotion);
            webgl.vertexAttribPointer(aPsotion, 4, webgl.FLOAT, false, 6 * 4, 0);

            let uniformProj = webgl.getUniformLocation(webgl.program, "proj");
            webgl.uniformMatrix4fv(uniformProj, false, projMat4);

            //获取纹理参数:纹理坐标系赋值给片元坐标系
            let attribOutUV = webgl.getAttribLocation(webgl.program, "outUV");
            webgl.enableVertexAttribArray(attribOutUV)
            webgl.vertexAttribPointer(attribOutUV, 2, webgl.FLOAT, false, 6 * 4, 4 * 4)

            // 通过数组类型Unint8Array可知是8位无符号整数型UNSIGNED_BYTE
            let indexArr = new Uint8Array(index)
            //创建纹理
            let indexBuffer = webgl.createBuffer()
            webgl.bindBuffer(webgl.ELEMENT_ARRAY_BUFFER, indexBuffer)
            webgl.bufferData(webgl.ELEMENT_ARRAY_BUFFER, indexArr, webgl.STATIC_DRAW)

            //获取shader纹理变量
            uniformTexture = webgl.getUniformLocation(webgl.program, "texture")
            uniformTexture1 = webgl.getUniformLocation(webgl.program, "texture1")
            texture1 = initTexture("fog.png")
            texture0 = initTexture("山水.png")
        }
        function handleLoadedTexture(texture) {
            // 设置纹理参数/细节
            webgl.bindTexture(webgl.TEXTURE_2D, texture);
            webgl.texImage2D(webgl.TEXTURE_2D, 0, webgl.RGBA, webgl.RGBA, webgl.UNSIGNED_BYTE, texture.image);
            /**
             * TEXTURE_2D 二维纹理
             * TEXTURE_MAG_FILTER 放大
             * */
            webgl.texParameteri(webgl.TEXTURE_2D, webgl.TEXTURE_MAG_FILTER, webgl.NEAREST);
            webgl.texParameteri(webgl.TEXTURE_2D, webgl.TEXTURE_MIN_FILTER, webgl.NEAREST);
            webgl.texParameteri(webgl.TEXTURE_2D, webgl.TEXTURE_WRAP_S, webgl.REPEAT);
            webgl.texParameteri(webgl.TEXTURE_2D, webgl.TEXTURE_WRAP_T, webgl.REPEAT);
        }
        function initTexture(imageFile, num) {
            //创建一个纹理
            let textureHandle = webgl.createTexture();
            textureHandle.image = new Image();
            textureHandle.image.src = imageFile;
            textureHandle.image.onload = function () {
                handleLoadedTexture(textureHandle, num)
            }
            return textureHandle
        }
        function draw() {
            webgl.clearColor(1.0, 0.0, 0.0, 1.0);
            webgl.clear(webgl.COLOR_BUFFER_BIT | webgl.DEPTH_BUFFER_BIT);
            webgl.enable(webgl.DEPTH_TEST);

            //纹理变动
            //获取动态变量anim
            uniformAnim = webgl.getUniformLocation(webgl.program, "anim")
            count += 0.01
            //把count赋值给这个动态变量
            webgl.uniform1i(uniformAnim, count)

            //激活第0层纹理
            webgl.activeTexture(webgl.TEXTURE0)
            //绑定纹理
            webgl.bindTexture(webgl.TEXTURE_2D, texture0)
            //赋值给第0层
            webgl.uniform1i(uniformTexture, 0)

            webgl.activeTexture(webgl.TEXTURE1)
            webgl.bindTexture(webgl.TEXTURE_2D, texture1)
            webgl.uniform1i(uniformTexture1, 1)

            webgl.drawElements(webgl.TRIANGLES, 6, webgl.UNSIGEND_BYTE, 0)
        }
        window.requestAnimationFrame = (function () {
            return window.requestAnimationFrame ||
                window.webkitRequestAnimationFrame ||
                window.mozRequestAnimationFrame ||
                window.oRequestAnimationFrame ||
                function (callback, element) {
                    window.setTimeout(callback, 1000 / 60)
                };
        })()
    </script>
</head>

<body onload="webglStart()">
    <canvas id='myCanvas' width="1024" height='768'></canvas>
</body>

</html>

单纹理(点精灵)

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

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>绘制点精灵</title>
    <script src="../glMatrix-0.9.6.min.js"></script>
    <script>
        let vertexString = `
        attribute vec4 a_position;
        uniform     mat4    proj;
        void main(void){
            gl_Position =proj *  a_position;
            gl_PointSize=16.0;
        }
        `;
        //color.a < 0.1 如果接近透明的部分,就不进行绘制了
        let fragmentString = `
        precision mediump float;
        uniform sampler2D texture;
        void main(void){
          vec4 color =texture2D(texture,gl_PointCoord);
          if(color.a < 0.1)
                discard;
          gl_FragColor = color;
        }
        `;
        var projMat4 = mat4.create();
        var webgl;
        var uniformTexture = 0;
        var textureHandle;
        function init() {
            initWebgl();
            initShader();
            initBuffer();

        }
        function initWebgl() {
            let webglDiv = document.getElementById('myCanvas');
            webgl = webglDiv.getContext("webgl");
            webgl.viewport(0, 0, webglDiv.clientWidth, webglDiv.clientHeight);
            mat4.ortho(0, webglDiv.clientWidth, webglDiv.clientHeight, 0, -1.0, 1.0, projMat4)
        }
        function initShader() {

            let vsshader = webgl.createShader(webgl.VERTEX_SHADER);
            let fsshader = webgl.createShader(webgl.FRAGMENT_SHADER);

            webgl.shaderSource(vsshader, vertexString);
            webgl.shaderSource(fsshader, fragmentString);

            webgl.compileShader(vsshader);
            webgl.compileShader(fsshader);
            if (!webgl.getShaderParameter(vsshader, webgl.COMPILE_STATUS)) {
                var err = webgl.getShaderInfoLog(vsshader);
                alert(err);
                return;
            }
            if (!webgl.getShaderParameter(fsshader, webgl.COMPILE_STATUS)) {
                var err = webgl.getShaderInfoLog(fsshader);
                alert(err);
                return;
            }
            let program = webgl.createProgram();
            webgl.attachShader(program, vsshader);
            webgl.attachShader(program, fsshader)

            webgl.linkProgram(program);
            webgl.useProgram(program);

            webgl.program = program
        }
        function initBuffer() {
            let pointPosition = new Float32Array([100.0, 100.0, 0.0, 1.0, 100.0, 200.0, 0.0, 1.0, 200.0, 200.0, 0.0, 1.0]);
            let aPsotion = 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(aPsotion);
            webgl.vertexAttribPointer(aPsotion,4, webgl.FLOAT,false,16,0 );
            let uniformProj = webgl.getUniformLocation(webgl.program, "proj");
            webgl.uniformMatrix4fv(uniformProj, false, projMat4);

            //获取纹理参数
            uniformTexture = webgl.getUniformLocation(webgl.program, "texture");

            //开启混合
            webgl.enable(webgl.BLEND);
            //使用混合
            webgl.blendFunc(webgl.SRC_ALPHA, webgl.ONE_MINUS_SRC_ALPHA);

            //加载本地纹理图片
            initTexture("point64.png");
        }
        function handleLoadedTexture(texture) {
            // 设置纹理参数/细节
            webgl.bindTexture(webgl.TEXTURE_2D, texture);
            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.NEAREST);
            webgl.texParameteri(webgl.TEXTURE_2D, webgl.TEXTURE_MIN_FILTER, webgl.NEAREST);
            webgl.texParameteri(webgl.TEXTURE_2D, webgl.TEXTURE_WRAP_S, webgl.REPEAT);
            webgl.texParameteri(webgl.TEXTURE_2D, webgl.TEXTURE_WRAP_T, webgl.REPEAT);
            //因为异步原因所以要加在这里
            webgl.uniform1i(uniformTexture, 0);
            draw();
            // webgl.bindTexture(webgl.TEXTURE_2D, null);
        }
        function initTexture(imageFile) {
            //创建一个纹理
            textureHandle = webgl.createTexture();
            textureHandle.image = new Image();
            textureHandle.image.src = imageFile;
            textureHandle.image.onload = function () {
                handleLoadedTexture(textureHandle)
            }

        }
        function draw() {
            webgl.clearColor(1.0, 0.0, 0.0, 1.0);
            webgl.clear(webgl.COLOR_BUFFER_BIT | webgl.DEPTH_BUFFER_BIT);
            webgl.enable(webgl.DEPTH_TEST);
            webgl.drawArrays(webgl.POINTS, 0, 3);
        }
    </script>
</head>

<body onload="init()">
    <canvas id='myCanvas' width="1024" height='768'></canvas>
</body>

</html>
结果演示

动态变换与动画

矩阵

矩阵转换库glmatrix

glmatrix官网

库的使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../glMatrix-0.9.6.min.js"></script>
    <script>
        let webgl;
        //angle旋转角度
        let vsString=`
        attribute vec4 a_position;
        uniform mat4 u_formMatrix;
        void main(){
            gl_Position=u_formMatrix * a_position; //平移矩阵*原始坐标
        }
        `
        let fsString=`
        void main(){
            gl_FragColor=vec4(0.0,0.0,1.0,1.0);
        }
        `
        function init(){
            initWebgl();
            initShader();
            initBuffer();
            draw()
        }
        function initWebgl(){
            let webglDiv=document.getElementById('webgl_canvas')
            webgl = webglDiv.getContext("webgl")
            webgl.viewport(0,0,webglDiv.clientWidth,webglDiv.clientHeight)
        }
        function initShader(){
            let shaderVS=webgl.createShader(webgl.VERTEX_SHADER)
            let shaderFS=webgl.createShader(webgl.FRAGMENT_SHADER)
            webgl.shaderSource(shaderVS,vsString)
            webgl.shaderSource(shaderFS,fsString)

            webgl.compileShader(shaderVS)
            webgl.compileShader(shaderFS)

            if (!webgl.getShaderParameter(shaderVS, webgl.COMPILE_STATUS)) {
                var err = webgl.getShaderInfoLog(shaderVS);
                alert(err);
                return;
            }
            if (!webgl.getShaderParameter(shaderFS, webgl.COMPILE_STATUS)) {
                var err = webgl.getShaderInfoLog(shaderFS);
                alert(err);
                return;
            }

            let program=webgl.createProgram()
            webgl.attachShader(program,shaderVS)
            webgl.attachShader(program,shaderFS)

            webgl.linkProgram(program)
            webgl.useProgram(program)
            webgl.program=program
        }
        function initBuffer(){
            /**
             * 平移
             **/
            // 创建4*4矩阵
            // let modelView=mat4.create()
            // //单元化(初始化)
            // mat4.identity(modelView)
            // //开始转化: 原始矩阵 , 进行平移变化:即向上/y移动0.2
            // //转化后重新赋值给modelView
            // mat4.translate(modelView,[0,0.2,0])
            
            /**
             * 旋转与缩放
             * */
            let modelView2=mat4.create()
            mat4.identity(modelView2)
            mat4.scale(modelView2,[1,2,1])//缩放
            let angle=2*Math.PI / 6 * 0.5;
            mat4.rotate(modelView2,angle,[0,0,1])

            let arr=[
                0,0,0,1,
                0,0.05,0,1,
                0.5,0,0,1,

                0.5,0,0,1,
                0,0.05,0,1,
                0.5,0.05,0,1
            ]
            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 uniformMatrix = webgl.getUniformLocation(webgl.program,"u_formMatrix")
            // 再把转换后的modelView值传给shader:uniformMatrix
            webgl.uniformMatrix4fv(uniformMatrix,false,modelView2)
        }
        function draw(){
            webgl.clearColor(1.0,0.0,0.0,0.5)
            webgl.clear(webgl.COLOR_BUFFER_BIT)
            webgl.drawArrays(webgl.TRIANGLES,0,3)
        }
    </script>
</head>
<body onload="init()">
    <canvas id="webgl_canvas" width="500" height="500"></canvas>
</body>
</html>
结果演示

时钟案例

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

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../glMatrix-0.9.6.min.js"></script>
    <script>
        let webgl;
        //angle旋转角度
        let vsString = `
        attribute vec4 a_position;
        uniform mat4 u_formMatrix;
        void main(){
            gl_Position=u_formMatrix * a_position; //平移矩阵*原始坐标
        }
        `
        let fsString = `
        void main(){
            gl_FragColor=vec4(0.0,0.0,1.0,1.0);
        }
        `
        let count=0
        function webglStart() {
            init()
            tick()
        }
        function tick(){
            window.setTimeout(tick,1000)
            initBuffer1()
            initBuffer2()
            initBuffer3()
            count+=1
        }
        function init() {
            initWebgl();
            initShader();
        }
        function initWebgl() {
            let webglDiv = document.getElementById('webgl_canvas')
            webgl = webglDiv.getContext("webgl")
            webgl.viewport(0, 0, webglDiv.clientWidth, webglDiv.clientHeight)
        }
        function initShader() {
            let shaderVS = webgl.createShader(webgl.VERTEX_SHADER)
            let shaderFS = webgl.createShader(webgl.FRAGMENT_SHADER)
            webgl.shaderSource(shaderVS, vsString)
            webgl.shaderSource(shaderFS, fsString)

            webgl.compileShader(shaderVS)
            webgl.compileShader(shaderFS)

            if (!webgl.getShaderParameter(shaderVS, webgl.COMPILE_STATUS)) {
                var err = webgl.getShaderInfoLog(shaderVS);
                alert(err);
                return;
            }
            if (!webgl.getShaderParameter(shaderFS, webgl.COMPILE_STATUS)) {
                var err = webgl.getShaderInfoLog(shaderFS);
                alert(err);
                return;
            }

            let program = webgl.createProgram()
            webgl.attachShader(program, shaderVS)
            webgl.attachShader(program, shaderFS)

            webgl.linkProgram(program)
            webgl.useProgram(program)
            webgl.program = program
        }
        function initBuffer1(){
            let modelView=mat4.create()
            mat4.identity(modelView)
            mat4.scale(modelView,[1,1,1])
            //一分钟转0.5度 -> 一秒钟转0.5/60度
            //Math.PI/180=1弧度
            //(Math.PI/180)*(0.5/60)*count
            let angle= -Math.PI/1800 * count *5/60
            mat4.rotate(modelView,angle,[0,0,1])
            let arr = [
                0, 0, 0, 1,
                0, 0.05, 0, 1,
                0.5, 0, 0, 1,

                0.5, 0, 0, 1,
                0, 0.05, 0, 1,
                0.5, 0.05, 0, 1
            ]
            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 uniformMatrix = webgl.getUniformLocation(webgl.program, "u_formMatrix")
            // 再把转换后的modelView值传给shader:uniformMatrix
            webgl.uniformMatrix4fv(uniformMatrix, false, modelView)

            webgl.clearColor(1.0, 0.0, 0.0, 0.5)
            webgl.clear(webgl.COLOR_BUFFER_BIT | webgl.DEPTH_BUFFER_BIT)
            webgl.enable(webgl.DEPTH_TEST)
            webgl.drawArrays(webgl.TRIANGLES, 0, 6)
        }
        function initBuffer2(){
            let modelView=mat4.create()
            mat4.identity(modelView)
            mat4.scale(modelView,[1,1,1])
            let angle= -Math.PI/1800 * count
            mat4.rotate(modelView,angle,[0,0,1])
            let arr = [
                0, 0, 0, 1,
                0, 0.05, 0, 1,
                0.6, 0, 0, 1,

                0.6, 0, 0, 1,
                0, 0.05, 0, 1,
                0.5, 0.05, 0, 1
            ]
            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 uniformMatrix = webgl.getUniformLocation(webgl.program, "u_formMatrix")
            // 再把转换后的modelView值传给shader:uniformMatrix
            webgl.uniformMatrix4fv(uniformMatrix, false, modelView)

            webgl.drawArrays(webgl.TRIANGLES, 0, 6)
        }
        function initBuffer3(){
            let modelView=mat4.create()
            mat4.identity(modelView)
            mat4.scale(modelView,[1,1,1])
            let angle= -Math.PI/30 * count
            mat4.rotate(modelView,angle,[0,0,1])
            let arr = [
                0, 0, 0, 1,
                0, 0.05, 0, 1,
                0.8, 0, 0, 1,

                0.8, 0, 0, 1,
                0, 0.05, 0, 1,
                0.5, 0.05, 0, 1
            ]
            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 uniformMatrix = webgl.getUniformLocation(webgl.program, "u_formMatrix")
            // 再把转换后的modelView值传给shader:uniformMatrix
            webgl.uniformMatrix4fv(uniformMatrix, false, modelView)

            webgl.drawArrays(webgl.TRIANGLES, 0, 6)
        }
    
    </script>
</head>

<body onload="webglStart()">
    <canvas id="webgl_canvas" width="500" height="500"></canvas>
</body>

</html>
结果演示

文末

webGL文档

webGL文档

文章来源

该文章所有内容全部是我在B站冰鉴韵老师的视频下总结的。


渣渣龙, 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:webGL-初识[保姆级文章、每节都有全部代码及在线演示]
喜欢 (1)

您必须 登录 才能发表评论!