glDrawElements 只绘制顶点缓冲对象的第一个Triangle

问题描述 投票:0回答:1

我正在尝试回到 OpenGL,自从我上次使用它以来,很多事情都发生了变化。不过,我尝试编写一个小型 3D 程序。现在程序应该显示两个基本的旋转立方体。

我的问题是,该程序只显示每个立方体一个三角形。看起来从VBO 中只读取了一个三角形。 我的第一次调试是围绕数据本身进行的,也许我弄乱了三角形或索引,但对我来说这看起来不错(还尝试了其他几个 OpenGL 教程中的顶点和索引列表)。 我还打乱了OpenGL函数的顺序,也许它们的顺序有问题。 但没有任何帮助,输出仍然只是每个立方体一个三角形。

The output of my program, clearly no cubes...

该程序当前由一个“引擎”组成,它处理窗口和基本 OpenGL 设置以及主渲染循环:

int my3DEngine::Run() {
    int return_value = ENGINE_OK;

    // Camera matrix
    glm::mat4 View = glm::lookAt(
        glm::vec3(4, 3, 3), // Camera is at (4,3,3), in World Space
        glm::vec3(0, 0, 0), // and looks at the origin
        glm::vec3(0, 1, 0)  // Head is up (set to 0,-1,0 to look upside-down)
    );

    do {

        // Clear the screen
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
       // glClearColor(m_color_R, m_color_G, m_color_B, m_color_A);

        //draw object list
        for (std::size_t i = 0; i < m_objects.size(); i++) {
            m_objects[i]->update();
            m_objects[i]->draw(m_projection, View);
        }

        // Swap buffers
        glfwSwapBuffers(m_window);
        glfwPollEvents();

    } // Check if the ESC key was pressed or the window was closed
    while (!glfwWindowShouldClose(m_window));

    return return_value;
}

正如你所看到的,还有对象。该对象初始化如下:

...

float vertices[] = {
//positions          //colors
-1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f,  // 0. left bottom back
 1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 0.0f,  // 1. right bottom back
 1.0f,  1.0f, -1.0f, 0.0f, 0.0f, 1.0f,  // 2. right top back
-1.0f,  1.0f, -1.0f, 1.0f, 1.0f, 0.0f,  // 3. left top back
-1.0f, -1.0f,  1.0f, 1.0f, 0.0f, 0.0f,  // 4. left bottom front
 1.0f, -1.0f,  1.0f, 0.0f, 1.0f, 0.0f,  // 5. right bottom front
 1.0f,  1.0f,  1.0f, 0.0f, 0.0f, 1.0f,  // 6. right top front
-1.0f,  1.0f,  1.0f, 1.0f, 1.0f, 0.0f  // 7. left top front
};

// Vertex index list
unsigned int indices[] = {
    0, 1, 2,  // triangle 1 (back face)
    2, 3, 0,  // triangle 2 (back face)
    4, 5, 6,  // triangle 3 (front face)
    6, 7, 4,  // triangle 4 (front face)
    3, 2, 6,  // triangle 5 (top face)
    6, 7, 3,  // triangle 6 (top face)
    1, 0, 4,  // triangle 7 (bottom face)
    4, 5, 1,  // triangle 8 (bottom face)
    0, 3, 7,  // triangle 9 (left face)
    7, 4, 0,  // triangle 10 (left face)
    1, 5, 6,  // triangle 11 (right face)
    6, 2, 1   // triangle 12 (right face)
};

    if (engine->Init() == ENGINE_OK) {

        // Open a window and create its OpenGL context
        if (engine->CreateMainWindow(1024, 768, "test", "data/icon/test.png", true, false) == ENGINE_OK) {

            obj->addShader(engine->LoadShaders("shaders/vertex.sh", "shaders/fragment_red.sh"));
            obj->addVertexData(vertices, g_vertex_indices_data, sizeof(vertices), sizeof(indices), sizeof(vertices)/sizeof(GLfloat)/6, sizeof(indices)/sizeof(GLuint), GL_TRIANGLES);
            obj->setRotationSpeed(glm::vec3(0.002, 0.002f, 0.002f));
            obj->setPos(glm::vec3(0.0f,0.0f,-2.1f));

            obj_2->addShader(engine->LoadShaders("shaders/vertex.sh", "shaders/fragment.sh"));
            obj_2->addVertexData(vertices, g_vertex_indices_data, sizeof(vertices), sizeof(indices), sizeof(vertices) / sizeof(GLfloat) / 6, sizeof(indices) / sizeof(GLuint), GL_TRIANGLES);
            obj_2->setRotationSpeed(glm::vec3(-0.002, -0.002f, -0.002f));

            engine->addObject(obj);
            engine->addObject(obj_2);
            engine->setBackgrundColor(0.0f, 0.0f, 0.4f, 0.0f);

            engine->Run();
        }
        else {
            return_value = ENGINE_FATAL_ERROR;
            std::cerr << "Unable to create the window!" << std::endl;
        }
    }
    else {
        return_value = ENGINE_FATAL_ERROR;
        std::cerr << "Unable to initialize the engine!" << std::endl;
    }

