我认为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()
等等。
一个简单立方体的任何示例代码?
答案 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:这是列表,它已经在设备上,只需渲染它!