在 OpenGL 中,为什么 glVertexAttribPointer 需要将 "pointer" 参数作为 void* 传入?

In OpenGL, why does glVertexAttribPointer require the "pointer" argument to be passed in as void*?

glVertexAttribPointer的规格如下:

void glVertexAttribPointer( GLuint index,
    GLint size,
    GLenum type,
    GLboolean normalized,
    GLsizei stride,
    const GLvoid * pointer);

鉴于最后一个参数只是一个 4 字节的整数偏移量,为什么 OpenGL 希望它作为空指针传入?

旧版。

该参数在 VBO 之前具有不同的含义:您将顶点数据保存在客户端内存中并传递数组的地址(参见 glEnableClientState 等)。

现在最后一个参数可以有两个含义(缓冲区对象的偏移量,客户端状态数组的地址)。 Khronos 没有为缓冲区对象的 gl*Pointer 函数提供单独的版本,所以你需要做这个笨拙的转换。

一种看待它的方式是最后一个参数总是一个指针:

  • 如果没有绑定 VBO,它是一个相对于基地址 0 的指针。这是一个常规的内存地址,就像指针在 C/C++ 中通常使用的方式一样。
  • 如果是 VBO 绑定,它是一个相对于缓冲区基址的指针。

至少这是我能找到的唯一合乎逻辑的解释。

就我个人而言,我认为以这种方式重载入口点是一个非常不幸的决定,原因有很多:

  • 百思不得其解
  • 它需要在 C/C++ 中进行丑陋的类型转换。
  • 它在更多类型安全的语言中根本不起作用,例如 Java。

在像 Java 这样的语言中,您通常会得到接受不同类型的函数的重载版本。作为一个有点奇怪的历史记录,在 Android 中 GLES20 绑定的初始版本中缺少带有 int 参数的重载版本,这意味着您不能使用来自 Java。所以这比偶尔偶然的 OpenGL 程序员更容易绊倒。