画一个立方体和金字塔

Draw a cube and a pyramid

本文关键字:立方体 金字塔 一个      更新时间:2023-10-16

我正在学习OpenGL,并且正在使用QT 5.12。我目前需要画一个带有三角形的金字塔。

我认为顶点类和三角形结构很好,但不幸的是,并非所有三角形都正确显示。我仍然是OpenGL的新手,所以我可能在VBO/VAO绑定部分中缺少一些东西,但我不知道什么。

我已经创建了一个带有6个浮子的Mervertex类:3用于颜色:

class myVertex{
public:
    GLfloat _x;
    GLfloat _y;
    GLfloat _z;
    GLfloat _r;
    GLfloat _g;
    GLfloat _b;
    myVertex(GLfloat x, GLfloat y, GLfloat z, GLfloat r, GLfloat g, GLfloat b){
        _x=x;
        _y=y;
        _z=z;
        _r=r;
        _g=g;
        _b=b;
    }
};

然后我定义了三角形的结构:

struct triangle {
    myVertex a;
    myVertex b;
    myVertex c;
};

在mainview :: initializegl()中,我在每个顶点的3D中定义颜色和位置,然后构建三角形:

// Cube
    myVertex CUBE_LEFT_FRONT_DOWN  = myVertex(-1.0f,-1.0f,-1.0f,1.0f,0.0f,0.0f);
    myVertex CUBE_RIGHT_FRONT_DOWN = myVertex( 1.0f,-1.0f,-1.0f,0.0f,1.0f,0.0f);
    myVertex CUBE_LEFT_BACK_DOWN   = myVertex(-1.0f, 1.0f,-1.0f,0.0f,0.0f,1.0f);
    myVertex CUBE_RIGHT_BACK_DOWN  = myVertex( 1.0f, 1.0f,-1.0f,1.0f,1.0f,0.0f);
    myVertex CUBE_LEFT_FRONT_UP    = myVertex(-1.0f,-1.0f, 1.0f,1.0f,0.0f,1.0f);
    myVertex CUBE_RIGHT_FRONT_UP   = myVertex( 1.0f,-1.0f, 1.0f,0.0f,1.0f,1.0f);
    myVertex CUBE_LEFT_BACK_UP     = myVertex(-1.0f, 1.0f, 1.0f,0.2f,0.5f,0.7f);
    myVertex CUBE_RIGHT_BACK_UP    = myVertex( 1.0f, 1.0f, 1.0f,0.7f,0.2f,0.5f);

    // Every face is made of 2 triangles
    triangle left1  = {CUBE_LEFT_BACK_DOWN,  CUBE_LEFT_FRONT_DOWN,  CUBE_LEFT_BACK_UP};
    triangle left2  = {CUBE_LEFT_FRONT_UP,   CUBE_LEFT_FRONT_DOWN,  CUBE_LEFT_BACK_UP};
    triangle right1 = {CUBE_RIGHT_BACK_DOWN, CUBE_RIGHT_BACK_UP,    CUBE_RIGHT_FRONT_DOWN};
    triangle right2 = {CUBE_RIGHT_FRONT_UP,  CUBE_RIGHT_BACK_UP,    CUBE_RIGHT_FRONT_DOWN};
    triangle back1  = {CUBE_LEFT_BACK_DOWN,  CUBE_RIGHT_BACK_DOWN,  CUBE_LEFT_BACK_UP};
    triangle back2  = {CUBE_RIGHT_BACK_UP,   CUBE_RIGHT_BACK_DOWN,  CUBE_LEFT_BACK_UP};
    triangle front1 = {CUBE_LEFT_FRONT_DOWN, CUBE_RIGHT_FRONT_DOWN, CUBE_LEFT_FRONT_UP};
    triangle front2 = {CUBE_RIGHT_FRONT_UP,  CUBE_RIGHT_FRONT_DOWN, CUBE_LEFT_FRONT_UP};
    triangle down1  = {CUBE_LEFT_FRONT_DOWN, CUBE_RIGHT_FRONT_DOWN, CUBE_LEFT_BACK_DOWN};
    triangle down2  = {CUBE_RIGHT_BACK_DOWN, CUBE_RIGHT_FRONT_DOWN, CUBE_LEFT_BACK_DOWN};
    triangle up1    = {CUBE_RIGHT_BACK_UP,   CUBE_RIGHT_FRONT_UP,   CUBE_LEFT_BACK_UP};
    triangle up2    = {CUBE_LEFT_FRONT_UP,   CUBE_RIGHT_FRONT_UP,   CUBE_LEFT_BACK_UP};
    triangle cube[] = {left1, left2, right1, right2, back1, back2, front1, front2, down1, down2, up1, up2};

