C++ C++;删除不可见面VBO

C++ C++;删除不可见面VBO,c++,opengl,vbo,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

不久前我制作了一个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);
}
#包括
#包括
#包括
#包括
#包括
#定义偏移量缓冲区(字节)((GLfloat*)NULL+字节)
PFNGLGENBUFFERSARBPROC GLGENBULTS=NULL;
PFNGLBINDBUFFERPROC glBindBuffer=NULL;
PFNGLBUFFERDATAPROC glBufferData=NULL;
GLfloat顶点[];
GLuint m_顶点缓冲区;
胶合木纤维软垫;
void VBOinit()
{
#ifdef_WIN32
glGenBuffers=(PFNGLGENBUFFERSARBPROC)wglGetProcAddress(“glGenBuffers”);
glBindBuffer=(PFNGLBINDBUFFERPROC)wglGetProcAddress(“glBindBuffer”);
glBufferData=(PFNGLBUFFERDATAPROC)wglGetProcAddress(“glBufferData”);
#否则
glGenBuffers=(PFNGLGENBUFFERSARBPROC)glXGetProcAddress((const GLubyte*)“glGenBuffers”);
glBindBuffer=(PFNGLBINDBUFFERPROC)glXGetProcAddress((const GLubyte*)“glBindBuffer”);
glBufferData=(PFNGLBUFFERDATAPROC)glXGetProcAddress((const GLubyte*)“glBufferData”);
#恩迪夫
如果(!glGenBuffers | | |!glBindBuffer | |!glBufferData)
{

std::cerr您可以通过调用以下命令启用背面剔除:

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

glFrontFace(GL_CCW);//添加了我们在上面的评论中开始的内容的细节,以及一些其他内容

如前所述,添加
glEnable(GL\u CULL\u 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()
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);
}
相反,我会这样构造它:

loop over x, y, z
    VBOrender(x, y, z)
end loop
VBObind()
loop over x, y, z
    VBOrender(x, y, z)
end loop
VBOunbind()
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);
}
并在当前的
VBOrender
函数中拆分代码,如下所示:

loop over x, y, z
    VBOrender(x, y, z)
end loop
VBObind()
loop over x, y, z
    VBOrender(x, y, z)
end loop
VBOunbind()
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);
}
我希望这将给您带来显著的性能改进。要获得更高的性能,您需要一些更具戏剧性的东西,例如在一次绘制调用中打包所有多维数据集。不过,这看起来有点棘手,因为从中可以看出,每个多维数据集的渲染都是有条件的


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

如何定义“性能不足”?现代GPU甚至感觉不到一个立方体,它更像是“哈,您注意到什么了吗?”。当渲染16*16*16块时,它给我30+/-fps;渲染32*32*32块给我4 fps,不,我的gpu不错,实际上我有一个好的gpu(2gb NVidia GForce gt440)您的问题不是几何体的数量,而是API调用开销。对于每个多维数据集,您执行对
glDrawArrays
的调用;正是这些调用降低了性能。尝试在单个
glDrawArrays
调用中批处理更多几何体。在现代GPU上,当单个
glDrawArrays
调用会导致至少绘制约200个三角形。如果你能将1000多个三角形放入其中,事情就会变得很好。在你的情况下,你可以使用实例化来绘制所有立方体,只需一个
glDraw…
调用。我怎么做?我对VBO是新手:)但是在VBO中删除面如何工作?仍然没有弄清楚。你不知道从VBO中删除面。最好的方法是从传递给
glDrawElements
的索引列表中删除面(而不是
glDrawArrays
)。许多新手将OpenGL与场景图混淆,即跟踪几何体的系统。但这不是OpenGL的工作方式。OpenGL是一种绘图API,它将点、线和三角形绘制到帧缓冲区,一次绘制一个点、线或三角形。绘制一个场景图时,它已经忘记了它。这就是为什么OpenGL不做隐藏曲面之类的事情删除。它为您提供了深度测试和背面剔除,但仍然可以处理所有内容。谢谢,我会尝试:)好的,还有另一个选项,删除面。(删除一些顶点指针)但是idk how:/Edit:抱歉,这是我的块数组。但是我如何“删除面”任何人都知道如何通过删除顶点数组的部分来“删除面”。或者排除它们?