对于OpenGL中的某些函数,必须为stride指定字节偏移量,例如在glVertexAttribPointer()
中。起初我会猜到它将是一个像整数一样的正常数值。但经过检查,我意识到需要将其转换为void*
(更具体地说是GLvoid*
)。我的问题是:void*
的意图是什么?为什么必须将它用于字节偏移?
答案 0 :(得分:5)
glVertexAttribPointer()是Vertex Buffer Objects之前的旧函数。
在VBO之前,您的顶点数据将存储在客户端数组中,您需要在绘制之前将指向数据的指针传递给OpenGL。
当VBO出现时,他们通过允许指针用于传递整数偏移来重新调整此函数。
e.g。
void* offset = (void*)offsetof(vertexStructName, vertexMemberName);
答案 1 :(得分:3)
某些OpenGL函数(例如glDrawElements
)采用与上下文相关的GLvoid *
参数。在旧的GL上,在Vertex Buffers之前,程序员会将一个整数索引数组直接传递给glDrawElements
,如下所示:
const GLuint indexes[] = { ... };
glDrawElements(GL_TRIANGLES, numIndexes, GL_UNSIGNED_INT, indexes);
这被称为立即模式绘图。
当引入顶点和索引缓冲区时,OpenGL架构板决定它们应该重用现有的接口,从而为glDrawElements
,glVertexAttribPointer
的最后一个空指针参数提供新的上下文相关含义,一些其他类似的功能。
使用索引缓冲区,渲染数据已经在GPU上,因此void指针参数意味着是 offset 进入缓冲区。例如:第一个渲染的索引。导致glDrawElements
的新用法:
size_t firstIndex = ...
size_t indexDataSize = sizeof(GLuint);
glDrawElements(GL_TRIANGLES, numIndexes, GL_UNSIGNED_INT, reinterpret_cast<const GLvoid *>(firstIndex * indexDataSize));
这适用于在现代OpenGL上重新使用的所有旧功能,例如glDrawElementsInstanced
,glDrawElementsBaseVertex
,glDrawRangeElements
和其他功能。
现在处于glVertexAttribPointer
的具体情况:
void glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * pointer);
const GLvoid * pointer
参数是从顶点开始到给定元素的偏移量(以字节为单位)。同样,它保持这样,因为函数存在于Vertex / Index Buffers之前并重新用于它们,而在立即模式时,你会传递一个顶点数组作为'指针'参数。
所以在过去,glVertexAttribPointer
的用法有点像:
const vec3 positions[] = { ... };
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, positions);
在现代GL中,你会使用:
struct Vert {
vec3 position;
vec3 normal;
};
size_t offset;
offset = offsetof(Vert, position);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, reinterpret_cast<const GLvoid *>(offset));
offset = offsetof(Vert, normal);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, reinterpret_cast<const GLvoid *>(offset));
答案 2 :(得分:0)
它被称为void指针,它可以指向任何类型,如char *,但它略有不同。首先,你必须记住指针只是一个数字,一个地址到正确的位置,仅此而已。要使用void指针指向的数据,必须将其显式转换为正确的类型,不能直接取消引用它们。它们允许您跳过类型检查,应该避免它们。
我看到的另一个不同之处是意图明确。当你看到char *指针时,你无法确定它是否会指向char / char数组。它可能是别的东西,它是高度情境化的:我看到它混淆的情况,有时很明显;另一方面,void指针的意图是明确的:它可以是任何东西,你必须考虑应用程序的上下文来找到类型。
另一件事是指针算术,AFAIR在无效指针的情况下它没有被标准定义。
我认为OpenGL中的void指针用于使API更通用,从而为驱动程序提供更多控制(通过设置可以更轻松地将浮动类型更改为双打)。但这只是猜测,需要确认。