8

OpenGL 2.x スタイルの頂点配列を使用して OpenGL 3.x で動作するエンジンを更新しようとしています。これは、VAO/VBO への更新を意味します。私は VBO に適切にバインドしていないと思います。詳細については以下を読むか、コードにスキップして、私が間違っていることを見つけてください。

私のメッシュ クラスの簡単な概要は次のようになります。

メッシュ

  • ルート MeshNode

MeshNode

  • 変身
  • VAO 指数
  • インデックス VBO インデックス
  • 子 MeshNode の配列
  • MeshObject の配列

メッシュ オブジェクト

  • メッシュ全体の 1 つの部分について、ファイルからロードされたすべての頂点およびインデックス データ
  • 頂点 VBO インデックス

MeshObject を 1 つだけ使用して MeshNode を描画すると、うまく描画されるようです。複数の MeshObject を使用して MeshNode を描画すると、描画しようとしているモデルの全体的な形状が得られますが、文字化けしています。

Visual Studio デバッガーで頂点データを確認し、gDEbugger を使用して VBO データを確認したところ、すべて問題ないように見えたので、ファイルからの読み込みと VBO への読み込みが機能していると確信しています。

gDEbugger を使用して、三角形ではなくすべての頂点のポイントを描画するように強制しました。これは単一の MeshObject の形状をしているため、さまざまな VBO に適切にバインドしていないだけだと思います。異なるインデックスで描画しようとしているかのようですが、毎回同じ頂点です。

VertexData は次のようになります。

struct VertexData
{
    enum
    {
        NUM_TEXCOORDS = 1,
    };
    vector3 vertex;
    vector3 normal;
    vector2 texCoord[NUM_TEXCOORDS];
};

関連する MeshNode コード:

void MeshNode::initVAO(void)
{
    closeVAO();

    unsigned int scan;

    //init index data
    if (m_meshObjects.size() > 0)
    {
        glGenVertexArrays(1, &m_meshVAO);
        glBindVertexArray(m_meshVAO);
        {
            //add up the total index count for all the mesh objects in this node
            unsigned int indexCount = 0;
            for (scan = 0; scan < m_meshObjects.size(); ++scan)
            {
                indexCount = indexCount + m_meshObjects[scan].getIndices()->size();
            }
            //make the actual index buffer
            glGenBuffers(1, &m_indexVBO);
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexVBO);
            {
                glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * sizeof(unsigned short), NULL, GL_STATIC_DRAW);

                //set up VBOs and fill the index buffer with the index data from each mesh object
                unsigned int offset = 0;
                for (scan = 0; scan < m_meshObjects.size(); ++scan)
                {
                    m_meshObjects[scan].initVBOs(offset);
                }
            }
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
        }
        glBindVertexArray(0);
    }
    for (scan = 0; scan < m_childMeshNodes.size(); ++scan)
    {
        m_childMeshNodes[scan]->initVAO();
    }
}

void MeshNode::closeVAO(void)
{
    if (m_meshVAO != 0)
    {
        glBindVertexArray(m_meshVAO);
        {
            glDeleteBuffers(1, &m_indexVBO);
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
        }
        glBindVertexArray(0);
        glDeleteVertexArrays(1, &m_meshVAO);
        m_meshVAO = 0;
        m_indexVBO = 0;
    }
}

void MeshNode::render(const matrix4 &_parentTransform)
{
    matrix4 transform = _parentTransform * m_transform;

    if (m_meshObjects.size() > 0)
    {
        glBindVertexArray(m_meshVAO);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexVBO);
        {
            for (unsigned int objectScan = 0; objectScan < m_meshObjects.size(); ++objectScan)
            {
                m_meshObjects[objectScan].render(transform);
            }
        }
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
        glBindVertexArray(0);
    }

    for (unsigned int childScan = 0; childScan < m_childMeshNodes.size(); ++childScan)
    {
        m_childMeshNodes[childScan]->render(transform);
    }
}

関連する MeshObject コード:

void MeshObject::initVBOs(unsigned int& _indexOffset)
{
    //sub in this section of the index data
    m_indexOffset = _indexOffset;
    _indexOffset = _indexOffset + m_indices.size();
    glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, m_indexOffset * sizeof(unsigned short), m_indices.size() * sizeof(unsigned short), &(m_indices[0]));

    //init vertex data
    glGenBuffers(1, &m_vertexVBO);
    glBindBuffer(GL_ARRAY_BUFFER, m_vertexVBO);
    {
        glBufferData(GL_ARRAY_BUFFER, m_data.size() * sizeof(VertexData), &(m_data[0]), GL_STATIC_DRAW);

        glVertexAttribPointer(Shader::POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (char*)0);
        glEnableVertexAttribArray(Shader::POSITION);
        glVertexAttribPointer(Shader::NORMAL, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (char*)12);
        glEnableVertexAttribArray(Shader::NORMAL);
        glVertexAttribPointer(Shader::TEXCOORD0, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (char*)24);
        glEnableVertexAttribArray(Shader::TEXCOORD0);
    }
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

void MeshObject::closeVBOs(void)
{
    glDeleteBuffers(1, &m_vertexVBO);

    m_vertexVBO = 0;
}

void MeshObject::render(const matrix4& _transform)
{
    m_material->bind(_transform);
    glBindBuffer(GL_ARRAY_BUFFER, m_vertexVBO);
    {
        glEnableVertexAttribArray(Shader::POSITION);
        glEnableVertexAttribArray(Shader::NORMAL);
        glEnableVertexAttribArray(Shader::TEXCOORD0);
        glDrawRangeElements(GL_TRIANGLES, m_indexOffset, m_indexOffset + m_indices.size(), m_indices.size(), GL_UNSIGNED_SHORT, (char*)0);
        glDisableVertexAttribArray(Shader::POSITION);
        glDisableVertexAttribArray(Shader::NORMAL);
        glDisableVertexAttribArray(Shader::TEXCOORD0);
    }
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}
4

2 に答える 2

1

の使い方を間違っていると思いますglDrawRangeElementsstartおよびendパラメーターは、インデックス配列で発生する可能性のある最小および最大の頂点インデックスですが、次に および を指定します。m_indexOffestこれm_indexOffset+m_indices.size()は、レンダリングするインデックス データ範囲であり、必ずしもこれらのインデックス配列内の頂点インデックスの範囲ではありません。

また、補足として、VAO はすべての頂点配列/バッファー状態、すべてのバッファー バインディング、ポインター、および有効なフラグをカプセル化するため、多くの不要な呼び出しを行っています。メソッドでインデックス バッファーinitVAOをバインドするだけで、メソッドで VAO をバインドすると常にバインドされますMeshNode::render(もちろん、この場合はすべての呼び出しを省略しglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)ます)。同様に、メソッドで属性配列を有効にするだけでよくinitVAO(すべてMeshObjectの s で同じ属性が有効になっていると仮定)、VAO をバインドすると自動的に有効になります。現在の構成では、VAO は完全に不要であり、何のメリットもありません。

于 2011-09-01T22:03:56.347 に答える