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 ,//顶点2 
 -0.5,-0.5,//顶点3 
];


Geometry

同样,您可以为索引创建一个数组.上述三角形指数的指数为[0,1,2],可定义为 :

 
 var indices = [0,1 ,2]

为了更好地理解指数,可以考虑更复杂的模型,如square.我们可以将一个正方形表示为一组两个三角形.如果(0,3,1)和(3,1,2)是我们打算绘制正方形的两个三角形,那么索引将被定义为 :

 
 var indices = [0,3,1,3,1,2];


Geometry Example

注意 :

对于绘制图元,WebGL提供以下两种方法 :

  • drawArrays() : 使用此方法时,我们使用JavaScript数组传递基元的顶点.

  • drawElements() : 使用此方法时,我们使用JavaScript数组传递基元的顶点和索引.

缓冲区对象

缓冲区对象是WebGL提供的一种机制,用于指示系统中分配的内存区域.在这些缓冲区对象中,您可以存储要绘制的模型的数据,对应于顶点,索引,颜色等.

使用这些缓冲区对象,您可以将多个数据传递给着色器程序(顶点着色器)通过其中一个属性变量.由于这些缓冲区对象驻留在GPU内存中,因此可以直接渲染它们,从而提高性能.

要处理几何体,有两种类型的缓冲区对象.它们是 :

  • 顶点缓冲区对象(VBO) : 它包含将要呈现的图形模型的每顶点数据.我们在WebGL中使用顶点缓冲区对象来存储和处理有关顶点的数据,例如顶点坐标,法线,颜色和纹理坐标.

  • 索引缓冲对象(IBO) : 它包含将要呈现的图形模型的索引(索引数据).

定义所需几何并存储它们之后在JavaScript数组中,您需要将这些数组传递给缓冲区对象,从那里将数据传递到着色器程序.按照以下步骤将数据存储在缓冲区中.

  • 创建一个空缓冲区.

  • 将适当的数组对象绑定到空缓冲区.

  • 将数据(顶点/索引)传递给缓冲区使用其中一个类型数组.

  • 取消绑定缓冲区(可选).

<!DOCTYPE HTML>
<html>
   <head>
      <style>
         #mycanvas{border:1px solid blue;}
      </style>
   </head>
   <body>
      <canvas id = "mycanvas" width = "300" height = "300"></canvas>
   </body>
</html>

创建缓冲区

要创建空缓冲区对象,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 代表索引数据.

对象缓冲区 : 第二个是上一步中创建的缓冲区对象的引用变量.引用变量可以是顶点缓冲区对象或索引缓冲区对象.

示例

以下代码片段显示了如何使用bindBuffer ()方法.

//顶点缓冲区
 var vertex_buffer = gl.createBuffer(); 
 gl.bindBuffer(gl.ARRAY_BUFFER,vertex_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)

此方法接受三个参数,它们将在下面和下面讨论;

目标 : 第一个参数是一个枚举值,表示我们使用的数组缓冲区的类型.此参数的选项是 :

  • ARRAY_BUFFER 代表顶点数据.

  • ELEMENT_ARRAY_BUFFER 代表索引数据.

对象数据 : 第二个参数是包含要写入缓冲区对象的数据的对象值.在这里,我们必须使用类型数组传递数据.

用法 : 此方法的第三个参数是一个枚举变量,它指定如何使用缓冲区对象数据(存储数据)来绘制形状.此参数有三个选项,如下所示.

  • gl.STATIC_DRAW : 数据将被指定一次并多次使用.

  • gl.STREAM_DRAW : 数据将被指定一次并使用几次.

  • gl.DYNAMIC_DRAW : 数据将被重复指定并多次使用.

示例

以下代码段显示如何使用 bufferData()方法.假设顶点和索引分别是包含顶点和索引数据的数组.

//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 .

  • 您可以使用 new

取消绑定缓冲区

建议您取消绑定缓冲区使用后.可以通过传递null值代替缓冲区对象来完成,如下所示.

gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,null );

WebGL提供以下方法来执行缓冲操作 :

Sr.No.方法和描述
1

void bindBuffer (enum target ,Object buffer )

target :  ARRAY_BUFFER,ELEMENT_ARRAY_BUFFER

2

void bufferData (enum target ,long size ,enum usage )

目标 :  ARRAY_BUFFER,ELEMENT_ARRAY_BUFFER

用法 :  STATIC_DRAW,STREAM_DRAW,DYNAMIC_DRAW

3

void bufferData(enum target, long size, enum usage)

目标用法 : 与上面的 bufferData 相同

4

void bufferSubData (enum target ,long offset ,Object data )

目标 :  ARRAY_BUFFER,ELEMENT_ARRAY_BUFFER

5Object createBuffer()
6void deleteBuffer (对象缓冲区)
7

getBufferParameter(enum target, enum pname)

目标 :  ARRAY_BUFFER,ELEMENT_ ARRAY_BUFFER

pname :  BUFFER_SIZE,BUFFER_USAGE

8bool isBuffer(Object buffer)