【问题标题】:c++ OpenGL Issue drawing mesh with vbo and vao stored within an object [duplicate]c ++ OpenGL问题使用存储在对象中的vbo和vao绘制网格[重复]
【发布时间】:2018-03-26 15:33:48
【问题描述】:

我正在尝试使用 c++ 和 OpenGL 制作一个 3D 国际象棋游戏,在此过程中我遇到了一个非常奇怪的错误,其中三角形(棋子的替代品)不会绘制,我留下了一个空白屏幕.当我在主函数而不是在片类中创建网格对象时,它可以正常工作,但是当它在片类中时却没有。这是指针的问题吗?

这是我的代码:

所以我主要创造了一个国际象棋

Piece piece = Piece(vec3(0, 0, 0)); //Create a chess peice

随后在 main 方法中循环绘制网格(draw 方法将在本文后面展示)

piece.GetMesh().Draw(); //Draw the chess peice

在棋子标题中,我创建了网格信息和对象:

//Mesh information
vector <vec3> verticies;
vector <unsigned int> indicies;
Mesh mesh;

在国际象棋棋子的 .cpp 文件中,我创建了网格对象 - verticies 是一个 vec3 向量,indicies 是一个 unsigned int 向量。

mesh = Mesh(verticies, indicies); //Create the mesh object

这是网格构造函数

Mesh::Mesh(vector <vec3> verticies, vector <unsigned int> indicies)
{
    unsigned int numVerticies = verticies.size();
    unsigned int numIndicies = indicies.size();

    vector <vec2> texCoords;

    //set the tex coords
    unsigned int texCoordsIndex = 0;

    for (unsigned int i = 0; i < numIndicies; i++)
    {
        switch (texCoordsIndex)
        {
        case 0:
            texCoords.push_back(vec2(0, 0));
            texCoordsIndex++;
            break;
        case 1:
            texCoords.push_back(vec2(0, 1));
            texCoordsIndex++;
            break;
        case 2:
            texCoords.push_back(vec2(1, 1));
            texCoordsIndex = 0;
            break;
        }
    }

    //Sends the mesh to the buffer
    drawCount = indicies.size();

    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);

    glGenBuffers(NUM_BUFFERS, vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo[POSITION_VB]);
    glBufferData(GL_ARRAY_BUFFER, verticies.size() * sizeof(verticies[0]), &verticies[0], GL_STATIC_DRAW);

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

    glBindBuffer(GL_ARRAY_BUFFER, vbo[TEXCOORD_VB]);
    glBufferData(GL_ARRAY_BUFFER, texCoords.size() * sizeof(texCoords[0]), &texCoords[0], GL_STATIC_DRAW);

    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[INDEX_VB]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicies.size() * sizeof(indicies[0]), &indicies[0], GL_STATIC_DRAW);

    glBindVertexArray(0);
}

这里是绘图函数,它是Mesh类中的一个方法

void Mesh::Draw()
{
    glBindVertexArray(vao);
    glDrawElements(GL_TRIANGLES, drawCount, GL_UNSIGNED_INT, 0);
    glBindVertexArray(0);
}

如果我提供的代码不足,请询问,我可以在线程中添加更多代码部分。

谢谢。

【问题讨论】:

    标签: c++ opengl drawing mesh vao


    【解决方案1】:

    也许这是一个从臀部的镜头,但由于您在类Mesh 的构造函数中使用glGenVertexArrays,我假设您在类Mesh 的析构函数中使用glDeleteVertexArrays
    在这一行:

    mesh = Mesh(verticies, indicies);
    

    会发生以下情况:

    您创建一个临时的Mesh 对象,该对象在其构造函数中生成顶点数组对象。此时所有数据都有效,生成顶点数组对象(GPU)。分配对象时,临时对象的成员将复制到目标对象。现在存在 2 个相同的对象。完成此操作后,临时对象Mesh 立即被销毁,顶点数组对象被临时对象的析构函数Mesh::~Mesh 删除(glDeleteVertexArrays)。至此所有数据都消失了。

    在析构函数Mesh::~Mesh中放一个断点,就可以简单的追踪过期了。

    使类不可复制且不可复制构造,但指定移动构造函数和移动运算符。

    class Mesh 
    {
        Mesh(const Mesh &) = delete;
        Mesh & operator = (const Mesh &) = delete;
    
        Mesh( Mesh && );
        Mesh & operator = ( Mesh && );
    
        ....
    };
    

    见:

    【讨论】:

    • @Rabbid76: "从 Mesh 的析构函数中移除 glDeleteVertexArrays" 不,不要那样做。在析构函数中删除它对于这种设计是正确的。问题在于不正确地调用析构函数,如本例所示。这应该是一个只能移动的类型,所以它应该有一个移动构造函数/操作符来将 VAO 从一个实例移动到另一个实例。
    • @NicolBolas 我不能不同意,你当然是对的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-02
    • 1970-01-01
    • 2021-07-18
    • 1970-01-01
    • 2020-07-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多