1

我想直截了当,这就是为什么我从这个场景开始:-

假设您要绘制两个立方体,并假设您已使用两个立方体的数据创建、绑定、填充缓冲区对象,并且您拥有两个立方体的元素数组,如下所示:

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()呢?

4

2 回答 2

4

不。

在代码中:

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

于 2013-09-16T21:16:16.220 回答
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));

我有

在此处输入图像描述

他们是一样的。

事实上,我整天都在想这个问题。

正如本书指出的那样(这里,检查最后一个注释的第二段),(在 32 位操作系统上)如果您的模型包含超过 65536(2 个字节)顶点,则元素数组不能使用 GL_UNSIGNED_SHORT(2 bytes) 不再作为索引的类型。相反,它必须使用 GL_UNSIGNED_INT(4 个字节)。它需要两倍的存储空间。

然后在这里查看 glDrawElementsBaseVertex 的描述。它表示如果 ( indices [i] + basevertex ) 的值超过type的最大值,则该值将被上转换为 32 位无符号整数。

考虑到这些参考资料,我有以下结论:

例如,假设我有一个由 1,000,000 个顶点组成的 3D 角色。如果我使用 glDrawElements 来渲染它,我必须使用 GL_UNSIGNED_INT 来存储索引,这大约需要 3.8MB。但是,如果我可以使用“65536 * numberOfPage + index ”之类的东西(如果我可以在不同的“页面”中分解这些顶点,就像随机访问一样,并使用索引来指示该页面中的顶点;并且 65536 可能是页面大小)与 glDrawElementsBaseVertex,我仍然可以使用 GL_UNSIGNED_SHORT 来存储这些索引。在这种情况下,它将为我节省大约 1.9MB。

也许 1.9MB 听起来不是一个很大的数字,但想想现代 3D 视频游戏的情况。我确信这些字符必须包含超过 1,000,000 个顶点,在这种情况下,glDrawElementsBaseVertex 为您保存的可能是 190MB 而不是 1.9MB。

无论如何,这只是我的猜测,因为我也是 OpenGL 和计算机图形学的初学者。:)

于 2014-11-02T07:21:54.333 回答