// Pyramid
    myVertex PYR_LEFT_FRONT  = myVertex(-1.0f,-1.0f,-1.0f,0.0f,1.0f,0.0f);
    myVertex PYR_RIGHT_FRONT = myVertex( 1.0f,-1.0f,-1.0f,0.0f,0.0f,1.0f);
    myVertex PYR_LEFT_BACK   = myVertex(-1.0f, 1.0f,-1.0f,1.0f,0.0f,0.0f);
    myVertex PYR_RIGHT_BACK  = myVertex( 1.0f, 1.0f,-1.0f,0.5f,0.8f,0.0f);
    myVertex PYR_TOP         = myVertex( 0.0f, 0.0f, 1.0f,0.3f,0.1f,0.4f);

// Base need 2 triangles
    triangle leftside  = {PYR_LEFT_FRONT,  PYR_LEFT_BACK,   PYR_TOP};
    triangle rightside = {PYR_RIGHT_FRONT, PYR_RIGHT_BACK,  PYR_TOP};
    triangle frontside = {PYR_LEFT_FRONT,  PYR_RIGHT_FRONT, PYR_TOP};
    triangle backside  = {PYR_LEFT_BACK,   PYR_RIGHT_BACK,  PYR_TOP};
    triangle base1     = {PYR_LEFT_FRONT,  PYR_LEFT_BACK,   PYR_RIGHT_FRONT};
    triangle base2     = {PYR_RIGHT_BACK,  PYR_LEFT_BACK,   PYR_RIGHT_FRONT};
    triangle pyramid[] = {leftside, rightside, frontside, backside, base1, base2};

现在我定义了VBO和VAO,启用属性等:

GLuint cubeVBO;
GLuint cubeVAO;
GLuint pyrVBO;
GLuint pyrVAO;
glGenBuffers(1, &cubeVBO);
glGenVertexArrays(1, &cubeVAO);
glBindVertexArray(cubeVAO);
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(cube), cube, GL_STATIC_DRAW);
glGenBuffers(1, &pyrVBO);
glGenVertexArrays(1, &pyrVAO);
glBindVertexArray(pyrVAO);
glBindBuffer(GL_ARRAY_BUFFER, pyrVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(pyramid), pyramid, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof(myVertex),(void *)0);
glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,sizeof(myVertex),(void *)(3*sizeof(GLfloat)));

最后我画在屏幕上:

MainView::paintGL() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    shaderProgram.bind();
    glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
    glDrawArrays(GL_TRIANGLES,0,36);
    glBindBuffer(GL_ARRAY_BUFFER, pyrVBO);
    glDrawArrays(GL_TRIANGLES,0,18);

    shaderProgram.release();
}

我希望看到这样的数字:预期

但是现在我看到了:我的结果

我多次审查了代码,但我不明白出了什么问题。

如果命名的非零数组缓冲区对象是绑定的,则glVertexAttribPointer的最后一个参数被视为字节偏移到缓冲区的数据存储中。
通用顶点属性数据的定义和引用的缓冲区的名称在顶点数组对象状态向量中。

通过glVertexAttribPointer的调用定义了通用顶点属性数据的数组,即Vertex数组对象的呼叫,该对象应将其存储到其中,必须绑定到顶点规范。适当的缓冲对象也必须绑定:

// vertex array buffer for cube
GLuint cubeVBO;
glGenBuffers(1, &cubeVBO);
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(cube), cube, GL_STATIC_DRAW);
// vertex array buffer for pyramid
GLuint pyrVBO;
glGenBuffers(1, &pyrVBO);
glBindBuffer(GL_ARRAY_BUFFER, pyrVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(pyramid), pyramid, GL_STATIC_DRAW);
// vertex array object for cube
GLuint cubeVAO;
glGenVertexArrays(1, &cubeVAO);
glBindVertexArray(cubeVAO);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof(myVertex),(void *)0);
glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,sizeof(myVertex),(void *)(3*sizeof(GLfloat)));
// vertex array object for pyramid
GLuint pyrVAO;
glGenVertexArrays(1, &pyrVAO);
glBindVertexArray(pyrVAO);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, pyrVBO);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof(myVertex),(void *)0);
glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,sizeof(myVertex),(void *)(3*sizeof(GLfloat)));