定义几何
几何数据是指用于定义图形对象形状的信息,这些数据主要包括顶点、图元及其相关的属性。几何数据是WebGL渲染管线的输入,用于生成最终的图像。以下是几何数据的主要组成部分:
-
顶点数据:顶点是几何数据的基本单位,用于定义图形的形状。一个顶点通常包含以下信息:
- 位置 定义顶点在空间中的位置
- 法向量 表示顶点的方向,用于光照计算
- 纹理坐标 用于映射纹理到几何对象
- 颜色 每个顶点可以携带颜色信息(r,g,b,a),用于直接着色
- 其他属性 开发者可以定义额外的顶点属性,用于一些特别的场景,比如CAE仿真结果场数据
-
图元:由顶点组成的基础几何形状,是WebGL渲染的基础单位。我们的引擎中支持以下几种图元类型:
- 点(Points) gl.POINTS:单个顶点绘制为一个点
- 线(Lines) 由两个顶点组成的线段。类型包括: gl.LINES:独立的线段。 gl.LINE_STRIP:连续的线段。 gl.LINE_LOOP:连续线段,最后一个顶点与第一个顶点相连。
- 三角形(Triangles) 由三个顶点组成的三角形,是WebGL中最常用的图元。类型包括: gl.TRIANGLES:独立的三角形。 gl.TRIANGLE_STRIP:连续的三角形条带。 gl.TRIANGLE_FAN:以一个中心顶点为基础的三角形扇形。
-
顶点索引:用于指定图元中顶点的连接信息。通过索引数组可以重用顶点数据,减少冗余。索引数据存储在索引缓冲对象(Index Buffer Object)中。
接下来,我们可以从零构建一个简单的3D空间渲染场景scene,该场景的几何是一个三角形。
从这个例子中,您可以了解到以下内容:
- 定义几何:详细介绍了如何利用ORE Core库的接口定义绘制场景中的几何数据
- 使用几何数据:WebGL的着色器如何使用几何数据,使其呈现在2D屏幕中
- 构造渲染场景:从零开始构建渲染上下文所需的所有对象
定义几何
在下面的代码段中定义了3D空间中的一个三角形,它的三个顶点的位置坐标分别是:(-0.5, -0.5, 0.0),(0.5, -0.5, 0.0),(0.0, 0.5, 0.0)。
我们先创建一个geometry对象,包括它的顶点位置、顶点索引。这里需要使用Vertices接口,来声明一个存储顶点数据的顶点缓冲对象,使用Triangles接口,声明了三角形图元的索引缓冲对象。
const geometry: JGeometry = {
vertices: {
// 所有顶点的位置被保存在一个顶点缓冲中。
positions: Vertices([-0.5, -0.5, 0.0, 0.5, -0.5, 0.0, 0.0, 0.5, 0.0])
},
//当具备顶点信息后,使用顶点索引数组就可以定义三角形图元。索引数组保存在一个索引缓冲中。
indices: Triangles([0, 1, 2])
};
顶点缓冲对象
在上面的代码段中我们可以看出,顶点缓冲的定义需要使用接口Vertices。一般来说,顶点信息不仅仅包含位置信息,还需要有法向、纹理以及boundingBox。
const geometry: JGeometry = {
vertices: {
// 所有的图元顶点的位置、法向量、纹理坐标,它们分别保存在各自的顶点缓冲中。
positions: Vertices([-0.5, -0.5, 0.0, 0.5, -0.5, 0.0, 0.0, 0.5, 0.0]),
normals: Vertices([...]),
texCoords: Vertices([...]),
},
indices: Triangles([0, 1, 2]),
boundingBox: bbox(-0.5, 0.5, -0.5, 0.5, 0.0, 0.0)
};
顶点缓冲对象会作为WebGL的Shader程序的输入,在Shader程序中,您将需要指定顶点缓冲对象的数组维度,比如3D空间中位置是三维的,而2D空间中位置是二维的。法向量是三维的,而纹理坐标是二维的。
索引缓冲对象
两个顶点连接形成一个线段,三个顶点连接形成一个三角形面。当空间中存在大量顶点时,必须通过索引缓冲对象定义这些顶点的连接,不同的连接,最终会成为不同形状的Shell。
比如一个三角形面的顶点索引是数组[0,1,2],另一个三角形面的顶点索引是数组[0,2,3], 如果这两个三角形面属于同一个几何,那么在该几何的索引缓冲中,就有会这样一个数组片段:[...,0,1,2,0,2,3,...]。我们需要将该实体几何的所有图元的索引数组都写入该IBO中,最终被传输到着色器中。
ORE core中提供了多种图元接口,他们本质上是声明了构成某种图元的顶点索引数组对象:
-
Points,创建多个顶点POINTS。 -
Lines,创建多个双顶点线段LINES,每两个顶点指定一条单独线段。 -
LineStrip,创建不闭合的连续线段LINE_STRIP,每个顶点之后的顶点指定的是线条延伸到的下一个点。 -
LineLoop,创建闭 合的连续线段LINE_LOOP,与LINE_STRIP类似,只不过最后一条线段是由指定的最后一个和第一个顶点连接而成。 -
Triangles,创建多个三角形面TRIANGLES,每三个顶点指定一个三角形面。 -
TriangleFan,创建扇型连续三角形面TRIANGLE_FAN。指定的第一个顶点充当原点,后继的每个顶点与它前面的一个顶点以及原点,一起构成下一个三角形面。 -
TriangleStrip,创建线型连续三角形面TRIANGLE_STRIP。指定开始的三个顶点之后,后继的每个顶点与它前面两个顶点一起构成下一个三角形面。
在这个例子中,我们使用了定义TRIANGLES图元的接口Triangles([0, 1, 2]),表示顶点缓冲中的索引0、1、2对应的顶点构成的一个三角形。
图元的索引缓冲都可以用两种不同的类型定义,即:JElementIndices类型与JArrayIndices类型。下面以定义三角形面的索引缓冲为例:
// JElementIndices类型的索引缓冲
const triangles1 = Triangles([...]);
// JArrayIndices类型的索引缓冲
const triangles2 = Triangles(n);
-
ElementIndices类型:
Triangles([...])中需要直接写出所有图元的索引数组缓冲,比如Triangles([0,1,2,0,2,3]),它代表该几何有两个三角形面,它们的顶点索引数组分别是[0,1,2]、[0,2,3]。 -
ArrayIndices类型:
Triangles(n)中只需要指定构成所有三角形面的顶点个数,就可以确定该几何所有的三角形图元各自的索引数组了。比如Triangles(6)代表该几何有两个三角形面,分别是[0,1,2]、[3,4,5],或者比如TriangleStrip(6)代表该几何有4个三角形面,分别是[0,1,2]、[1,2,3]、[2,3,4]、[3,4,5]。