我正在阅读"OpenGL Superbible"一书,我忍不住注意到,当我们创建着色器并创建将着色器附加到的程序时,我们将它们存储为GLuint,GLuint是无符号整数。
为什么它们被存储为数字?这个数字的值是什么意思?
示例:
GLuint vertex_shader;
GLuint fragment_shader;
GLuint program;
// Create and compile vertex shader
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, vertex_shader_source, NULL);
glCompileShader(vertex_shader);
// Create program, attach shaders to it, and link it
program = glCreateProgram();
glAttachShader(program, vertex_shader);
glLinkProgram(program);
这些整数是句柄。这是许多API使用的常见习惯用法,用于通过不透明的间接级别隐藏资源访问。OpenGL有效地防止您在不使用API调用的情况下访问句柄后面的内容。
来自维基百科:
在计算机程序设计中,句柄是对资源的抽象引用。[…]资源句柄可以是不透明的标识符,在这种情况下,它们通常是整数,也可以是允许访问进一步信息的指针。
数字的值没有任何意义,0
除外,它的意思是"没有对象"。
当您进行glGen*()
或glCreate*()
类型的调用时,这些值由驱动程序生成。它们是对对象的不透明引用。您可以想象驱动程序在这些数字和相应的内部对象之间保持映射。每次将数字作为参数传递给API调用(例如glBind*()
)时,驱动程序都会查找该数字,并将其映射回相应的内部对象。
从语义上讲,这非常像C/C++中的指针。当你分配内存时,你会得到一个指针。您可以使用这个指针来引用您分配的内存。不过,在OpenGL的情况下,您不会获得原始内存地址,而是获得引用对象的不透明表示。
在其他API中也使用了相同的概念。例如,Windows(Win32)广泛使用不透明的对象引用,他们称之为"句柄"。
现在你可能想知道OpenGL为什么不简单地使用指针而不是这些对象id。这只是我个人的看法,但我相信主要的动机是OpenGL被设计为客户端/服务器API,在那里渲染可以在不同于运行应用程序的机器上进行。如果API流必须打包并通过网络发送,那么使用指向引用对象的指针并不容易。在这种情况下,使用不透明的id要干净得多。
顺便说一句,在OpenGL的官方术语中,这些值大多被称为"名称"。我总是觉得这有点误导,因为大多数人听到"name"时都会想到字符串。我自己大多称他们为"id"。