三、WebGL入门,顶点缓冲区

本文将引导读者入门WebGL,重点讲解顶点缓冲区的概念和使用方法,包括如何创建缓冲区、绑定缓冲区到WebGL对象以及如何传入数据。此外,还提到了相关知识点如索引缓冲区、纹理、帧缓冲等。
摘要由CSDN通过智能技术生成

我们在接下来的学习中,我们主要会了解到一下一些知识点:

  1. 顶点缓冲区
  2. 索引缓冲区
  3. 纹理
  4. 帧缓冲
  5. 深度缓冲
  6. 颜色缓冲
  7. 模型缓冲
  1. 模型矩阵
  2. 观察矩阵
  3. 投影矩阵
  4. 视口
本节先介绍顶点缓冲区


顶点缓冲区的使用步骤:

  1. 创建缓冲区
  2. 绑定缓冲区到WebGL对象
  3. 传入数据到缓冲区
1 ,createBuffer()
 triangleBuffer = webgl.createBuffer();
创建缓冲区,在显存上。
2,bindBuffer()
<span style="font-size:18px;">webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer);</span>
将创建出来的缓冲区绑定到webGL对向上,这里我们使用了2个参数,第一个是类型,因为我们使用的是数组的点数据,所以使用系统提供的 gl.ARRAY_BUFFER 变量。第二个参数是我们需要绑定的Buffer对象,这里使用的就是我们前边创建出来的Buffer对象。
3,bufferData()
 var jsArrayData = 
     [
       0.0, 1.0, 0.0,//上顶点
       -1.0, -1.0, 0.0,//左顶点
       1.0, -1.0, 0.0
      ];//右顶点
 webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(jsArrayData), webgl.STATIC_DRAW);

这一步我们将我们的点位置数组传入到Buffer对象中 该方法接受的3个参数分别为

  • 数据类型,可以是 gl.ARRAY_BUFFER , gl.ELEMENT_ARRAY_BUFFER ,本例中使用的是 gl.ARRAY_BUFFER
  • 数据
  • 缓冲类型,有这么几种可以供我们选择 GL_STREAM_DRAW , GL_STATIC_DRAW ,GL_DYNAMIC_DRAW
缓冲区的数据偶尔变动用GL_STREAM_DRAW 缓冲区的数据不变用GL_STATIC_DRAW,缓冲区数据经常变动用GL_DYNAMIC_DRAW

于是问题就出现了,我的一部分数据不变,一部分数据经常变动,该如何处理?这个以后再谈

给缓冲区赋值还有另外一种方式,用到以下两个函数:
 void bufferData(GLenum target, GLsizeiptr size , GLenum usage);
 void bufferSubData(GLenum target, GLintptr offset, BufferDataSource? data);
其中第一个函数是我们之间用到的 void bufferData(GLenum target, BufferDataSource? data, GLenum usage)函数的重载。
步骤是:1,先创建一个size大小的空的缓冲区,2,再往里面传值(PS:以后开发推荐用这种方式,灵活
//另外一种赋值方式
webgl.bufferData(webgl.ARRAY_BUFFER,4*9,webgl.STATIC_DRAW);
webgl.bufferSubData(webgl.ARRAY_BUFFER, 0, new Float32Array(jsArrayData));
4*9的意思是:绘制之间的三角形要3个点,一个点有3个坐标(x,y,z)共9个变量,由于是float类型的,占4个字节,共4*9个字 节, 即存储这9个变量要36个字节的缓冲区大小。

再解释下GLintptr offset的含义:offset单位是字节,意思是从BufferDataSource? data所指向的数组或缓冲的首地址偏移offset个字节开始读数据,上面代码offset是0,代表是从数组或缓冲区首地址开始读数据,若offset=2时,如下图所示:

上节提到了:
webgl.bindBuffer(webgl.ARRAY_BUFFER,triangleBuffer)
使用了两次,现在来详细的解释下原因。
我在创建一个缓冲区,代码如下:
jsArrayData1 = [
                    1.0, 1.0, 0.0,//上顶点
                    -1.0, -1.0, 0.0,//左顶点
                    0.0, -1.0, 0.0
                ];//右顶点
  triangleBuffer1=webgl.createBuffer();
  webgl.bindBuffer(webgl.ARRAY_BUFFER,triangleBuffer1);
  webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(jsArrayData1), webgl.STATIC_DRAW);
