一个 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);
这个调用有一些问题:
- glDrawArrays 的第三个参数是你正在绘制的东西的数量,所以你实际上是在说:
从 0 处的缓冲区绘制四边形直到 VBO,然后停止。
你应该说的是:
从缓冲区中的 0 处绘制四边形直到缓冲区长度,然后停止
所以现在看起来像这样:
glDrawArrays(GL_QUADS, 0, verts);
'VBO' 在您的代码中是您要使用的缓冲区的 ID。
把它想象成一个你知道号码的指针,或者更确切地说是一个有 ID 的用户。
- 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 的理论对你会有用。
我正在开发一款类似 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);
这个调用有一些问题:
- glDrawArrays 的第三个参数是你正在绘制的东西的数量,所以你实际上是在说:
从 0 处的缓冲区绘制四边形直到 VBO,然后停止。
你应该说的是:
从缓冲区中的 0 处绘制四边形直到缓冲区长度,然后停止
所以现在看起来像这样:
glDrawArrays(GL_QUADS, 0, verts);
'VBO' 在您的代码中是您要使用的缓冲区的 ID。 把它想象成一个你知道号码的指针,或者更确切地说是一个有 ID 的用户。
- 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 的理论对你会有用。