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