一个 vbo 中的多个四边形

Multiple quads in one vbo

我正在开发一款类似 minecraft 的游戏,而且我一直在使用 vbos。然而;在单个 vbo 中绘制多张面孔时,我似乎遇到了一些问题。

这是我的 vbo 生成代码:

glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, verts);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, verts * 9 * sizeof(GLfloat), NULL, GL_STATIC_DRAW);
void* ptr = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);

GLfloat*model = (GLfloat*)ptr;
GLfloat*tex = ((GLfloat*)ptr) + verts * 6;
GLfloat*color = ((GLfloat*)ptr) + verts * 3;
int p = 0;
int k = p * 3;

    for (int mcy = 0; mcy < 5; mcy++) {
        for (int mcx = 0; mcx < 5; mcx++) {
        double addonX = mcx*32.0; 
        double addonY = mcy*32.0; 
        int addonx = mcx * 32;
        int addony = mcy * 32;
        if (!(hill.get(addonX, addonY)*400.0 > 100 && hill.get(32 + addonX, addonY)*400.0 > 100 && hill.get(addonX, 32 + addonY)*400.0 > 100 && hill.get(32 + addonX, 32 + addonY)*400.0 > 100)) {
            draw = true;

            int biome1 = BiomeToColor(GetBiome(x, y, addonX, addonY), hill.get(addonX, addonY)*400.0);
            int biome2 = BiomeToColor(GetBiome(x, y, 32 + addonX, addonY), hill.get(32 + addonX, addonY)*400.0);
            int biome3 = BiomeToColor(GetBiome(x, y, addonX, 32 + addonY), hill.get(addonX, 32 + addonY)*400.0);
            int biome4 = BiomeToColor(GetBiome(x, y, 32 + addonX, 32 + addonY), hill.get(32 + addonY, 32 + addonY)*400.0);







            model[k] = addonx+ 32;
            model[k + 1] = addony;
            model[k + 2] = hill.get(addonX + 32, addonY)*400.0;

            color[k] = BiomeColors[biome2].r;
            color[k + 1] = BiomeColors[biome2].g;
            color[k + 2] = BiomeColors[biome2].b;


            p++;
            k = p * 3;



            model[k] = addonx + 32;
            model[k + 1] =  addony + 32;
            model[k + 2] = hill.get(addonX + 32, addonY + 32)*400.0;

            color[k] = BiomeColors[biome4].r;
            color[k + 1] = BiomeColors[biome4].g;
            color[k + 2] = BiomeColors[biome4].b;
            p++;
            k = p * 3;



            model[k] = addonx;
            model[k + 1] = addony + 32;
            model[k + 2] = hill.get(addonX, addonY + 32)*400.0;

            color[k] = BiomeColors[biome3].r;
            color[k + 1] = BiomeColors[biome3].g;
            color[k + 2] = BiomeColors[biome3].b;



            p++;
            k = p * 3;





            model[k] = addony;
            model[k + 1] = addony;
            model[k + 2] = hill.get(addonX, addonY)*400.0;

            color[k] = BiomeColors[biome1].r;
            color[k + 1] = BiomeColors[biome1].g;
            color[k + 2] = BiomeColors[biome1].b;


            p++; 
            k = p * 3;

        }
    }
}
glUnmapBuffer(GL_ARRAY_BUFFER);
glBindBuffer(GL_ARRAY_BUFFER, 0);

这是我用来绘制 vbo 的代码:

glBindBuffer(GL_ARRAY_BUFFER, VBO);

    glVertexPointer(3, GL_FLOAT, 0, 0);
    glTexCoordPointer(3, GL_FLOAT, 0, (char*)NULL + verts * 6 * sizeof(GLfloat));
    glColorPointer(3, GL_FLOAT, 0, (char*)NULL + verts * 3 * sizeof(GLfloat));

    glDrawArrays(GL_QUADS, 0, VBO);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

这是我想要的结果(在每个 vbo 中使用一个四边形):

unfortunatly I'm still new so you have to click this link :/

这是我在每个 vbo 中使用多个四边形得到的结果:

image

那么为什么我要在单个 vbo 中绘制多个四边形? 一个词:性能,如果你比较两个图像,真正突出的东西(嗯,除了第二个图像的错误)是帧率计数器。我想让这个游戏成为一件大事,所以每个 fps 对我来说都很重要。

编辑: 天哪,我太蠢了:

model[k] = addony;

一个非常简单的错误,但却如此令人震惊。 只是证明了这么小的事情是如何阻止比赛的。 现在一切正常。

glDrawArrays(GL_QUADS, 0, VBO);

这个调用有一些问题:

  1. glDrawArrays 的第三个参数是你正在绘制的东西的数量,所以你实际上是在说:

从 0 处的缓冲区绘制四边形直到 VBO,然后停止。

你应该说的是:

从缓冲区中的 0 处绘制四边形直到缓冲区长度,然后停止

所以现在看起来像这样:

glDrawArrays(GL_QUADS, 0, verts);

'VBO' 在您的代码中是您要使用的缓冲区的 ID。 把它想象成一个你知道号码的指针,或者更确切地说是一个有 ID 的用户。

  1. GL_QUADS 不好用 GL_TRIANGLES 有很多问题 GL_QUADS 后来特别是在手机和其他平台上使你的数据在三角形中更好。

你不应该画画 GL_QUADS 有多种原因

你为什么不使用 VAO?您使用的是没有 VAO 的旧版 OpenGL 吗?否则我会建议在这里使用 VAO 而不是 VBO,这样你就不需要为每个绘制调用绑定指针。

glBindBuffer(GL_ARRAY_BUFFER, verts);

您在这里尝试的是将 ID 为 'verts' 的 VBO 绑定为我们当前的 VBO。

'So why do I want to draw multiple quads in a single vbo? One word: performance'

您尝试过使用实例绘制多个四边形吗? 因此,为每个形状发送一个模型矩阵,以便您在着色器中而不是在缓冲区中修改它们的位置和形状。通过这种方式,您可以一遍又一遍地绘制一个 vbo,只需通过一次绘制调用稍作变换即可。

这里有一个很好的实例化教程:

http://learnopengl.com/#!Advanced-OpenGL/Instancing

只是出于好奇,但你为什么决定使用:

glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);

而不是在 glBufferData 调用中缓冲数据?

如果以后需要缓冲数据可以使用glBufferSubData

老实说,我认为您的性能问题源于一系列因素。

我个人会使用 glBufferData 而不是地图数据,当我需要在 运行 期间而不是在加载期间执行时,我会使用 glBufferSubData。

我会将颜色上传到着色器,并使用不同的模型矩阵和颜色一次又一次地绘制多个相同的 VBO,以便我对其进行实例化。

但是您不需要这样做。

我建议的是用三角形和颜色组成数据,并将整个地面绘制为您似乎尝试过的网格。您的问题很可能是由 glDrawArrays 长度设置为 VBO 的长度引起的。

但是在这种情况下,我会使用块大小的 glBufferData 构建一个 VBO,然后我会对每个具有颜色的四边形使用 glBufferSubData 等。完成后,我会在不同的块旁边绘制多次.

我想多了解一些 OpenGL 的理论对你会有用。