webgl笔记(webgl编程指南pdf)
webgl
webgl 需要用到 canvas
MDN 链接
canvas
画布
使用方法,新建 canvas 标签
js 获取,然后使用 getContext 获取上下文
使用上下文对象上的 api 来进行绘制
getContext
详情
获取上下文
两个参数(contextType,contextAttributes)
contextType 是 string 类型
'2d'
创建 2d 上下文对象
'webgl'
创建 webgl 上下文对象(三维)
'bitmaprenderer'
创建放置图片的上下文contextAttributes 是可选参数,为 object 类型
返回值:正常情况返回上下文对象,
失败返回null
特点:标签内部书写的内容,是在浏览器不兼容 canvas 的时候才显示
坐标系:canvas 坐标系原点在左上角
同一个作用域中只能有一个类型的上下文,否则会报错
let canvas = document.querySelector("#canvas"); let ctx = canvas.getContext("2d"); 复制代码
2d 上下文
常用属性
fillStyle
设置颜色,
值是 string,设置后存储在缓存区
常用方法
fillRect
设置矩形,颜色是最近的一个 fillStyle
四个值,距左距离,距上距离,宽,高,类型都是 number
drawArrays
绘制图形 ,链接
mode 指定绘制的方式,接收常量符号,如下:
first
count
gl.POINTS 绘制一系列点
gl.LINES 绘制一系列单独线段。每两个点作为端点,线段之间不连接。
gl.LINE_STRIP 绘制一个线条。即,绘制一系列线段,上一点连接下一点。
gl.LINE_LOOP 绘制一个线圈。即,绘制一系列线段,上一点连接下一点,并且最后一点与第一个点相连。
gl.TRIANGLES 绘制一系列三角形。每三个点作为顶点。
gl.TRIANGLE_STRIP 绘制一个三角带
gl.TRIANGLE_FAN 绘制一个三角扇
注意:如果 mode 不是这几个值会抛出 gl.INVALID_ENUM 异常。
类型为整数,指定从哪个点开始绘制。
注意:如果这个值为负数会抛出 gl.INVALID_VALUE 异常
整数型,指定绘制需要用到多少个顶点
没有返回值
三个参数(mode, first, count)
gl 上下文(3d)
常用属性
常用方法
clearColor
设置清除颜色
四个值:都是 float 类型,rgba
clear
清除画布
gl.COLOR_BUFFER_BIT 指定深度缓冲区
gl.DEPTH_BUFFER_BIT 指定颜色缓存
gl.STENCIL_BUFFER_BIT 指定模板缓冲区
一个参数,(gl 是 gl 的上下文,可以使用其他变量)
返回值:无
如果前面没有设置清除颜色,默认为白色
着色器
CDN 链接
分为两种,定点着色器和片元着色器
共同点
:
都要先存储为字符串,然后调用方法使用
字符串内容都要有 main 函数,而且也不要给 main 函数自定义参数,且 main 函数前的 void 表示他不可以有返回值
且内部函数内部需要放置一些规范内容,在下面分析
定点着色器
描述顶点位置的,顶点可以理解为是每个顶端
顶点着色器需要对顶点坐标进行转换,通过
gl_Position
保存处理过的的顶点(表示顶点位置),类型为vec4
,这个变量必须要写gl_PointSize 变量为可选变量,类型为 float,表示点的尺寸(像素为单位),如果不写的话默认为 1.0
片元着色器(片段着色器)
在顶点着色器处理完成后,绘制颜色和纹理
片元就是显示在屏幕上的像素,可以理解为这个片元包含了这个像素的位置,颜色以及其他信息
将点的颜色处理后复制给
gl_FragColor
变量,也是它控制这个像素在显示器上的最终展示颜色,必须要写
,类型为 vec4,也就是 rgba 颜色
vec4 方法
参数有四个,都是浮点型
作用:返回 vec4 对象
注意(总是迷糊)
:这个方法只是处理了四个参数,而不是只能用于处理坐标,他也可以处理 rgba 颜色
齐次坐标
由 4 个参数组成,(x,y,z,w),等价于三维坐标(x/w,y/w,z/w)
因为
齐次坐标是四维
的,而他的特点是如果 w 为 1.0 的话,就等价于三维,所以经常用于表示顶点的三维坐标使用(好处:提高准确性)需要注意:0<= w <=1.0
demo(有些方法暂时没搞懂)
<!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> * { margin: 0; padding: 0; } body { width: 100vw; height: 100vh; } </style> </head> <body> <canvas id="canvas">不兼容</canvas> </body> </html> <script src="https://cdn.jsdelivr.net/npm/gl-matrix@3.0.0/gl-matrix-min.js"></script> <script> // mat4在下面会用到,因为依赖于matrix库,而matrix库更新了,将mat4放在了glMatrix上,所以我们手动将他存在全局 const mat4 = glMatrix.mat4; const canvas = document.querySelector("#canvas"); canvas.width = document.body.clientWidth; canvas.height = document.body.clientHeight; const gl = canvas.getContext("webgl"); </script> <script> //顶点着色器 const vsSource = ` attribute vec4 aVertexPosition; uniform mat4 uModelViewMatrix; uniform mat4 uProjectionMatrix; void main() { gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition; } `; //片元着色器 //vec方法接受了四个值,可以称之为齐次坐标是四维的,在三维图形系统中被大量使用,如果最后一个值为1.0那么就表示前三个参数为坐标点 const fsSource = ` void main() { gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); } `; // 创建指定类型的着色器,上传source源码并编译 function loadShader(gl, type, source) { // 创建一个着色器 const shader = gl.createShader(type); // 将源码发送到着色器 gl.shaderSource(shader, source); // 着色器获取到源代码,开始编译 gl.compileShader(shader); // 调用getShaderParameter,指定着色器shader和要检查的值gl.COMPILE_STATUS,如果返回错误,代表编译失败 if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { //编译失败,就通过getShaderInfoLog拿到日志,然后输出 alert( "An error occurred compiling the shaders: " + gl.getShaderInfoLog(shader) ); //输出后使用deleteShader删除着色器,然后返回null gl.deleteShader(shader); return null; } //编译成功,返回编译的着色器 return shader; } // 初始化着色器程序,让WebGL知道如何绘制我们的数据 function initShaderProgram(gl, vsSource, fsSource) { const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource); const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource); // 创建着色器程序 const shaderProgram = gl.createProgram(); gl.attachShader(shaderProgram, vertexShader); gl.attachShader(shaderProgram, fragmentShader); gl.linkProgram(shaderProgram); // 创建失败, alert if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { alert( "Unable to initialize the shader program: " + gl.getProgramInfoLog(shaderProgram) ); return null; } return shaderProgram; } const shaderProgram = initShaderProgram(gl, vsSource, fsSource); // const programInfo = { program: shaderProgram, attribLocations: { vertexPosition: gl.getAttribLocation(shaderProgram, "aVertexPosition"), }, uniformLocations: { projectionMatrix: gl.getUniformLocation( shaderProgram, "uProjectionMatrix" ), modelViewMatrix: gl.getUniformLocation(shaderProgram, "uModelViewMatrix"), }, }; // 在绘制图形前,创建缓冲器,存储顶点,然后返回 function initBuffers(gl) { // 通过createBuffer得到缓冲对象 const positionBuffer = gl.createBuffer(); // 通过bindBuffer绑定上下文 gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); // 创建数组,记录顶点(为浮点型) var vertices = [ 1.0, 1.0, 0.0, -1.0, 1.0, 0.0, 1.0, -1.0, 0.0, -1.0, -1.0, 0.0, ]; // 通过bufferData创建顶点对象 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); return { position: positionBuffer, }; } // 先引入工具库https://cdn.jsdelivr.net/npm/gl-matrix@3.0.0/gl-matrix-min.js // mat4报错问题参考https://github.com/mdn/sprints/issues/2817 function drawScene(gl, programInfo, buffers) { // 设置清除颜色 gl.clearColor(0.0, 0.0, 0.0, 1.0); // 清除深度缓冲区 //文章:https://blog.csdn.net/dizia/article/details/80156765 gl.clearDepth(1.0); // 启用深度测试 gl.enable(gl.DEPTH_TEST); // 遮盖深度缓冲区 gl.depthFunc(gl.LEQUAL); // 清除画布 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); // 计算角度 const fieldOfView = (45 * Math.PI) / 180; // in radians const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight; const zNear = 0.1; const zFar = 100.0; const projectionMatrix = mat4.create(); mat4.perspective(projectionMatrix, fieldOfView, aspect, zNear, zFar); const modelViewMatrix = mat4.create(); mat4.translate(modelViewMatrix, modelViewMatrix, [-0.0, 0.0, -6.0]); { const numComponents = 3; const type = gl.FLOAT; const normalize = false; const stride = 0; const offset = 0; gl.bindBuffer(gl.ARRAY_BUFFER, buffers.position); gl.vertexAttribPointer( programInfo.attribLocations.vertexPosition, numComponents, type, normalize, stride, offset ); gl.enableVertexAttribArray(programInfo.attribLocations.vertexPosition); } gl.useProgram(programInfo.program); gl.uniformMatrix4fv( programInfo.uniformLocations.projectionMatrix, false, projectionMatrix ); gl.uniformMatrix4fv( programInfo.uniformLocations.modelViewMatrix, false, modelViewMatrix ); { const offset = 0; const vertexCount = 4; gl.drawArrays(gl.TRIANGLE_STRIP, offset, vertexCount); } } drawScene(gl, programInfo, initBuffers(gl)); </script>
作者:外婆桥卖汤
链接:https://juejin.cn/post/7036706674509348900
伪原创工具 SEO网站优化 https://www.237it.com/