1

奇妙な問題が
あります。15x15要素のゲームフロアを出力する必要があります。
これまで、ゲームループで関数「printFloor()」を呼び出していました。

この関数は、225の要素すべてをステップスルーし、それらの値に応じて、テクスチャファイルの異なる部分を表示します。そのため、CPUはすべてのループサイクルで同じ225テクスチャをレンダリングする必要がありました。ゲームループは各サイクルで約16〜32ミリ秒必要だったので、この出力をディスプレイリストに入れました。

if(!gamefloorPrepared)  //no Display list created -> this is the first time the floor nees to
                        //be printed
{   gamefloor = glGenLists(1);

    glNewList(gamefloor,GL_COMPILE);
        for(int y=0;y<size.y;y++)
        {   for(int x=0;x<size.x;x++)
            {   printFloorElement(spielfeld[y][x],{x,y});     //see below
            }
        }
    glEndList();
    gamefloorPrepared=1;
}else
{   glCallList(gamefloor);
}

関数printFloorElementは、位置を計算し、グラフィックモードを「switchGraphicMode(TEXTURES);」に変更し、テクスチャをバインドして、テクスチャを描画します。

glBegin(GL_QUADS);
    glTexCoord2f(spriteSize.x* spritePos.x   +halfTexelSize.x,spriteSize.y*(spritePos.y+1)-halfTexelSize.y);   glVertex2f(display.a.x,display.a.y);
    glTexCoord2f(spriteSize.x* spritePos.x   +halfTexelSize.x,spriteSize.y* spritePos.y   +halfTexelSize.y);   glVertex2f(display.a.x,display.b.y);
    glTexCoord2f(spriteSize.x*(spritePos.x+1)-halfTexelSize.x,spriteSize.y* spritePos.y   +halfTexelSize.y);   glVertex2f(display.b.x,display.b.y);
    glTexCoord2f(spriteSize.x*(spritePos.x+1)-halfTexelSize.x,spriteSize.y*(spritePos.y+1)-halfTexelSize.y);   glVertex2f(display.b.x,display.a.y);
glEnd();

問題:1つのゲームループサイクルに60〜80ミリ秒かかるため、かなり遅くなります。ディスプレイリストは一度だけ生成されます、私はすでにそれをチェックしました。

「switchGraphicMode()」-関数:

void switchGraphicMode(GRAPHICMODES target)//can be "TEXTURES" or "DRAWING"
{   if(target != graphicMode)//"gaphicMode" = global Variable which shows if GL_TEXTURE_2D is currently enabled
    {   if(target==DRAWING)
        {   glDisable(GL_TEXTURE_2D);
            graphicMode=DRAWING;
        }else
        {   glEnable(GL_TEXTURE_2D);
            graphicMode=TEXTURES;
        }
    }
}

誰もが理由を知っていますか?

4

2 に答える 2

2

glBegin()/ glEnd()およびdisplaylistsは、非推奨の「イミディエイトモード」パイプラインの一部です。

現在推奨されている方法は、頂点バッファオブジェクトを使用することです。

これら2つの方法の違いは、即時モードでは、レンダリングループを通過するたびに、ディスプレイリストを使用している場合でも頂点データをホストメモリからGPUに転送することです(ディスプレイリストはホスト上で維持され、ディスプレイでは維持されません)。カード)。

頂点バッファオブジェクトは、ディスプレイカードのメモリに保持されるメモリバッファです。一度設定すると、レンダリングを開始する前に頂点データを一度に転送します。次に、レンダリングループを通過するたびに、そのバッファからのデータを使用して描画するようにディスプレイカードに指示する特殊な描画関数を呼び出します。これにより、コストのかかるホストからディスプレイカードへのデータ転送を実行する必要がなくなります。

頂点バッファオブジェクトを使用するには、即時モードレンダリングよりも少し多くの設定が必要ですが、高速化する価値は十分にあります。Googleopengl頂点バッファオブジェクト。始めるためのチュートリアルとサンプルコードがたくさんあるはずです。

于 2012-11-13T06:47:41.163 に答える
0

これらのコードスニペットで見分けるのは難しいですが、最初のステップとして、DisplayListに入力するときにバッチ処理を利用することをお勧めします。これは見逃しているようです。

glEnable(GL_TEXTURE_2D);

if(!gamefloorPrepared)
{   gamefloor = glGenLists(1);

    glNewList(gamefloor,GL_COMPILE);
    glBegin(GL_QUADS);
        for(int y=0;y<size.y;y++)
        {   for(int x=0;x<size.x;x++)
            {   
                glTexCoord2f(spriteSize.x* spritePos.x   +halfTexelSize.x,spriteSize.y*(spritePos.y+1)-halfTexelSize.y);   glVertex2f(display.a.x,display.a.y);
                glTexCoord2f(spriteSize.x* spritePos.x   +halfTexelSize.x,spriteSize.y* spritePos.y   +halfTexelSize.y);   glVertex2f(display.a.x,display.b.y);
                glTexCoord2f(spriteSize.x*(spritePos.x+1)-halfTexelSize.x,spriteSize.y* spritePos.y   +halfTexelSize.y);   glVertex2f(display.b.x,display.b.y);
                glTexCoord2f(spriteSize.x*(spritePos.x+1)-halfTexelSize.x,spriteSize.y*(spritePos.y+1)-halfTexelSize.y);   glVertex2f(display.b.x,display.a.y);
            }
        }
    glEnd();
    glEndList();
    gamefloorPrepared=1;
}else
{  
 glCallList(gamefloor);    
}
glDisable(GL_TEXTURE_2D);

このようにして、ディスプレイリスト内のすべての頂点が1つのGL_QUADS句内にあり、不要なtexture_2d状態の変更はありません。

PS誰かが非推奨の機能についてコメントを追加する必要があります;)

于 2012-11-12T09:18:49.070 に答える