导读
顶点着色器、图元装配、光栅化、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
库的使用
<!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文档
文章来源
该文章所有内容全部是我在B站冰鉴韵老师的视频下总结的。