当前位置: 首页 > 知识库问答 >
问题:

如何在体素引擎中正确使用VAO和VBO

仇睿
2023-03-14

我目前正在构建一个体素引擎(比如Minecraft),我正在使用opengl。

发动机的当前设计如下所示:

班级地图-

类块-

类块-

我想做的是让每个块都有一个Draw()函数,它将绘制块中的所有块。我想我应该使用glGenBuffers()为每个块创建一个缓冲区。从我读的教程应该首先创建一个顶点数组与glVertex Array和比绑定它,比绑定一个缓冲区,它与目标GL_ARRAY_BUFFER和填充它的数据。

到目前为止,我设法渲染了一个单一的块,其中使用了一个缓冲区,该缓冲区在块中创建了glGenBuffers(),但在主函数中,我创建了glVertex Array并将其绑定,而不是在块中调用Draw()函数,并将其绑定到块中使用glDrawArray()进行缓冲区和绘图。

我的问题是,为每个块创建VBO是正确的吗?我还需要为每个块创建一个glVertexArray?或者我应该对所有块使用一个,每次绑定另一个VBO?

我试图通过教程和opengl维基学习更多关于VAO和VBO的知识,但到目前为止,我还没有完全理解它是如何工作的,以及它应该如何正确使用。

共有2个答案

裴宏壮
2023-03-14

我知道我很晚了,但如果将来有人发现这个问题,我会把答案放在这里。

Minecraft的工作方式与人们想象的不同。与上面描述的使用嵌套缓冲区的系统不同,块可以只使用整数数组(如果块类型少于256,则使用无符号字符)。如果块数组中出现块的“ID”,则可以使用每种类型的一个块,然后在特定位置对其进行渲染,而不是使用多个html" target="_blank">对象来表示块。

它可以是一个3D数组(在你的例子中,也可以是向量向量向量,但这不是很有效),也可以是一个1D数组,可以通过宽度、高度和深度进行访问。每个ID(整数或无符号字符)将链接到一个块类型。因此,当您想要渲染块时,您可以遍历块的所有维度-宽度、高度、深度-并查看该点的ID。如果为3,则渲染一块污垢,如果为1,则将其设置为草块,如果为0,则将其设置为空气块等。此系统非常适合塑造和生成地形,因为您只需操纵一个整数阵列。如果您按照密度的顺序排列块,那么您可以对块的区域执行一些算术来塑造地形(例如,从块的该区域的所有ID中减去一个),并且所有块类型都会发生变化。

这将通过实例化来完成,这样您就可以在一块中有一个污垢块,并在需要的地方多次渲染它。在某种程度上,甚至可以用制服来改变街区的位置,一个接一个地渲染。

要回答您的问题,您需要一个VBO来定义块的位置数据和纹理坐标。还有一个VAO,用于存储数据在内存中的排列方式。但是在这之后,您可以在渲染每个块之前绑定不同的纹理,具体取决于块中块数组中的ID。加载时,根据块的大小,将块中污垢块的所有位置分组,并绑定一次纹理,然后在一个块中渲染所有污垢块(因为纹理绑定调用太频繁可能会导致性能问题)。

周和歌
2023-03-14

我想你可能想得太早了。为什么你的地图被分成几块?您是否期望在并非所有映射都在内存中的情况下进行某种分页?如果您的整个地图适合GPU内存,则每个地图使用一个缓冲区,并且不需要块。首先让你的渲染像那样漂亮。

之后,您可以考虑优化,例如仅绘制可见零件。或以较低的细节绘制远处的零件。在这一点上,您决定如何保留GPU缓冲区,何时更新或丢弃它们。这只是一个缓存问题。这不是一个简单的问题,但是缓存问题。

更实际的是:如果你组织成块,是的,每个块有一个缓冲区。一个顶点和一个索引缓冲区。一次画一张。切换缓冲区对于绘图来说并不坏。但是,当您加载缓冲区时,您希望加载整个内容,而不是部分。不要使用低于65k顶点的缓冲区。

作为第一步,只需从CPU内存中提取。一旦你对事情的发展有了更好的了解,缓存就会随之产生。不要过早地将GPU结构混合到您的设计中。您还需要CPU结构来处理拾取或AI之类的事情。您应该有一个“基本事实”数据集,然后根据不同的需要使用不同的分区和表示。

 类似资料:
  • 我正在使用斯坦福大学的openNLP引擎在30000个文档集合中查找名词,在这样做的同时,我在java中遇到了OutofMemory错误,尽管我在文档的特定部分中检测到了所有名词,这意味着我只将一部分文本传递给openNLP中的MaxentTagger,我应该如何纠正这个错误?

  • 问题内容: 从官方教程中: 在卸载和销毁组件之前立即调用。使用此方法执行任何必要的清除,例如使计时器无效,取消网络请求或清除在其中创建的所有DOM元素。 我了解“使计时器无效”。可以用终止。但是我不理解“清理在中创建的任何DOM元素”,我可以看到这种情况的示例吗? 问题答案: 如果网络请求发送库支持中止正在进行的网络请求调用,则绝对可以在方法中调用该请求。 但是,与清理元素有关。根据目前的经验,我

  • 问题内容: 我一直在尝试在Node.js中调用D3。我首先尝试使用脚本标签从D3的网站导入d3.v2.js D3的作者建议一个人应该“ npm install d3” …我做到了,我可以在节点控制台中成功调用它: 但是,当尝试使用“ node app.js”从app.js调用它时,我得到: 我意识到,D3的作者在其他地方已经明确规定了应该使用画布: https://github.com/mbost

  • 问题内容: 我试图通过以下方式将多维度Javascript数组传递到网站上的另一页: 在数组上使用JSON.stringify 将结果值分配给输入字段 将该字段发布到第二页 在发布的值上使用json_decode 然后使用var_dump进行测试 (直接回显已发布的变量只是看它是否通过了) 第一页的Javascript: 第二页的php: 回声工作正常,但var_dump返回NULL 我做错了什么

  • 我试图在OpenGL中使用多个VAO和VBO渲染多个对象。使用相同的顶点渲染多个对象我已经做过了,但是我想做的是为每个对象使用不同的顶点,例如画一个正方形和一个圆形。对于一个正方形,我只需要6个顶点,但是对于圆,我需要360个顶点。我有阅读或创建着色器的错误。 以下是顶点着色器: 片段着色器: VAO和VBO的生成与绑定 以及渲染循环中的绘制调用: 我重复一遍,用我做过的相同顶点绘制多个对象。我需

  • 引擎配置 支持的数据库 数据库URL 《PostgreSQL》 MySQL 甲骨文公司 Microsoft SQL服务器 SQLite 其他 引擎创建API 池化 自定义DBAPI connect()参数/on connect例程 传递给的特殊关键字参数数据库接口() 控制如何将参数传递给DBAPI connect()函数 在连接后修改DBAPI连接,或在连接后运行命令 完全替换DBAPI con