新的顶点数组jsArrayData1,新的缓冲区triangleBuffer1,注意bufferData()这个操作并没有指定是向哪个缓冲区传输数据,说明是上一个句代码bindBuffer()指定的,它指定的是一个状态,是一个状态机,当设置好后若不改变则会一直保持这个状态,现在绑定的是triangleBuffer1,则目前都是使用的是triangleBuffer1指向的缓冲区。
下面就是绘制了
     webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer1);
     webgl.enableVertexAttribArray(v3PositionIndex);
     webgl.vertexAttribPointer(v3PositionIndex, 3, webgl.FLOAT, false, 0, 0);
     webgl.drawArrays(webgl.TRIANGLES, 0, 3);
注意在绘制前又调用了一次bindBuffer(),绑定的是triangleBuffer1,使用是其绑定的缓冲区,绘制的结果是:


若改成:
webgl.bindBuffer(webgl.ARRAY_BUFFER,triangleBuffer)
则绘制的结果是:

bindBuffer()的作用是修改当前的状态。

下面来介绍下剩下来的几个函数:

void enableVertexAttribArray(GLuint index);
void vertexAttribPointer(GLuint indx, GLint size, GLenum type, 
                             GLboolean normalized, GLsizei stride, GLintptr offset);
void drawArrays(GLenum mode, GLint first, GLsizei count);

第一个enableVertexAttribArray()是启用顶点属性索引
第二个函数vertexAttribPointer()重点说一下,第一个参数GLuint indx是指shader程序的输入入口,由于如下操作
webgl.bindAttribLocation(programObject,v3PositionIndex,"v3Position");
v3PositionIndex索引与shader程序里面的v3Position变量绑定了,vertexAttribPointer()的含义是告诉显卡从当前绑定的缓冲区(bindBuffer()指定的缓冲区)中读取顶点数据,入口是v3PositionIndex,即传值给v3Position。
第二个参数GLint size是指v3Position的维度,由于类型是vec3,所以size = 3。第三个参数GLenum type是指参数类型,
指定一个数据占多少个字节。第四个参数GLboolean normalized是指是否标准化(化为0-1范围),第五个参数比较复杂,
先讲第六个参数GLintptr offset,这参数是指从shader程序的入口v3PositionIndex从bindBuffer()绑定的缓冲区偏移offset个字节
开始读数据,这里offset=0,指从绑定缓冲区首地址开始读。可以参照上边的bufferSubData()函数理解。
现在我们来看第五个参数GLsizei stride,stride的意思是步长,单位是字节,指的是每个顶点数据所占的字节数
我们上一节例子的顶点数据只包含位置信息(xyz),其实还可以包含其他一些信息,如颜色信息(rgba),法向量(nxnynz),
纹理信息(uv)等。现在改写下顶点数据:
 var jsArrayData = 
    [
     //x     y       z       nx      ny      nz
     -0.5,   +0.5,   0.0,    0.0,    0.0,    0.0,
     +0.5,   +0.5,   0.0,    0.0,    0.0,    0.0,
     +0.5,   -0.5,   0.0,    0.0,    0.0,    0.0,

     -0.5,   +0.5,   0.0,    0.0,    0.0,    0.0,
     +0.5,   -0.5,   0.0,    0.0,    0.0,    0.0,
     -0.5,   -0.5,   0.0,    0.0,    0.0,    0.0,
    ];//右顶点

一个顶点信息增加了法向量信息,而由于我们的shader程序中v3Position是顶点的位置数据,若stride=0时,
则最终 v3Position读取的数据为(-0.5,0.5,0.0), (0.0,0.0,0.0),(0.5,0.5,0.0)为jsArrayData数组的前三个,
读的数据有误, 所以stride=6*4(每个数据占4个字节)才能保证读到我们想要的数据,stride=6*4的意思是每个步长24个字节
读取一个v3Position数据(前三个数据传给v3Position)。

第三个函数drawArrays(),第一个参数GLenum mode指的是绘制图元模式,下面是WebGL的图元模式:
    const GLenum POINTS                         = 0x0000;
    const GLenum LINES                          = 0x0001;
    const GLenum LINE_LOOP                      = 0x0002;
    const GLenum LINE_STRIP                     = 0x0003;
    const GLenum TRIANGLES                      = 0x0004;
    const GLenum TRIANGLE_STRIP                 = 0x0005;
    const GLenum TRIANGLE_FAN                   = 0x0006;

第二个参数GLint first指从绑定的缓冲区(bindBuffer())中首地址偏移first 下标(不是字节数)开始读数据。
第三个参数count是指绘制顶点数据的个数,即shader代码运行的次数。

下面简单介绍下WebGL的坐标系。

本节介绍的东西比较多,也比较啰嗦,若有错误,欢迎指正。
本节完!

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值