我认为最有趣的函数是对象顶点设置函数及其绘制函数:

void my3DEngineObject::addVertexData(const GLfloat vertex_data[], const GLuint vertex_indices[], const size_t vertex_data_size, const size_t vertex_indices_size, int nr_vertices, int nr_indices, GLenum mode) {
    m_vertex_data_size = vertex_data_size;
    m_vertex_index_size = vertex_indices_size;
    
    m_vertex_data = new GLfloat[m_vertex_data_size];
    m_vertex_index_data = new GLuint[vertex_indices_size];
    memcpy(m_vertex_data, vertex_data, m_vertex_data_size);
    memcpy(m_vertex_index_data, vertex_indices, m_vertex_index_size);
    m_nr_vertices = nr_vertices;
    m_nr_indices = nr_indices;
    m_mode = mode;
    
    glGenVertexArrays(1, &m_vertexArray);
    glGenBuffers(1, &m_vertexbuffer);
    glGenBuffers(1, &m_indexbuffer);
    glBindVertexArray(m_vertexArray);

    // bind and fill the vertex buffer
    glBindBuffer(GL_ARRAY_BUFFER, m_vertexbuffer);
    glBufferData(GL_ARRAY_BUFFER, m_vertex_data_size, m_vertex_data, GL_STATIC_DRAW);
    //bind and fill the indices buffer
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexbuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_vertex_index_size, m_vertex_index_data, GL_STATIC_DRAW);
}

void my3DEngineObject::addShader(GLuint id) {
    m_shaderID = id;
    m_shader_MVP_handle = glGetUniformLocation(m_shaderID, "MVP");
}

void my3DEngineObject::update() {
    m_angle_radians += m_rot_speed;
    m_pos += m_trans_speed;
}

void my3DEngineObject::draw(glm::mat4 projection, glm::mat4 view) {
    //rotate around its own center
    
    //m_rotationMatrix_X = glm::rotate(glm::mat4(1.0f), glm::radians(m_rot_speed.x), glm::vec3(1.0f, 0.0f, 0.0f));
    //m_rotationMatrix_Y = glm::rotate(glm::mat4(1.0f), glm::radians(m_rot_speed.y), glm::vec3(0.0f, 1.0f, 0.0f));
    //m_rotationMatrix_Z = glm::rotate(glm::mat4(1.0f), glm::radians(m_rot_speed.z), glm::vec3(0.0f, 0.0f, 1.0f));

    m_modelMatrix = m_identity_matrix;

    m_translationMatrix = glm::translate(glm::mat4(1.0f), glm::vec3(m_pos.x, m_pos.y, m_pos.z)); //position the object in world space
    m_modelMatrix = m_modelMatrix * m_translationMatrix;

    m_rotationMatrix_X = glm::rotate(glm::mat4(1.0f), m_angle_radians.x, glm::vec3(1.0f, 0.0f, 0.0f)); //rotate the object around its centerpoint
    m_rotationMatrix_Y = glm::rotate(glm::mat4(1.0f), m_angle_radians.y, glm::vec3(0.0f, 1.0f, 0.0f));
    m_rotationMatrix_Z = glm::rotate(glm::mat4(1.0f), m_angle_radians.z, glm::vec3(0.0f, 0.0f, 1.0f));
    m_modelMatrix = m_modelMatrix * m_rotationMatrix_X * m_rotationMatrix_Y * m_rotationMatrix_Z;

    //set modelview projection matrix
    m_MVP = projection * view * m_modelMatrix;
    drawObject();
}

void my3DEngineObject::drawObject() {
    if (m_shaderID != ENGINE_FATAL_ERROR) {
        glUseProgram(m_shaderID);
        glUniformMatrix4fv(m_shader_MVP_handle, 1, GL_FALSE, &m_MVP[0][0]);
    }
    
    glBindVertexArray(m_vertexArray);

    // position attribute
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);

    // color attribute
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
    
    glDrawElements(GL_TRIANGLES, m_nr_indices, GL_UNSIGNED_INT, 0);

    glDisableVertexAttribArray(1);
    glDisableVertexAttribArray(0);

    glBindVertexArray(0);
}

但是,当我将测试数据直接放入 addVertexData 函数时,它就可以工作了。

