我想直截了当,这就是为什么我从这个场景开始: -
假设您要绘制两个立方体并假设您已经创建,绑定,填充缓冲区对象以及两个多维数据集的数据,并且您拥有两个多维数据集的元素数组,如下所示:
const GLshort indexData[] =
{
//Object 1
0, 2, 1, 3, 2, 0,
4, 5, 6, 6, 7, 4,
8, 9, 10, 11, 13, 12,
14, 16, 15, 17, 16, 14,
//Object 2
18, 20, 19, 21, 20, 18,
22, 23, 24, 24, 25, 22,
26, 27, 28, 29, 31, 30,
32, 34, 33, 35, 34, 32,
};
绘制这两个对象的第一种方法如下: -
// first Cube
glDrawElements(GL_TRIANGLES, ARRAY_COUNT(indexData), GL_UNSIGNED_SHORT, 0);
// second Cube
glDrawElementsBaseVertex(GL_TRIANGLES, ARRAY_COUNT(indexData),GL_UNSIGNED_SHORT, 0, numberOfVertices / 2);
但是可以使用以下代码绘制两个立方体吗?
// first cube
glDrawElements(GL_TRIANGLES, ARRAY_COUNT(indexData), GL_UNSIGNED_SHORT, 0);
//second cube
// set the indice pointer to 24 so that it starts reading data for the second cube
glDrawElements(GL_TRIANGLES, ARRAY_COUNT(indexData), GL_UNSIGNED_SHORT, pointer to 24th element);
如果是,那么使用glDrawElementBaseVertex()
是什么意思?
答案 0 :(得分:3)
没有
在代码中:
glDrawElements(GL_TRIANGLES, ARRAY_COUNT(indexData), GL_UNSIGNED_SHORT, 0);
最后一个元素是指向索引数组的指针。在这种情况下,您传递0,这是空指针,这意味着OpenGL将从绑定数组中获取索引。这不是抵消。
在第二部分中:
glDrawElementsBaseVertex(GL_TRIANGLES, ARRAY_COUNT(indexData),GL_UNSIGNED_SHORT, 0, numberOfVertices / 2);
最后一个参数是偏移量,如您所愿。 此外,如果您计划为每次调用仅绘制一半缓冲区,则应从
更改count参数ARRAY_COUNT(indexData)
到
ARRAY_COUNT(indexData)/2
为了每次调用绘制一半缓冲区。
有关详细信息,请阅读有关这两个功能的文档:
glDrawElements
glDrawElementsBaseVertex
答案 1 :(得分:0)
是
实际上,我正在阅读和你一样的在线书籍,我遇到了和你一样的问题。
我已经测试了你的代码(带有“第24个元素”的代码),它的工作方式与原始代码类似:
原着
glDrawElementsBaseVertex(GL_TRIANGLES, ARRAY_COUNT(indexData),
GL_UNSIGNED_SHORT, 0, numberOfVertices / 2);
我得到了
和
glDrawElements(GL_TRIANGLES, ARRAY_COUNT(indexData), GL_UNSIGNED_SHORT,
(void*)(indexData + 24));
我得到了
他们是一样的。
事实上,我整天都在想这个问题。
正如本书指出的那样(here,检查最后一个注释的第二段),(在32位操作系统上)如果你的模型包含超过65536(2个字节)的顶点,那么element数组不能再使用GL_UNSIGNED_SHORT(2个字节)作为索引的类型。相反,它必须使用GL_UNSIGNED_INT(4个字节)。它需要两倍的存储空间。
然后检查here以查看glDrawElementsBaseVertex的描述。它表示如果( indices [i] + basevertex )的值超过 type 的最大值,则该值将被上转换为32 -bit unsigned int。
考虑到这些参考文献,我得出以下结论:
例如,假设我有一个包含1,000,000个顶点的3D角色。如果我使用glDrawElements来渲染它,我必须使用GL_UNSIGNED_INT来存储索引,这将需要大约3.8MB。但是,如果我可以使用类似“65536 * numberOfPage + index ”的东西(如果我可以在不同的“页面”中打破这些顶点,就像随机访问一样,并且使用 index 来指示该页面中的顶点;而65536可能是页面的大小)使用glDrawElementsBaseVertex,我仍然可以使用GL_UNSIGNED_SHORT来存储这些索引。在这种情况下,它将节省我约1.9MB。
也许1.9MB听起来不是一个大数字,但想想现代3D视频游戏的情况。我确信这些字符必须包含超过1,000,000个顶点,在这种情况下,glDrawElementsBaseVertex可能会为你节省190MB而不是1.9MB。
无论如何,这只是我的推测,因为我也是OpenGL和计算机图形学的初学者。 :)