画一个立方体和一个金字塔

时间:2019-02-13 18:45:52

标签: c++ opengl

我正在学习OpenGL,正在使用Qt 5.12。我目前需要绘制一个立方体和一个带有三角形的金字塔。

我认为顶点类和三角形结构都不错,但是不幸的是,并非所有三角形都正确显示。我对OpenGL还是很陌生,所以我可能在VBO / VAO绑定部分中缺少某些内容,但是我不知道是什么。

我创建了一个myVertex类,该类具有6个浮点数:3个表示位置,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();
}

我希望看到这样的数字: Expected

但是现在我看到了: My result

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

1 个答案:

答案 0 :(得分:0)

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

在定义通用顶点属性数据的数组之前,必须通过调用glVertexAttribPointer来绑定顶点规范对象(应将顶点规范存储到该顶点对象)。正确的缓冲对象也必须被绑定:

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