void my3DEngineObject::addVertexData(const GLfloat vertex_data[], const GLuint vertex_indices[], const size_t vertex_data_size, const size_t vertex_indices_size, int nr_vertices, int nr_indices, GLenum mode) {

    GLfloat vertices[] = {
        //positions          //colors
        -1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f,  // 0. left bottom back
         1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 0.0f,  // 1. right bottom back
         1.0f,  1.0f, -1.0f, 0.0f, 0.0f, 1.0f,  // 2. right top back
        -1.0f,  1.0f, -1.0f, 1.0f, 1.0f, 0.0f,  // 3. left top back
        -1.0f, -1.0f,  1.0f, 1.0f, 0.0f, 0.0f,  // 4. left bottom front
         1.0f, -1.0f,  1.0f, 0.0f, 1.0f, 0.0f,  // 5. right bottom front
         1.0f,  1.0f,  1.0f, 0.0f, 0.0f, 1.0f,  // 6. right top front
        -1.0f,  1.0f,  1.0f, 1.0f, 1.0f, 0.0f  // 7. left top front
    };
    // Vertex index list
    GLuint indices[] = {
        0, 1, 2,  // triangle 1 (back face)
        2, 3, 0,  // triangle 2 (back face)
        4, 5, 6,  // triangle 3 (front face)
        6, 7, 4,  // triangle 4 (front face)
        3, 2, 6,  // triangle 5 (top face)
        6, 7, 3,  // triangle 6 (top face)
        1, 0, 4,  // triangle 7 (bottom face)
        4, 5, 1,  // triangle 8 (bottom face)
        0, 3, 7,  // triangle 9 (left face)
        7, 4, 0,  // triangle 10 (left face)
        1, 5, 6,  // triangle 11 (right face)
        6, 2, 1   // triangle 12 (right face)
    };

    m_nr_vertices = 8;
    m_nr_indices = 36;
    m_mode = mode;

    glGenVertexArrays(1, &m_vertexArray);
    glGenBuffers(1, &m_vertexbuffer);
    glGenBuffers(1, &m_indexbuffer);
    glBindVertexArray(m_vertexArray);

    // bind and fill the vertex buffer
    glBindBuffer(GL_ARRAY_BUFFER, m_vertexbuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    //bind and fill the indices buffer
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexbuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
}

所以我怀疑数据在传递给函数的过程中丢失了。我不认为它是 memcopy,因为当我直接使用来自输入参数

const GLfloat vertex_data[]
const GLuint vertex_indices[]
的数据时,它仍然不起作用。

c++ opengl glm-math vbo opengl-4
1个回答
0
投票

我发现了我的问题,这只是我一直忽视的一个非常愚蠢的类型。为了进行测试,我必须使用对象,一个简单的三角形和立方体:

    static const GLfloat g_vertex_buffer_data[] = {
 -1.0f, -1.0f, 0.0f,
  1.0f, -1.0f, 0.0f,
  0.0f,  1.0f, 0.0f,
    };

    static const GLuint g_vertex_indices_data[] = {
        0,1,2
    };

    GLfloat vertices[] = {
    //positions          //colors
    -1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f,  // 0. left bottom back
     1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 0.0f,  // 1. right bottom back
     1.0f,  1.0f, -1.0f, 0.0f, 0.0f, 1.0f,  // 2. right top back
    -1.0f,  1.0f, -1.0f, 1.0f, 1.0f, 0.0f,  // 3. left top back
    -1.0f, -1.0f,  1.0f, 1.0f, 0.0f, 0.0f,  // 4. left bottom front
     1.0f, -1.0f,  1.0f, 0.0f, 1.0f, 0.0f,  // 5. right bottom front
     1.0f,  1.0f,  1.0f, 0.0f, 0.0f, 1.0f,  // 6. right top front
    -1.0f,  1.0f,  1.0f, 1.0f, 1.0f, 0.0f  // 7. left top front
    };
    // Vertex index list
    GLuint indices[] = {
        0, 1, 2,  // triangle 1 (back face)
        2, 3, 0,  // triangle 2 (back face)
        4, 5, 6,  // triangle 3 (front face)
        6, 7, 4,  // triangle 4 (front face)
        3, 2, 6,  // triangle 5 (top face)
        6, 7, 3,  // triangle 6 (top face)
        1, 0, 4,  // triangle 7 (bottom face)
        4, 5, 1,  // triangle 8 (bottom face)
        0, 3, 7,  // triangle 9 (left face)
        7, 4, 0,  // triangle 10 (left face)
        1, 5, 6,  // triangle 11 (right face)
        6, 2, 1   // triangle 12 (right face)
    };

当我将立方体的数据传递给 addVertexData 函数时,我意外地使用了单个三角形的索引:

obj->addVertexData(vertices, g_vertex_indices_data, sizeof(vertices), sizeof(indices), sizeof(vertices)/sizeof(GLfloat)/6, sizeof(indices)/sizeof(GLuint), GL_TRIANGLES);

现在效果很好...

© www.soinside.com 2019 - 2024. All rights reserved.