顶点缓冲对象- OpenGL



我认为OpenGL(我使用的是OpenGL 4.0)支持顶点缓冲对象,这是(纠正我,如果我错了)一个动态的方式来绘制顶点,绑定它们类似于纹理绑定时,你可以释放一个动态的像素数组绑定到一个纹理,你仍然能够绘制它,即使在数组中的像素数据丢失。我尝试着创造一款迷你的《我的世界》,但是在绘制了256x256x60的世界(游戏邦注:即256个宽度和高度以及60个方块深度)后,游戏便彻底陷入了困境。我试着只画256x256x6,但它仍然没有快,例如,Minecraft运行。我用下面的方法画了a块:

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数据在一个名为"Block"的结构数组中时。除了画画,我什么也没做,只是因为画画总是卡住,显示函数每次运行时总是调用DrawBlock() 256x256x6或256x256x60次。我如何使用VBO动态地做到这一点?我在网上查了一下,但出现了一些未定义的函数,比如glGenBuffersARB()等等。有一个简单立方体的示例代码吗?

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

Minecraft是使用块加载和渲染。你应该加载一个数据块并渲染一个数据块,只需要一个draw调用。意味着一个顶点缓冲对象保存一个块。这可以通过大量的优化来实现。我也尝试过类似的东西,使用一次渲染调用,在一个64*64*256块的块上获得了近600 FPS。

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

    x
   xB
    x 

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

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

之后,你可以看看"延迟着色"。这可以提高你的帧率。使用延迟着色,你只对玩家可见的部分进行着色。不可见的方块(Minecraft中的隧道或被山覆盖的方块)不会被遮蔽。

我推荐阅读这个:https://sites.google.com/site/letsmakeavoxelengine/它还没有完成,但基本的解释和作者展示了一些代码,以及一些更多的细节。

我还建议深入研究一下VertexBufferObjects和现代OpenGL。(如果你想使用旧的OpenGL,请查看"display lists")

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

最新更新