gpt4 book ai didi

opengl - 是否可以将索引缓冲区对象 (IBO) 与功能 'glMultiDrawElements' 一起使用?

转载 作者:行者123 更新时间:2023-12-01 08:58:21 31 4
gpt4 key购买 nike

我使用 OpenGL 和 GLSL 开发了一个小型 3D 引擎。

我已经合并了一个顶点数据批处理系统,其目标是收集所有几何图形(所有对象)共享相同的着色器程序和相同的变换在一个唯一的顶点缓冲区对象(VBO)中,从而最大限度地减少状态更改(绑定(bind))和绘制调用也。

我目前使用函数“glMultiDrawElements”来渲染特定批处理的数据(因此是一次绘制调用)。因此,例如,如果我的批处理中有 3 个网格,我也有 3 个索引数组(每个网格一个),它们组织在一个“GLvoid **”数组(一个双数组)中。所以要渲染我的 3 个网格,我有一个独特的 glMultiDrawElements 调用,但我必须直接将参数中的 double 数组传递给函数。

但我想知道(对于性能问题)是否可以将所有元素(元素的双数组)存储在索引缓冲区对象(IBO)中(就像可以使用 glDrawElements -> 这里是一个简单的元素数组)并在 glMultiDrawElements 调用之前绑定(bind)它......我不这么认为,因为它是一个双数组而不是一个简单的数组,但也许(我希望如此)我错了。

这是一个使用 glDrawElements 的示例(伪代码):

[...]

//Setup data

[...]

#define OFFSET_BUFFER(offset) ((char*)NULL + offset)

foreach (pMeshGeometry from meshes) //iterates for each mesh of the scene
{
pMeshGeometry->GetIndexBuffer().Lock(); //Bind IBO
{
glDrawElements(pMeshGeometry->GetPrimitiveType(),
pMeshGeometry->GetIndexBufferSize(), pMeshGeometry->GetIndexBuffer().GetType(), OFFSET_BUFFER(0)); //Render a specific mesh eccording to indices
}
}

目前我以这种方式使用 glMultiDrawElement :
glMultiDrawElements(GL_TRIANGLES, &this->m_CountElementArray[0], GL_UNSIGNED_INT,
(const GLvoid **)&this->m_IndexAttribArray[0], this->m_CountElementArray.size()); //I enter the array of pointer directly in parameter

所以,也许下面的例子应该是可能的:
#define OFFSET_BUFFER(offset) ((char**)NULL + offset) //Something like this

glMultiDrawElements(GL_TRIANGLES, &this->m_CountElementArray[0], GL_UNSIGNED_INT,
OFFSET_BUFFER(0), this->m_CountElementArray.size()); //Something like this

所以如果不可能做到这一点,我想到了函数'glDrawRangeElements'。对于我将 3 个网格放入唯一 VBO 的示例,我只需要在每个 glDrawRangeElements 调用之前绑定(bind)一个 IBO(这里,每个网格有 3 个绘制调用 -> 所以是一个 glDrawRangeElements 循环)。所以这里显然可以使用 IBO。

这种方法肯定会奏效,但我认为这不是最好的方法!我认为可以使用带有 IBO 的 glMultiDrawElements 来做到这一点,但我不知道该怎么做。

或者,这真的是不可能的。也许在参数中直接输入索引数组的事实比使用 glDrawRangeElements 及其 IBO 的方法更快,因此在这种情况下使用 IBO 可能已被弃用,因此不适用。

你对那个怎么想的 ?

最佳答案

您当然可以将索引缓冲区与 glMultiDrawElements() 一起使用。 .客户端索引数组在 OpenGL 核心配置文件中已弃用。所以如果 glMultiDrawElements()无法使用索引缓冲区操作,将无法再使用它。
要了解它是如何工作的,我们需要查看 glMultiDrawElements() 的参数。意思是。调用基本上只是多个glDrawElements()的快捷方式来电。签名是:

void glMultiDrawElements(GLenum mode, const GLsizei* count, GLenum type,  
const GLvoid** indices, GLsizei primcount);
除了一些错误检查细节之外,这个调用相当于:
for (int i = 0; i < primcount; ++i) {
glDrawElements(mode, count[i], type, indices[i]);
}
现在请记住,如果绑定(bind)了索引缓冲区, glDrawElements() 的最后一个参数是缓冲区的相对偏移量。所以 glMultiDrawElements()对应的第4个元素是 偏移数组 进入缓冲区。第二个参数是一个匹配的计数数组。
人们经常使用宏来隐藏 glDrawElements()最后一个参数的繁琐类型转换。 .使用这个:
#define BUFFER_OFFSET(offset) (static_cast<char*>(0) + (offset))
例如,假设我们有一个索引缓冲区绑定(bind),并且我们想通过一次调用绘制索引数组的 3 个子范围:
  • 从缓冲区中的索引 10 开始的 20 个索引。
  • 从缓冲区中的索引 40 开始的 30 个索引。
  • 从缓冲区中的索引 90 开始的 10 个索引。

  • 我将使用无符号短裤 (GLushort) 作为索引类型。因此,索引缓冲区将使用来自 GLushort indexA[100] 的数据填充。在过去的某个时候。设置和绘制调用如下所示:
    GLsizei count[3] = {20, 30, 10};
    GLvoid* indices[3] = {
    BUFFER_OFFSET(10 * sizeof(GLushort)),
    BUFFER_OFFSET(40 * sizeof(GLushort)),
    BUFFER_OFFSET(90 * sizeof(GLushort)),
    };
    glMultiDrawElements(GL_TRIANGLE_STRIP, count, GL_UNSIGNED_SHORT, indices, 3);

    关于opengl - 是否可以将索引缓冲区对象 (IBO) 与功能 'glMultiDrawElements' 一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24516993/

    31 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com