而不是发布大量代码,我会直观地说出这个问题。我希望你明白我的目标。
我正在制作游戏,在代码中我有一个模型类,它可以加载模型并为它设置VBO。
在加载函数中,它生成一个新的VBO ID,并通过绑定它将文件中的顶点数据加载到该缓冲区中(这样可以正常工作)
在程序开始时,我创建一个模型对象并加载.obj文件。
在渲染功能中,我只需调用DrawArrays()函数(带有必要的额外内容),正如我所说,一切正常,因为模型出现在屏幕上没有任何问题。< / p>
然而问题是,当我在程序开头创建两个模型对象并将不同的.obj文件加载到每个模型对象中时。
问题在于,当我玩时,屏幕上只绘制第二个模型。
问题是因为我没有正确理解VBO的工作原理。
这就是我“思考”VBO工作的方式。
您可以根据需要生成任意数量的VBO ID。 您可以绑定每个ID以使其成为活动缓冲区。 您可以将顶点数据加载到该缓冲区中。 您现在有效地拥有许多不同的ID,每个ID都引用一组“顶点数据”。 通过调用DrawArray函数,它可以绘制您生成的每个缓冲区(在屏幕上有效显示所有模型)
现在我知道这是错的,因为在我有限的理解中,我无法看到如何打开/关闭模型。但无论我看多少教程,我都无法回答这个问题,因为他们都专注于显示第一个VBO ,这是我可以做到的。
所以......如果这是有意义的,有人可以启发我吗?
答案 0 :(得分:8)
你做的大部分是正确的,但绘图命令不绘制你生成的每个缓冲区。如果要使用不同缓冲区中的数据绘制2个对象,则必须发出2个绘图命令。
让我根据我的方式解释:
使用glGenBuffers创建缓冲区。在使用缓冲区之前,必须“绑定”它,即使用glBindBuffer使其处于活动状态。缓冲区处于活动状态时,您可以使用缓冲区(例如填充数据)。请注意,有不同的绑定目标,因此您可以,例如,有一个活动数组缓冲区(用于顶点数据)和一个活动元素数组缓冲区(用于索引数据)。
当你想绘制东西时,你必须指定你想要绘制的内容(我现在假设你正在使用自己的着色器)通常你至少指定你的顶点数据和索引数据。为此,首先将缓冲区与顶点数据绑定(作为数组缓冲区),然后使用属性id调用glVertexAttribPointer。这告诉OpenGL绑定缓冲区现在是当前属性的源。然后,将索引缓冲区绑定为元素数组缓冲区并调用glDrawElements(不确定glDrawArrays如何在这里工作)。
你不能同时为同一个属性使用多个VBO - 绑定另一个缓冲区的调用只会覆盖前一个调用并使第二个缓冲区处于活动状态,我认为这就是为什么只有第二个对象被绘制的原因。
您还可以使用VAO来简化绘图 - 基本上您为绑定命令分配了一个id,然后您可以用一行执行它们(想想显示列表)。
所以,我的(一个对象的)加载看起来像这样:
我的绘画(再次,一个对象):
对于第二个对象,您必须重复所有内容。
答案 1 :(得分:5)
按照以下步骤渲染模型,假设model1顶点存储在vertexBuffer中的vertexBuffer和model2顶点中:
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, <no. of vert>);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer2);
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, <no. of vert>);
//swap buffers depending on your windowing toolkit
确保不要在两个模型渲染的中间执行glClear。 一切顺利!
答案 2 :(得分:0)
你想要做的是在每次调用drawArrays之前将vertexArrayAttribute设置回第一个对象数据
绘制数组函数使用存储在VAO中的绑定来查找渲染所有内容所需的数据
所以为了渲染2个模型,你创建第二个VAO绑定它并根据需要调用glVertexAttribPointer。对于绘图,您绑定VAO并为每个模型调用drawArrays