【问题标题】:Vertex Buffer Objects - OpenGL顶点缓冲对象 - OpenGL
【发布时间】:2014-07-11 09:52:10
【问题描述】:

我认为 OpenGL(我使用的是 OpenGL 4.0)支持顶点缓冲区对象,这是(如果我错了,请纠正我)一种绘制顶点的动态方式,当您可以释放动态数组时,将它们绑定类似于纹理绑定将其绑定到纹理后的像素数,即使数组中的像素数据丢失,您仍然可以绘制它。 我试图制作一个迷你Minecraft游戏,但在绘制了256x256x60的世界(256宽高和60块深度)之后,游戏完全卡住了。我尝试只绘制 256x256x6,但它仍然不如 Minecraft 运行那么快。 我通过以下方式绘制了一个块:

void DrawBlock(double x, double y, double z, float xx, float yy, float zz)
{
   // Render a color-cube consisting of 6 quads with different colors
    xx = xx / 2;
    yy = yy / 2;
    zz = zz / 2;
    x -= xx;
    y -= yy;
    z -= zz;

    glBegin(GL_QUADS);                // Begin drawing the color cube with 6 quads
      // Top face (y = z + zz)
      // Define vertices in counter-clockwise (CCW) order with normal pointing out
      glColor3f(0.0f, 1.0f, 0.0f);     // Green
      glVertex3f(x + xx, y + yy, z - zz);
      glVertex3f(x - xx, y + yy, z - zz);
      glVertex3f(x - xx, y + yy,  z + zz);
      glVertex3f(x + xx, y + yy,  z + zz);

      // Bottom face (y = z - zz)
      glColor3f(1.0f, 0.5f, 0.0f);    // Orange
      glVertex3f(x + xx, y - yy,  z + zz);
      glVertex3f(x - xx, y - yy,  z + zz);
      glVertex3f(x - xx, y - yy, z - zz);
      glVertex3f(x + xx, y - yy, z - zz);

      // Front face  (z = z + zz)
      glColor3f(1.0f, 0.0f, 0.0f);    // Red
      glVertex3f(x + xx, y + yy, z + zz);
      glVertex3f(x - xx, y + yy, z + zz);
      glVertex3f(x - xx, y - yy, z + zz);
      glVertex3f(x + xx, y - yy, z + zz);

      // Back face (z = z - zz)
     glColor3f(1.0f, 1.0f, 0.0f);    // Yellow
      glVertex3f(x + xx, y - yy, z - zz);
      glVertex3f(x - xx, y - yy, z - zz);
      glVertex3f(x - xx, y + yy, z - zz);
      glVertex3f(x + xx, y + yy, z - zz);

      // Left face (x = z - zz)
      glColor3f(0.0f, 0.0f, 1.0f);    // Blue
      glVertex3f(x - xx, y + yy,  z + zz);
      glVertex3f(x - xx, y + yy, z - zz);
      glVertex3f(x - xx, y - yy, z - zz);
      glVertex3f(x - xx, y - yy,  z + zz);

      // Right face (x = z + zz)
       glColor3f(1.0f, 0.0f, 1.0f);     // Magenta
      glVertex3f(x + xx, y + yy, z - zz);
      glVertex3f(x + xx, y + yy,  z + zz);
      glVertex3f(x + xx, y - yy,  z + zz);
      glVertex3f(x + xx, y - yy, z - zz);
   glEnd();  // End of drawing color-cube
}

当 x、y 和 z 数据位于称为“块”的结构数组中时。 我除了画什么都没做,只是因为画一直卡住, 显示函数在每次运行时总是调用DrawBlock() 256x256x6 或 256x256x60 次。 如何使用 VBO 动态执行此操作? 我查看了互联网,但出现了一些未定义的函数,例如 glGenBuffersARB() 等等。 一个简单立方体的任何示例代码?

【问题讨论】:

  • 看这个问题OpenGL: VBO or glBegin() + glEnd()?。在开始这样的大型项目之前,您真的应该学习 OpenGL 的基本知识。此外,您应该阅读有关体素引擎的信息,因为即使使用 VBO,如果您尝试渲染所有块,也会遇到问题。
  • @t.niese 现在它只是在块之间移动:P
  • 我认为是这样,但这(以快速方式管理和渲染块)是基于块的游戏中的复杂部分之一。 ;) 添加碰撞检测(在方块上行走会更加复杂)。
  • @t.niese 块之间的碰撞检测 - 3 维?不,到目前为止,一切都在少量工作。而且我对如何与 NO 循环发生冲突有一个想法,大约 2-3 个 if 语句:P 无论如何,你有任何使用 VBO 的示例代码吗?
  • 您是否曾经费心按照我的第一条评论中的链接阅读问题及其答案(或在网络上搜索 VBO 教程)?无论如何,我试图给你一个很好的建议,让你首先学习现代 OpenGL (3.2+) 的基础知识,而不仅仅是如何使用 VBO 和寻找体素引擎。

标签: c opengl vbo


【解决方案1】:

如果您在没有任何优化的情况下绘制 256x256x6 块,如果使用上述方式,您将进行 393216 次绘制调用。

Minecraft 正在使用块进行加载和渲染。您应该只用一个绘图调用加载一个块并渲染一个块。意味着一个顶点缓冲区对象拥有一个块。这可以通过大量优化来完成。我已经尝试过类似的方法,并且使用一个渲染调用在一个块中使用 64*64*256 块获得了近 600 FPS。

我已经从硬盘加载了块并且每个块存储了一位(如果不活动,则为 0,如果活动则为 1)然后我处理了块并跳过了不活动的块,以及所有不可见的块(块的所有侧面都被其他块覆盖)。下一个优化是只渲染可见的一面。假设有一个块(2D)

    x
   xB
    x 

B 是你的方块,x 是当前方块周围的其他方块。因此,无需创建所有 4 个(8 个三角形 - 24 个顶点 - 72 个浮点数)边,您只需创建右侧(2 个三角形 - 6 个顶点 - 18 个浮点数)。我将浮点数附加到缓冲区(向量或其他动态数据结构)。 这个数据结构的内容现在被上传到 VBO,然后整个块被立即渲染。还有很多改进,但你只需要减少“网格”/“块”中的顶点数量。

如果你使用更多的块,你还可以添加很多其他的优化,不要渲染不可见或空的块。

然后您可以查看“延迟着色”。这可以提高您的帧速率。使用延迟着色,您只对玩家可见的部分进行着色。不可见的方块(Minecraft 中的隧道,或被山覆盖的方块)没有阴影。

我推荐阅读这篇文章:https://sites.google.com/site/letsmakeavoxelengine/ 还没有完成,但是已经解释了基础知识,作者展示了一些代码,以及更多细节。

我还建议深入了解 VertexBufferObjects 和现代 OpenGL。 (如果您想使用旧的 OpenGL,请查看“显示列表”)

如果没有“显示列表”或“VBO”,每次调用渲染时,三角形都会一次又一次地复制到 GPU - 这非常慢。因此使用 VBO 将它们复制一次,然后告诉 OpenGL:这是列表,它已经在设备上,只需渲染它!

【讨论】:

  • 虽然你的回答确实有帮助,但它没有回答我的问题,你能给我一个使用 VBO 的示例代码吗?最简单的一种。一个立方体。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多