Question

I made a VBO cube a while ago, It work's great but it has a lack of performance. How can I remove invisible faces in a VBO?

I also have a problem with the textures, they are seemed to be messed up :/ If anyone knows something to fix that, it would be great!

My code:

#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);
}

Thank you for reading :)

Was it helpful?

Solution

Adding detail on what we started in the comments above, plus a couple more things.

As was previously suggested, add glEnable(GL_CULL_FACE). I doubt that it addresses your bottleneck, but it can't hurt.

One other thing you should generally do is store your positions and texture coordinates interleaved in a single buffer, instead of storing them in separate buffers. Again, I think you're limited elsewhere right now, just a general recommendation.

To illustrate what I suggested in the comment about avoiding to set redundant state inside your loop. Right now your structure in pseudo code looks like this:

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

Instead, I would structure it like this:

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

And split up the code in your current VBOrender function like this:

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);
}

I expect that this will give you a significant performance improvement. To get massively better performance, you would need something more dramatic, like packing all the cubes in a single draw call. This looks slightly tricky, though, because from what I can see in your code on pastebin, the rendering of each cube is conditional.

If you're willing to write your own shaders, you can make the translation an attribute, which would be much faster to update than the fixed function transformation matrix.

OTHER TIPS

You can turn on back-face culling by calling:

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);

As for your textures, it looks like you've defined texture coordinates for 11 cube faces, but you you have 36 triangles you're drawing. 36 triangles would be 18 quads, so I think you need more texture coordinates.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top