- WebGL 示例
- WebGL - 绘制点
- WebGL - 绘制三角形
- WebGL - 绘制模式
- WebGL - 绘制四边形
- WebGL - 颜色
- WebGL - 平移
- WebGL - 缩放
- WebGL - 旋转
- WebGL - 立方体旋转
- WebGL - 交互式立方体
- WebGL 有用资源
- WebGL - 快速指南
- WebGL - 有用资源
- WebGL - 讨论
WebGL - 几何体
获取 WebGL 上下文后,您必须定义基本图形(您要绘制的对象)的几何体并将其存储。在 WebGL 中,我们使用 JavaScript 数组定义几何体的详细信息,例如顶点、索引、基本图形的颜色。为了将这些详细信息传递给着色器程序,我们必须创建缓冲区对象并将包含数据的 JavaScript 数组存储(附加)到相应的缓冲区中。
注意:稍后,这些缓冲区对象将与着色器程序(顶点着色器)的属性关联。
定义所需的几何体
使用顶点绘制的 2D 或 3D 模型称为网格。网格中的每个面称为多边形,多边形由 3 个或更多个顶点组成。
要在 WebGL 渲染上下文中绘制模型,您必须使用 JavaScript 数组定义顶点和索引。例如,如果我们想要创建一个位于坐标 {(5,5), (-5,5), (-5,-5)} 上的三角形,如所示,则可以为顶点创建一个数组,如下所示:
var vertices = [ 0.5,0.5, //Vertex 1 0.5,-0.5, //Vertex 2 -0.5,-0.5, //Vertex 3 ];
同样,您可以为索引创建一个数组。上述三角形的索引将为 [0, 1, 2],可以定义为:
var indices = [ 0,1,2 ]
为了更好地理解索引,请考虑更复杂的模型,如正方形。我们可以将正方形表示为两个三角形的集合。如果 (0,3,1) 和 (3,1,2) 是我们打算用来绘制正方形的两个三角形,则索引将定义为:
var indices = [0,3,1,3,1,2];
注意:
为了绘制基本图形,WebGL 提供了以下两种方法:
drawArrays() - 使用此方法时,我们使用 JavaScript 数组传递基本图形的顶点。
drawElements() - 使用此方法时,我们使用 JavaScript 数组传递基本图形的顶点和索引。
缓冲区对象
缓冲区对象是 WebGL 提供的一种机制,它指示系统中分配的内存区域。在这些缓冲区对象中,您可以存储要绘制的模型的数据,对应于顶点、索引、颜色等。
使用这些缓冲区对象,您可以通过其属性变量之一将多个数据传递给着色器程序(顶点着色器)。由于这些缓冲区对象驻留在 GPU 内存中,因此可以对其进行直接渲染,从而提高性能。
为了处理几何体,有两种类型的缓冲区对象。它们是:
顶点缓冲区对象 (VBO) - 它保存要渲染的图形模型的每个顶点数据。我们在 WebGL 中使用顶点缓冲区对象来存储和处理有关顶点的数据,例如顶点坐标、法线、颜色和纹理坐标。
索引缓冲区对象 (IBO) - 它保存要渲染的图形模型的索引(索引数据)。
定义所需的几何体并将其存储在 JavaScript 数组中后,您需要将这些数组传递给缓冲区对象,然后数据将传递给着色器程序。要将数据存储在缓冲区中,需要遵循以下步骤。
创建一个空缓冲区。
将适当的数组对象绑定到空缓冲区。
使用类型化数组之一将数据(顶点/索引)传递给缓冲区。
取消绑定缓冲区(可选)。
创建缓冲区
要创建空缓冲区对象,WebGL 提供了一个名为createBuffer()的方法。如果创建成功,此方法将返回一个新创建的缓冲区对象;否则,如果失败,则返回空值。
WebGL 作为状态机运行。创建缓冲区后,任何后续缓冲区操作都将在当前缓冲区上执行,直到我们取消绑定它。使用以下代码创建缓冲区:
var vertex_buffer = gl.createBuffer();
注意 - gl 是当前 WebGL 上下文的引用变量。
绑定缓冲区
创建空缓冲区对象后,您需要将适当的数组缓冲区(目标)绑定到它。WebGL 提供了一个名为bindBuffer()的方法来实现此目的。
语法
bindBuffer()方法的语法如下:
void bindBuffer (enum target, Object buffer)
此方法接受两个参数,下面将对它们进行讨论。
target - 第一个变量是枚举值,表示我们要绑定到空缓冲区的缓冲区类型。您有两个预定义的枚举值可供此参数选择。它们是:
ARRAY_BUFFER 表示顶点数据。
ELEMENT_ARRAY_BUFFER 表示索引数据。
Object buffer - 第二个是上一步中创建的缓冲区对象的引用变量。引用变量可以是顶点缓冲区对象或索引缓冲区对象的引用变量。
示例
以下代码片段显示了如何使用 bindBuffer() 方法。
//vertex buffer var vertex_buffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer); //Index buffer var Index_Buffer = gl.createBuffer(); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buffer);
将数据传递到缓冲区
下一步是将数据(顶点/索引)传递到缓冲区。到目前为止,数据采用数组的形式,在将其传递到缓冲区之前,我们需要将其包装在 WebGL 类型化数组之一中。WebGL 提供了一个名为bufferData()的方法来实现此目的。
语法
bufferData() 方法的语法如下:
void bufferData (enum target, Object data, enum usage)
此方法接受三个参数,下面将对它们进行讨论:
target - 第一个参数是枚举值,表示我们使用的数组缓冲区类型。此参数的选项为:
ARRAY_BUFFER 表示顶点数据。
ELEMENT_ARRAY_BUFFER 表示索引数据。
Object data - 第二个参数是包含要写入缓冲区对象的数据的对象值。这里我们必须使用类型化数组传递数据。
Usage - 此方法的第三个参数是一个枚举变量,指定如何使用缓冲区对象数据(存储的数据)来绘制图形。此参数有三个选项,如下所示。
gl.STATIC_DRAW - 数据将指定一次并使用多次。
gl.STREAM_DRAW - 数据将指定一次并使用几次。
gl.DYNAMIC_DRAW - 数据将重复指定并使用多次。
示例
以下代码片段显示了如何使用bufferData()方法。假设 vertices 和 indices 分别是保存顶点和索引数据的数组。
//vertex buffer gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); //Index buffer gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
类型化数组
WebGL 提供了一种称为类型化数组的特殊类型的数组,用于传输索引顶点和纹理等数据元素。这些类型化数组存储大量数据并以本机二进制格式处理它们,从而提高性能。WebGL 使用的类型化数组有 Int8Array、Uint8Array、Int16Array、Uint16Array、Int32Array、UInt32Array、Float32Array 和 Float64Array。
注意
通常,为了存储顶点数据,我们使用Float32Array;为了存储索引数据,我们使用Uint16Array。
您可以像使用 JavaScript 数组一样使用new关键字创建类型化数组。
取消绑定缓冲区
建议您在使用完缓冲区后取消绑定它们。这可以通过在缓冲区对象的位置传递空值来完成,如下所示。
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
WebGL 提供了以下方法来执行缓冲区操作:
序号 | 方法和描述 |
---|---|
1 | void bindBuffer (enum target, Object buffer) target - ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER |
2 | void bufferData(enum target, long size, enum usage) target - ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER usage - STATIC_DRAW, STREAM_DRAW, DYNAMIC_DRAW |
3 | void bufferData (enum target, Object data, enum usage) target 和 usage - 与上面的bufferData相同 |
4 | void bufferSubData(enum target, long offset, Object data) target - ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER |
5 | Object createBuffer() |
6 | void deleteBuffer(Object buffer) |
7 | any getBufferParameter(enum target, enum pname) target - ARRAY_BUFFER, ELEMENT_ ARRAY_BUFFER pname - BUFFER_SIZE, BUFFER_USAGE |
8 | bool isBuffer(Object buffer) |