Régóta terveztem, hogy egy a közelmúltban megjelent játékot veszek górcső alá kiderítendő a mai grafikai követelményeket ill. technikákat. Erre a célra az idSoft Quake4 engine-je kínálkozott a legjobb választásnak. Az elemzés egy NVidia QuadroFx570M-n készült tehát amennyiben vendor/driver specifikus részei vannak az engine-nek, akkor az elemzés csak erre a GPU-ra vonatkozik (egyik legjobb példa a kétoldalas stencil vizsgálat - Ati kártyák más néven nem támogatják ezt).
Geometriai jellemzők:
Az engine minden vertex adatot VBO-zik míg a vertex indexeket nem! Minden frame elején a szükséges adatokat feltölti a video memóriába. Úgy tűnik, hogy az animálást CPU oldalon végzi.
A vertex attributumokat a megszokott komponensszámmal (position - 3, texcoord - 2, TBN - 3x3, color - 4) és formátumban (color - unsigned byte, minden más - float) adja át. A vertex indexek mindig GL_UNSIGNED_INT.
Furcsa módon keveri a régi és új pipeline-t vagyis a position attribútumokat glVertexPointer hívással adja meg míg a többit glVertexAttribPointerrel.
Minden geometriát GL_TRIANGLES-ként renderel.
Az átlagos háromszög szám 30 000 - 130 000 között váltakozik, de ebben szerepel a shadow volume geometriája is és a multipass fázisok is! Külső terek megjelenítésekor általában 100 000 felett van az érték.
Gyakorlatilag nem használja a beépített mátrix kezelő parancsokat csak glLoadMatrixf-t. Nem használ glBegin/glEnd párost a rendereléshez.
Használja a három fontosabb mátrixot módot.
Raszterizálási jellemzők:
Rengeteg decalt renderel glPolygonOffset(0, -600) beállítás mellett.
Bump map rendereléskor 7 textúrát használ: diffuse maphez, normal maphez, specular maphez, egy projektív textúrát, kétféle gradient maphoz és egyet a normalizáló cube maphez.
Furcsa módon ebben a szakaszban is használja a régi pipeline-t -gyaníthatóan a HUD és decalok renderelésekor. A renderelés végén lehet találkozni texture environment combiner parancsokkal.
Az új pipeline-t GLSL-en (ezt leginkább bizonyos decalokhoz) és asm-on keresztül használja vegyesen.
Sok esetben akár 16 környezeti változót is átad a vertex programnak míg fragment programnak általában 2-t.
Érdekesség, hogy a depth range-t sokszor állítja: 0,1 ill. 0, 0.5 az előforduló értékek.
Árnyék renderelés:
Az árnyékterek renderelésekor használ polygonoffsetet 0,1 paraméterekkel.
Kihasználja a GL_EXT_stencil_test_two_side (ehhez kötelezően a GL_STENCIL_WRAP-et) valamint a GL_EXT_depth_bounds_test extensiont ill. a scissor test-et.
Úgy tűnik, hogy az árnyéktér sziluettjét és a szükséges geometriát a CPU-val állítja elő míg a fény irányának megfelelő kihuzást GPU-val végezteti és a végtelenbe vetíti az árnyéktér távoli végeit.
A térfelosztás alapján rendereli az árnyékokat: először az árnyékterek aztán a látható geometria.
A helyzetnek megfelelően használ z-fail és z-pass algoritmust.
Shadow map használatára utaló jeleket sehol nem találtam, csak egyszerű textúra projekcióra.
Egyéb:
A portálok renderelésekor is használ scissor testet. A háttérhez skybox-ot használ, amely függőleges irányban rövidebbnek tűnik, mint a szélessége. Úgy látszik, hogy a részecskerendszereket nem szűri engine, hanem mindig rendereli.
Végezetül jöjjön néhány negatívum.
Rengeteg textúra váltás. Rengeteg pointer váltás. Rengeteg állapot váltás. A vertex attributumok összefésülésének hiánya (különösen a statikus esetekben). Sok feleslegesnek tűnő utasítás - egymás után kiadott glLoadMatrix, glActiveTextureARB stb. parancsok. Elméletileg a régi (glVertexPointer és társai) és új típusú (glVertexAttribPointer) vertex attribútum átadást nem lehet keverni pontosabban nem kötelező az OpenGL implementációknak támogatnia.