NOTE
第五章-数据
本章我们会学到什么
- 如何创建缓冲和纹理,用它们来存储数据,以及程式如何访问数据。
- 如何使得OpenGL自动为我们的顶点属性提供数据。
- 如何从着色器中访问纹理和缓冲。
至今为止的示例中,我们要么在着色器直接使用硬编码的数据,要么将值一个一个地传入到着色器中。但要充分地演示OpenGL管线的构造,这很难代表现代图形编程。现代的图形处理器设计为流式处理器,可以吞吐大量的数据。一次给OpenGL传递很少的值是炒鸡没有效率的。要使得数据被OpenGL存储并访问,我们有两种主要的数据存储形式–缓冲和纹理。本章我们先介绍缓冲,它是无类型的线性数据块,可以被看成通用的内存配额。然后我们介绍纹理,它一般用来存储多维度数据,比如图像或者其他数据类型。
缓冲
在OpenGL中,缓冲是线性内存配额,可被用于多种用途。它们通过名字(names)来表示,名字就是OpenGL用来识别它们的句柄。在我们使用缓冲之前,先得要OpenGL为我们保留一些名字,然后用它们来分配内存并把数据放进去。为一个缓冲对象分别的内存被称为数据仓储(data store)。缓冲的数据仓储是OpenGL存放缓冲数据的地方。我们可以使用OpenGL命令来将数据放入缓冲,或者我们可以映射(map)缓冲对象得到一个指针,然后我们的应用可以使用这个指针直接读写缓冲。
一旦我们得到一个缓冲的名字,我们可以将它绑定到一个缓冲绑定点(buffer binding point)从而将它附加到OpenGL上下文。绑定点有时称为目标(targets),这些术语可以互换使用(从严格的技术角度来讲,目标 targets和绑定点 binding point是有区别的,一个目标可以有多个绑定点,不过,大多数情况下还是很容易理解真正的含义的)。在OpenGL中有很多的缓冲绑定点,并且每个都有不同的用处,尽管它们绑定的缓冲对象可能是同一个。比如:我们可以用缓冲的内容为顶点着色器自动提供输入;存储着色器会用到的变量的值;或者作为着色器存储生成数据的地方。我们甚至可以同时将一个缓冲用于多种用途。
创建缓冲并分配内存
在我们让OpenGL分配内存之前,我们需要先创建一个缓冲对象来表示这个配额。就像OpenGL中大多数对象一样,缓冲对象用GLuint变量来表示,这个变量也称为它的名字(names)。使用glCreateBuffers()函数可以创建一个或多个缓冲对象,它的原型为:
void glCreateBuffers(GLsizei n, GLuint* buffers);
glCreateBuffers()的第一个参数n
,是要创建的缓冲对象的数目。第二个参数buffers
,是用来存储缓冲对象名字的变量的地址。如果我们只需要创建一个缓冲对象,将n
设置为1,buffers
设置为单个GLuint变量的地址即可。如果我们需要一次创建多个缓冲,将n
设置为指定的数目,buffers
指向包含至少n
个GLuint变量的数组地址即可。OpenGL会假定这个数组足够大,它会向指定的地址写入n
个缓冲的名字。
从glCreateBuffers()获取到的每个名字都代表一个缓冲对象。我们可以调用glBindBuffer()将缓冲对象绑定到当前OpenGL上下文,glBindBuffer()的原型为:
void glBindBuffer(GLenum target, GLuint buffer);
在我们真正使用缓冲对象之前,我们需要分配它们的数据仓储(data stor