顶点缓冲区对象 - OpenGL

时间:2014-07-11 09:52:10

标签: c opengl vbo

我认为OpenGL(我正在使用OpenGL 4.0)支持顶点缓冲对象,这是一个动态的方法来绘制顶点(当我错了时纠正我),绑定它们类似于纹理绑定,当你可以释放动态数组时将它绑定到纹理后的像素数,即使数组中的像素数据丢失,您仍然可以绘制它。 我试图制作一个迷你魔兽世界游戏,但在绘制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数据位于名为“Block”的结构数组中时。 我仍然没有做任何事情,只是绘图,只是因为绘图一直卡住, 显示功能在每次运行时始终调用DrawBlock() 256x256x6或256x256x60次。 如何使用VBO动态执行此操作? 我查看了互联网,但是一些未定义的函数看起来像glGenBuffersARB()等等。 一个简单立方体的任何示例代码?

1 个答案:

答案 0 :(得分:0)

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

Minecraft正在使用块来加载和渲染。你应该加载一个块并在一个只有一个绘制调用的情况下渲染一个块。意味着一个顶点缓冲区对象包含一个块。这可以通过大量优化来完成。我尝试了类似的东西,并在一个块上使用一个渲染调用64 * 64 * 256块获得了近600 FPS。

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

    x
   xB
    x 

B是你阻止,x是当前的其他块。因此,不是创建所有4个(8个三角形 - 24个Verts - 72个浮点数),而是创建右侧(2个三角形 - 6个Verts - 18个浮点数)。我将浮点数附加到缓冲区(向量或其他动态数据结构)。 此数据结构的内容现在上传到VBO,稍后立即呈现整个块。还有很多改进,但你必须减少“网格”/“块”中的顶点数量。

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

之后你可以看看“Deferred Shading”。这可以提高您的帧速率。使用延迟着色,您只需遮蔽播放器可见的内容。不可见的块(Minecraft中的隧道,或山峰覆盖的块)没有阴影。

我建议阅读:https://sites.google.com/site/letsmakeavoxelengine/尚未完成,但解释了基础知识,作者展示了一些代码,以及更多细节。

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

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