C++删除不可见的面VBO

C++ Remove invisible faces VBO

本文关键字:VBO 删除 C++      更新时间:2023-10-16

我不久前做了一个VBO多维数据集,它工作得很好,但性能不足。如何删除VBO中的不可见面?

我对纹理也有问题,它们似乎被搞砸了:/如果有人知道解决这个问题的方法,那就太好了!

我的代码:

#include <windows.h>
#include <iostream>
#include <glew.h>
#include <GL/gl.h>
#include <GL/glu.h>
#define OFFSET_BUFFER(bytes) ((GLfloat *)NULL + bytes)
PFNGLGENBUFFERSARBPROC glGenBuffers = NULL;
PFNGLBINDBUFFERPROC glBindBuffer = NULL;
PFNGLBUFFERDATAPROC glBufferData = NULL;
GLfloat vertex[];
GLuint m_vertexBuffer;
GLuint m_textureBuffer;
void VBOinit()
{
#ifdef _WIN32
glGenBuffers = (PFNGLGENBUFFERSARBPROC)wglGetProcAddress("glGenBuffers");
glBindBuffer = (PFNGLBINDBUFFERPROC)wglGetProcAddress("glBindBuffer");
glBufferData = (PFNGLBUFFERDATAPROC)wglGetProcAddress("glBufferData");
#else
glGenBuffers = (PFNGLGENBUFFERSARBPROC)glXGetProcAddress((const GLubyte*)"glGenBuffers");
glBindBuffer = (PFNGLBINDBUFFERPROC)glXGetProcAddress((const GLubyte*)"glBindBuffer");
glBufferData = (PFNGLBUFFERDATAPROC)glXGetProcAddress((const GLubyte*)"glBufferData");
#endif
if (!glGenBuffers || !glBindBuffer || !glBufferData)
{
    std::cerr << "VBOs are not supported by your graphics card" << std::endl;
    return;
}
// TEXTURE VBO
GLfloat texture[] =
{
    0, 0,
    1, 0,
    1, 1,
    0, 1,
    0, 0,
    1, 0,
    1, 1,
    0, 1,
    0, 0,
    1, 0,
    1, 1,
    0, 1,
    0, 0,
    1, 0,
    1, 1,
    0, 1,
    0, 0,
    1, 0,
    1, 1,
    0, 1,
    0, 0,
    1, 0,
    1, 1,
    0, 1,
    0, 0,
    1, 0,
    1, 1,
    0, 1,
    0, 0,
    1, 0,
    1, 1,
    0, 1,
    0, 0,
    1, 0,
    1, 1,
    0, 1,
    0, 0,
    1, 0,
    1, 1,
    0, 1
};
glGenBuffers(1, &m_textureBuffer);
glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(texture), &texture, GL_STATIC_DRAW);
// GEOMETRIC VBO
GLfloat vertex[] =
{
    0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f,      // v0-v0.5f-v2 (front)
    -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f,      // v2-v3-v0
    0.5f, 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f,      // v0-v3-v4 (right)
    0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f,      // v4-v5-v0
    0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f,      // v0-v5-v6 (top)
    -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,      // v6-v0.5f-v0
    -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f,      // v0.5f-v6-v7 (left)
    -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f,      // v7-v2-v0.5f
    -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f,      // v7-v4-v3 (bottom)
    0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f,      // v3-v2-v7
    0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f,      // v4-v7-v6 (back)
    -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f     // v6-v5-v4
};
glGenBuffers(1, &m_vertexBuffer); //Generate a buffer for the vertices
glBindBuffer(GL_ARRAY_BUFFER, m_vertexBuffer); //Bind the vertex buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex), &vertex[0], GL_STATIC_DRAW); //Send the data to OpenGL
}
void VBOrender(int x, int y, int z)
{
glBindTexture(GL_TEXTURE_2D, Texture::textures[0]);
glTranslatef(x, y, z);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, m_vertexBuffer);
glVertexPointer(3, GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer);
glTexCoordPointer(2, GL_FLOAT, 0, OFFSET_BUFFER(0));
//glPolygonMode(GL_FRONT, GL_LINE);
glDrawArrays(GL_TRIANGLES, 0, 36);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glTranslatef(-x, -y, -z);
}

感谢阅读:)

在上面的评论中添加了关于我们开始的内容的详细信息,以及其他一些内容。

如前所述,添加glEnable(GL_CULL_FACE)。我怀疑它是否能解决你的瓶颈,但它不会造成伤害。

通常应该做的另一件事是将交错的位置和纹理坐标存储在单个缓冲区中,而不是将它们存储在单独的缓冲区中。同样,我认为你现在在其他地方受到限制,只是一个一般性的建议。

为了说明我在评论中关于避免在循环中设置冗余状态的建议。现在你的伪代码结构是这样的:

loop over x, y, z
    VBOrender(x, y, z)
end loop

相反,我会这样构建它:

VBObind()
loop over x, y, z
    VBOrender(x, y, z)
end loop
VBOunbind()

将当前VBOrender函数中的代码拆分如下:

void VBObind()
{
    glBindTexture(GL_TEXTURE_2D, Texture::textures[0]);
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glBindBuffer(GL_ARRAY_BUFFER, m_vertexBuffer);
    glVertexPointer(3, GL_FLOAT, 0, 0);
    glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer);
    glTexCoordPointer(2, GL_FLOAT, 0, OFFSET_BUFFER(0));
}
void VBOunbind()
{
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
void VBOrender(int x, int y, int z)
{
    glTranslatef(x, y, z);
    glDrawArrays(GL_TRIANGLES, 0, 36);
    glTranslatef(-x, -y, -z);
}

我希望这将给您带来显著的性能改进。为了获得更好的性能,你需要一些更戏剧性的东西,比如在一个draw调用中打包所有的立方体。不过,这看起来有点棘手,因为从你在pastebin上的代码中可以看到,每个立方体的渲染都是有条件的。

如果您愿意编写自己的着色器,可以将平移作为属性,这将比固定函数变换矩阵更新得更快。

您可以通过调用:来打开背面剔除

glFrontFace(GL_CCW); // <- says faces are defined in counter-clockwise order. Change if yours are in clockwise order
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);

至于纹理,看起来您已经为11个立方体面定义了纹理坐标,但您正在绘制36个三角形。36个三角形将是18个四边形,所以我认为你需要更多的纹理坐标。