所以,在为我正在研究的3D场景编写模型加载器的过程中,我决定打包顶点,纹理和普通数据,如下所示:
VVVVTTTNNN
对于每个顶点,其中V =顶点坐标,T = UV坐标,N =正常坐标。当我将这些数据传递给我的场景的顶点着色器时,我会进行三次glVertexAttribPointer调用,如下所示:
glVertexAttribPointer(ATTRIB_VERTEX, 4, GL_FLOAT, 0, 10, group->vertices.data);
glEnableVertexAttribArray(ATTRIB_VERTEX);
glVertexAttribPointer(ATTRIB_NORMAL, 3, GL_FLOAT, 0, 10, group->normals.data);
glEnableVertexAttribArray(ATTRIB_NORMAL);
glVertexAttribPointer(ATTRIB_UV_COORDINATES, 3, GL_FLOAT, 0, 10, group->uvcoordinates.data);
glEnableVertexAttribArray(ATTRIB_UV_COORDINATES);
传递的每个组指针都指向该顶点类型开始的共享顶点数据块中的起始位置:
group->vertices.data == data
group->uvcoordinates.data == &data[4]
group->normals.data == &data[7]
我将这些数据交错的部分原因是为缓存友好性编程并最小化发送到卡的数据。 (注意:这不是一个现实的性能瓶颈。我正在调查优化,因为我想了解更多关于编程以解决这些问题。)但是,对于我的生活,我无法想象GL会如何能够推断出3个不同的指针指的是相同较大数据块内的偏移位置,从而进行必要的优化以避免一旦复制数据就复制数据。此外,由于我只是确保系统内存中的数据位置(并且实际上没有任何关于如何在GPU上组织数据的保证),我只是真正优化我访问任何一个GL之外的这些顶点。是对的吗?这些优化大多是无用的,或者以这种方式提供数据有助于最小化向GPU的数据传输/防止在顶点着色器中迭代顶点数据时的缓存未命中?
答案 0 :(得分:3)
OpenGL只是一个API,智能在于驱动程序。无论如何,问题实际上很容易实现:对于每个Vertex属性,你有一个起始内存地址,当调用glDrawArrays或glDrawElements时,你会找到找到的最大索引。这定义了范围的上限。
然后对起始地址和每个地址检查的顶点属性进行排序,检查其范围是否与任何其他顶点属性范围重叠。您可以找到连续的区域并复制它们。
在Vertex Buffer Objects的情况下,它甚至更简单,因为您已经将东西复制到OpenGL中以备处理。