C ++删除隐形面VBO

时间:2014-04-19 14:13:20

标签: c++ opengl vbo

我不久前制作了一个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);
}

感谢您阅读:)

2 个答案:

答案 0 :(得分:0)

您可以致电:

打开背面剔除
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个四边形,所以我认为你需要更多的纹理坐标。

答案 1 :(得分:0)

在上面的评论中添加我们开始的内容的详细信息,以及更多内容。

如前所述,添加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);
}

我希望这会给您带来显着的性能提升。为了获得更好的性能,您需要更具戏剧性的东西,比如在一次绘制调用中打包所有多维数据集。但这看起来有点棘手,因为从your code on pastebin中我可以看到,每个立方体的渲染都是有条件的。

如果您愿意编写自己的着色器,则可以使转换成为一个属性,更新比固定函数转换矩阵快得多。