
2025-04-02 日报 Day144

今日的鸡汤
无论何时,无论遇到何事,都要保持年轻的心态。放下过往陈旧的观念,打破固有的认知经验,去探索新鲜的事物,把更多时间放在修炼自我上。
今日学习内容
1、JS 红皮书 P569-580 第十八章:动画与 Canvas 图形
今日笔记
1、WebGL: WebGL 是画布的 3D 上下文。推荐一个 WebGL 教程网站:Learn WebGL。
注意 定型数组是在 WebGL 中执行操作的重要数据结构。
2、WebGL上下文: 在完全支持的浏览器中,WebGL 2.0 上下文的名字叫”webgl2”,WebGL 1.0 上下文的名字叫”webgl1”。如果浏览器不支持 WebGL,则尝试访问 WebGL 上下文会返回 null。在使用上下文之前,应该先检测返回值是否存在:
1 | let drawing = document.getElementById("drawing"); |
3、WebGL基础: 取得 WebGL 上下文后,就可以开始 3D 绘图了。可以在调用 getContext()取得 WebGL 上下文时指定一些选项。这些选项通过一个参数对象传入,选项就是参数对象的一个或多个属性。
alpha:布尔值,表示是否为上下文创建透明通道缓冲区,默认为 true。
depth:布尔值,表示是否使用 16 位深缓冲区,默认为 true。
stencil:布尔值,表示是否使用 8 位模板缓冲区,默认为 false。
antialias:布尔值,表示是否使用默认机制执行抗锯齿操作,默认为 true。
premultipliedAlpha:布尔值,表示绘图缓冲区是否预乘透明度值,默认为 true。
preserveDrawingBuffer:布尔值,表示绘图完成后是否保留绘图缓冲区,默认为 false。
- 常量: 如果你熟悉 OpenGL,那么可能知道用于操作的各种常量。这些常量在 OpenGL 中的名字以 GL_开头。在 WebGL 中,context 对象上的常量则不包含 GL_前缀。例如,GL_COLOR_BUFFER_BIT 常量在WebGL 中要这样访问 gl.COLOR_BUFFER_BIT。WebGL 以这种方式支持大部分 OpenGL 常量。
- 方法命名: OpenGL(同时也是 WebGL)中的很多方法会包含相关的数据类型信息。接收不同类型和不同数量参数的方法,会通过方法名的后缀体现这些信息。表示参数数量的数字(1~4)在先,表示数据类型的字符串(“f”表示浮点数,“i”表示整数)在后。比如,gl.uniform4f()的意思是需要 4 个浮点数值参数,而 gl.uniform3i()表示需要 3 个整数值参数。
还有很多方法接收数组,这类方法用字母“v”(vector)来表示。因此,gl.uniform3iv()就是要接收一个包含 3 个值的数组参数。在编写 WebGL 代码时,要记住这些约定。 - 准备绘图: 准备使用 WebGL 上下文之前,通常需要先指定一种实心颜色清除
- 视口与坐标: 绘图前还要定义 WebGL 视口。默认情况下,视口使用整个
- 缓冲区: 在 JavaScript 中,顶点信息保存在定型数组中。要使用这些信息,必须先把它们转换为 WebGL 缓冲区。创建缓冲区要调用 gl.createBuffer()方法,并使用 gl.bindBuffer()方法将缓冲区绑定到WebGL 上下文。绑定之后,就可以用数据填充缓冲区了。比如:调用 gl.bindBuffer()将 buffer 设置为上下文的当前缓冲区。然后,所有缓冲区操作都在buffer 上直接执行。因此,调用 gl.bufferData()虽然没有包含对 buffer 的直接引用,但仍然是在它上面执行的。上面最后一行代码使用一个 Float32Array(通常把所有顶点信息保存在Float32Array 中)初始化了 buffer。如果想输出缓冲区内容,那么可以调用 drawElements()方法并传入 gl.ELEMENT_ARRAY_BUFFER。
1
2
3let buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0, 0.5, 1]), gl.STATIC_DRAW);
gl.bufferData()方法的最后一个参数表示如何使用缓冲区。这个参数可以是以下常量值。
gl.STATIC_DRAW:数据加载一次,可以在多次绘制中使用。
gl.STREAM_DRAW:数据加载一次,只能在几次绘制中使用。
gl.DYNAMIC_DRAW:数据可以重复修改,在多次绘制中使用。
缓冲区会一直驻留在内存中,直到页面卸载。如果不再需要缓冲区,那么最好调用 gl.deleteBuffer()方法释放其占用的内存:
gl.deleteBuffer(buffer); - 错误: 与 JavaScript 多数情况下不同的是,在 WebGL 操作中通常不会抛出错误。必须在调用可能失败的方法后,调用 gl.getError()方法。这个方法返回一个常量,表示发生的错误类型。下面列出了这些常量。
gl.NO_ERROR:上一次操作没有发生错误(0 值)。
gl.INVALID_ENUM:上一次操作没有传入 WebGL 预定义的常量。
gl.INVALID_VALUE:上一次操作需要无符号数值,但是传入了负数。
gl.INVALID_OPERATION:上一次操作在当前状态下无法完成。
gl.OUT_OF_MEMORY:上一次操作因内存不足而无法完成。
gl.CONTEXT_LOST_WEBGL:上一次操作因外部事件(如设备掉电)而丢失了 WebGL 上下文。 - 着色器: WebGL 中有两种着色器:顶点着色器和片段(或像素)着色器。顶点着色器用于把 3D 顶点转换为可以渲染的 2D 点。片段着色器用于计算绘制一个像素的正确颜色。WebGL 着色器的独特之处在于,它们不是 JavaScript 实现的,而是使用一种与 C 或 JavaScript 完全不同的语言 GLSL(OpenGL Shading Language)写的。
编写着色器: GLSL 是一种类似于 C 的语言,专门用于编写 OpenGL 着色器。因为 WebGL 是 OpenGL ES 2 的实现,所以 OpenGL 中的着色器可以直接在 WebGL 中使用。这样也可以让桌面应用更方便地移植到 Web 上。
每个着色器都有一个 main()方法,在绘制期间会重复执行。给着色器传递数据的方式有两种:attribute 和 uniform。attribute 用于将顶点传入顶点着色器,而 uniform 用于将常量值传入任何着色器。attribute 和 uniform 是在 main()函数外部定义的。在值类型关键字之后是数据类型,然后是变量名。下面是一个简单的顶点着色器的例子:创建着色器程序: 浏览器并不理解原生 GLSL 代码,因此 GLSL 代码的字符串必须经过编译并链接到一个着色器程序中。为便于使用,通常可以使用带有自定义 type 属性的1
2
3
4
5
6// OpenGL 着色器语言
// 着色器,摘自 Bartek Drozdz 的文章“Get started with WebGL—draw a square”
attribute vec2 aVertexPosition;
void main() {
gl_Position = vec4(aVertexPosition, 0.0, 1.0);
}访问人数 总访问量由 Hexo 驱动 主题 Redefine v2.6.4