1

これがあまりにも多くのコード ダンプに見えないことを願っていますが、なぜこれが機能しないのかについてはまったくわかりません。glGetError() からエラーを取得しようとしましたが、常に 0 を返すようです。問題に影響を与えていると思われるコードのみを含めようとしました。これを使用した他のほとんどの状況では、他のコードが正常に機能していたためです。

とにかく、最初にコードを書いてください:

これは私のメインのレンダリング ループです。

float rotate = 0.0f;
void Render(SDL_Window *window)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glLoadIdentity();

    gluLookAt(-2,-2,-10,   0,0,0,   0,1,0);

    glRotatef(rotate, 0, 1, 0);
    // Start drawing
    glUseProgramObjectARB( *shader->GetShaderProgram() );
    texture->EnableTexture( *shader->GetShaderProgram(),"tex" );
    cube->Render();
    SDL_GL_SwapWindow(window);
    rotate = rotate+1;
    glUseProgramObjectARB(0);
}

これは私のオブジェクトです render(cube->Render()):

void Object3DVBO::Render()
{

    //Bind the buffers and tell OpenGL to use the Vertex Buffer Objects (VBO's), which we already prepared earlier
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboID); 
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, texcoordsID);
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, normalID);
    glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indiceID);

    //Enable states, and render (as if using vertex arrays directly)
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);

    glTexCoordPointer(2, GL_FLOAT, 0, 0);
    glNormalPointer(GL_FLOAT, 0, 0);
    glVertexPointer(3, GL_FLOAT, 0,  0);

    if(textureid > 0) {
        glEnable(GL_TEXTURE_2D);      // Turn on Texturing
        //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
        glBindTexture(GL_TEXTURE_2D, textureid);
    }

    //Draw the thing!
    glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_BYTE, 0);
    //restore the GL state back
    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);
    if(textureid > 0) {
        glDisable(GL_TEXTURE_2D);      // Turn off Texturing
        glBindTexture(GL_TEXTURE_2D, textureid);
    }

    glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); //Restore non VBO mode
    glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
};

これは、VBO を初期化するためのコードです。

void Object3DVBO::SetVBO()
{
    // Vertices:
    glGenBuffersARB(1, &vboID);
    glBindBufferARB( GL_ARRAY_BUFFER_ARB, vboID);
    glBufferDataARB( GL_ARRAY_BUFFER_ARB, sizeof(GLfloat)*vertices.size(), &vertices, GL_STATIC_DRAW_ARB );

    // Vertices:
    glGenBuffersARB(1, &indiceID);
    glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, indiceID);
    glBufferDataARB( GL_ELEMENT_ARRAY_BUFFER_ARB, sizeof(GLubyte)*indices.size(), &indices, GL_STATIC_DRAW_ARB );

    // Normals:
    glGenBuffersARB(1, &normalID);
    glBindBufferARB( GL_ARRAY_BUFFER_ARB, normalID);
    glBufferDataARB( GL_ARRAY_BUFFER_ARB, sizeof(GLfloat)*normals.size(), &normals, GL_STATIC_DRAW_ARB );

    // Texture coordinates:
    glGenBuffersARB(1, &texcoordsID);
    glBindBufferARB( GL_ARRAY_BUFFER_ARB, texcoordsID);
    glBufferDataARB( GL_ARRAY_BUFFER_ARB, sizeof(GLfloat)*texCoords.size(), &texCoords, GL_STATIC_DRAW_ARB );

    vertices.clear();
    normals.clear();
    texCoords.clear();
    indices.clear();
}

そして最後に、テキストファイルで作成した最も単純なモデル:

mesh:
-0.5 -0.5 0.0
0.5 -0.5 0.0
0.5 0.5 0.0
-0.5 0.5 0.0
normals:
0 0 -1
0 0 -1
0 0 -1
0 0 -1
texcoords:
0.0 0
1.0 0
1.0 1.0
0.0 1.0
indices:
0 0 0 1 1 1 2 2 2 0 0 0 2 2 2 3 3 3
end:

