OpenGL 对象
在顶点数据定义好了之后,通常这些属性会作为输入发送给图形渲染管线的第一个处理阶段:顶点着色器。它会在GPU上创建内存用于存储顶点数据,同时还要告诉OpenGL如何去解释内存中的这些数据,并且指定如何发送到显卡。顶点着色器接下来会处理内存中指定数量的顶点。通常会采用VBO对象来管理这个GPU上分配的内存。
VBO对象
VBO,即顶点缓冲对象(Vertex Buffer Object),主要作用就是可以一次性发送大批顶点数据到显卡上,而不是每个顶点发送一次。原因是CPU传送数据给GPU其实是比较耗时的,所以尽可能的一次性把需要的顶点数据全部传给GPU,这样顶点着色器几乎能立即访问到顶点,有助于加快顶点着色器效率。
系列文章
- Android OpenGL基础1——常用概念及方法解释
- Android OpenGL基础2——Shader的使用流程
- Android OpenGL基础3——纹理的使用
- Android OpenGL基础4——变换
- Android OpenGL——Android Studio OpenGL开发的简单示例
创建步骤
生成一个(或多个)缓冲类型的id
1
2
3
4
5
6
7// 生成一个vbo id
unsigned int vbo;
glGenBuffers(1, &vbo);
// 或者 生成3个 vbo id
unsigned int vbos[3];
glGenBuffers(3, &vbos);glGenBuffers(GLsizei n, GLuint buffers),生成缓冲对象名字,n为缓冲对象名字个数, buffers为存放名字的数组,*n和数组长度需要一直
将缓冲对象id绑定给指定的缓冲类型
1
glBindBuffers(GL_ARRAY_BUFFER, vbo)
缓冲类型通常有:GL_ARRAY_BUFFER, GL_COPY_READ_BUFFER,
GL_COPY_WRITE_BUFFER, GL_ELEMENT_ARRAY_BUFFER,
GL_PIXEL_PACK_BUFFER, GL_PIXEL_UNPACK_BUFFER, GL_TEXTURE_BUFFER,
GL_TRANSFORM_FEEDBACK_BUFFER, or GL_UNIFORM_BUFFER.
注意:OpenGL中存在多种不同类型的缓冲对象(如上所述),所以只要缓冲对象类型不同,OpenGL是允许我们同时绑定多个缓冲的。
小结
创建VBO对称步骤:
- 生成VBO对象id(调用
glGenBuffers
); - 为生成的id指定缓冲类型(调用
glBindBuffers
);
赋值操作
VBO 对象的赋值主要利用glBufferData
函数来进行:
1 | /** |
上面的usage参数,常用的有如下几个值:
- STREAM,modified once and used at most a few times;
- STATIC,modified once and used many times;
- DYNAMIC,modified repeatedly and used many times;
示例:
1 | // 定义顶点数据 |
支持数据就已经推送到GPU中去了,一个VBO过程就结束了。
数据的处理
上面通过一些列的接口调用,最终完成了想GPU数据的推送,那么GL是怎么告诉GPU如何处理这些数据的呢,毕竟上面的vertices
数组描述了顶点数据两种类型的信息:位置和颜色。要处理上面的数据(vertices),需要如下代码:
1 | // 位置属性 |
- glEnableVertexAttribArray,开启对应位置的顶点属性;
- glDisableVertexAttribArray,关闭随影位置的顶点属性;
- glVertexAttribPointer,说明顶点属性数据的解析规则;
OpenGL中,主要通过glVertexAttribPointer
这个函数来说明该如何解析传递给GPU的数据的。参数说明:
1 | void glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, |
- index,指定哪个顶点属性奖杯修改,通常对应如顶点Shader中layout(position = 0)这个position;
- size,表示顶点属性指的大小,上面
vertices
位置和颜色都是有三个float型数据组成的,所以是3; - type,指的是数据的类型,上面
vertices
对应的时GL_FLOAT; - normalized,是否希望数据标准化。如果我们设置为GL_TRUE,所有数据都会被映射到0(对于有符号型signed数据是-1)到1之间。我们把它设置为GL_FALSE;
- stride,表示一条完整顶点属性(包括location和color)的长度(这里需要6个数来表示),所以这里是6;
- pointer,表示偏移量,即在一段数据中,指定的数据偏移多少位置开始。在这里,坐标数据都是每段数据的起始位置,所以偏移量是0,而颜色数据在坐标数据之后,坐标数据有3个分量,所以每个颜色数据偏移三个float字节开始算;
VAO对象
VAO,即顶点数组对象(Vertex Array Object),VAO作用就是顶点属性调用都会存储在VAO中。这样的好处就是,当配置顶点属性指针时,你只需要将那些调用执行一次,之后再绘制物体的时候只需要绑定相应的VAO就行了。简单来说有点类似复用的概念。 那么VAO到底复用了哪些过程呢,先看物体绘制的一般过程:
1 | // 0. 复制顶点数组到缓冲中供OpenGL使用 |
如果使用VAO,任何绑定VAO后的顶点属性调用都会储存在这个VAO中。这样的好处就是,当配置顶点属性指针时,你只需要将那些调用执行一次,之后再绘制物体的时候只需要绑定相应的VAO就行了。
创建及使用
生成一个id并绑定,然后进行VBO的复制操作,再进行顶点指针的设置操作,
1 | // 定义一个 id,用来存储生成的VAO对象名称 |
Sample对象
Sample对象,即采样器对象,它是GLSL有一个供纹理对象使用的内建数据结构,在Shader定义好Sample对象后,后面这个对象就可以接收外面传递进来的纹理对象的值了。
根据纹理的类型,Sample对象也有相对应的类型:
- 1D->sample1D;
- 2D->sample2D;
- 3D->sample3D;
数学基础
要学习好OpenGL,就必须对基本的数学知识有所了解,这里先列出几个点:
- 向量
- 矩阵