この外側にあるのは、テキストファイルを読み取り、関数からのベクトルに格納することです。オブジェクトのヘッダー ファイルは次のとおりです。

class Object3DVBO
{
public:
    Object3DVBO(const char* objectfilename, GLuint textureid);
    ~Object3DVBO();
    void Render();
private:
    GLuint  vboID, 
            texcoordsID, 
            normalID, 
            textureid,
            indiceID;
    int     vertCount,
            indexCount;
    std::vector<GLfloat> vertices;
    std::vector<GLfloat> normals;
    std::vector<GLfloat> texCoords;
    std::vector<GLubyte> indices;

    void ConvertToReadable( std::vector<GLfloat> v, std::vector<GLfloat> n, std::vector<GLfloat> tc, std::vector<GLint> i);
    void ReadObjectData( const char* objectfilename);
    void SetVBO();
};

他の部分は、シェーダーペアとテクスチャに対して基本的に同じことを行うためのもので、これらは正常に動作しているようです (シェーダーは現在バージョン 120 のみであるため、ftransform() などを使用しています)。

私が抱えている問題は、インデックスを使用してこのコードと glDrawElements を使用すると、黒い画面が表示され (どこにもエラーはありません)、glDrawArrays に切り替えると機能することです (または、少なくとも何かが表示されます。多くのチュートリアル、例を読みましたおよび他のSOの投稿が私が間違っていることを見つけようとしていますが、これまでのところ、ソリューション/チュートリアルのどれも違いをもたらしていません。

これは教育目的で行っているため、glDrawElements とインデックスを使用する必要があります。どんな助けでも大歓迎です!

Ps。SDL バージョンについて疑問に思っている人がいれば、その SDL2.

4

1 に答える 1

1

問題の核心は次のとおりです。

//Bind the buffers and tell OpenGL to use the Vertex Buffer Objects (VBO's), which we already prepared earlier
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboID);          // 1
glBindBufferARB(GL_ARRAY_BUFFER_ARB, texcoordsID);    // 2
glBindBufferARB(GL_ARRAY_BUFFER_ARB, normalID);       // 3
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indiceID);

//Enable states, and render (as if using vertex arrays directly)
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);

glTexCoordPointer(2, GL_FLOAT, 0, 0);                 // 2
glNormalPointer(GL_FLOAT, 0, 0);                      // 3
glVertexPointer(3, GL_FLOAT, 0,  0);                  // 1

1、2、および 3 のラベルが付いた行は、ペアである必要があります。つまり、一度にバインドできる VBO は 1 つだけであり、glTexCoordPointer (...)たとえば呼び出しのコンテキストを提供するため、適切な VBO がバインドされている間にポインターを設定する必要があります。

次のように修正できます。

//Bind the buffers and tell OpenGL to use the Vertex Buffer Objects (VBO's), which we already prepared earlier
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboID);          // 1
glVertexPointer(3, GL_FLOAT, 0,  0);                  // 1

glBindBufferARB(GL_ARRAY_BUFFER_ARB, texcoordsID);    // 2
glTexCoordPointer(2, GL_FLOAT, 0, 0);                 // 2

glBindBufferARB(GL_ARRAY_BUFFER_ARB, normalID);       // 3
glNormalPointer(GL_FLOAT, 0, 0);                      // 3


glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indiceID);

//Enable states, and render (as if using vertex arrays directly)
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);

もう 1 つ問題がありますが、これは実際にはエラーではなく、パフォーマンスの問題です。GL_UNSIGNED_BYTEハードウェアでサポートされている頂点インデックス タイプではありません。ドライバーは、ハードウェアが使用できるようにインデックス配列を 16 ビット型に変換する必要があるため、VBO に格納するときに 8 ビット インデックスを使用しても実際にはメリットがありません。デバッグ出力が有効になっているほとんどの OpenGL プロファイラーとドライバーは、これを行おうとするとパフォーマンス警告を生成します。

于 2013-11-06T00:46:46.280 に答える