1k likes | 1.17k Views
Számítógépes grafika. DirectX 3. gyakorlat. Emlékeztető. Rajzoltunk múlt órán üres ablakot, képet, szöveget Ehhez megismerkedtünk a Direct3D Object-tel és a Direct3D Device-szal Textúrabetöltést is megismertük. Tartalom. 1. Áttekintés 2. Háromdimenziós alapok 3. CG. Jelenlegi programváz.
E N D
Számítógépes grafika DirectX 3. gyakorlat
Emlékeztető • Rajzoltunk múlt órán üres ablakot, képet, szöveget • Ehhez megismerkedtünk a Direct3D Object-tel és a Direct3D Device-szal • Textúrabetöltést is megismertük
Tartalom • 1. Áttekintés • 2. Háromdimenziós alapok • 3. CG
Jelenlegi programváz • A videókártya memóriájába kerülő erőforrások lefoglalása InitDeviceObjects • A Direct3D Object létrehozása • A Direct3DDevice objektum létrehozása • olyan erőforrások lefoglalása, amik nem a videókártya memóriájába kerülnek InitD3D
Jelenlegi programváz FrameUpdate Render - A színtér felépítésének módosítása, különböző mátrixok beállítása (nézeti, projekciós) stb. - A színtér kirajzolása
Jelenlegi programváz A videókártya memóriájába kerülő erőforrások felszabadítása ReleaseDeviceObjects • A Direct3D Device megsemmisítése • A Direct3D Object megsemmisítése • Az erőforrások felengedése, amelyek nem a videókártya memóriájába kerültek CleanUpD3D
Jelenlegi programváz InitDeviceObjects ReleaseDeviceObjects FrameUpdate Render InitD3D CleanUpD3D
CDXAppBase • Az ősosztály • Tartalmazza a WinAPI-s ablaklétrehozás kódját • Adattagjai között szerepel egy-egy D3D Object, Device, Presentation Parameters
CDX*App • Ezeket írjuk mi, múlt órán például CDXImageApp stb. • A következő függvényeket kell megvalósítani benne: HRESULT InitD3D(); HRESULT InitDeviceObjects(); VOID ReleaseDeviceObjects(); VOID CleanUpD3D(); VOID FrameUpdate(); VOID Render();
CDX*App.h #pragmaonce #include "dxappbase.h" class CDX*App : public CDXAppBase { public: CDX*App(void); ~CDX*App(void); HRESULT InitD3D(); HRESULT InitDeviceObjects(); VOID ReleaseDeviceObjects(); VOID CleanUpD3D(); VOID FrameUpdate(); VOID Render(); ...
main.cpp • Létrehoz a CDX*App-unkból egy objektumot • Meghívja annak az ablaklétrehozó eljárását • És a Run futattóeljárását • A Run • Kezeli a Windows-os üzeneteket (kattintások, átméretezések stb.) • Ha épp nincs feldolgozandó üzenet, akkor a Render-t meghívja (a Render-ben pedig mi FrameUpdate-et is hívunk)
CDXAppBase::Run VOID CDXAppBase::Run() { MSG msg; ZeroMemory( &msg, sizeof(msg) ); while( msg.message!=WM_QUIT ) { if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } else Render(); } }
Tartalom • 1. Áttekintés • 2. Háromdimenziós alapok • 3. CG
Primitívek • A 3D-s modelljeinket primitívekből, építőelemekből rakjuk össze • Egy 3D-s primitív csúcspontokból áll, amik egyetlen térbeli entitást alkotnak • Például pontok, poligonok stb.
Pipeline Vertex shader Fragment shader
Direct3D primitívjei • Ha tudjuk, hogy milyen típusú primitívet szeretnénk rajzolni, akkor onnantól már csak a pontjait kell megadni • Ugyanis a 3D-s entitást a primitívtípusból és az azt jellemző pontösszekötési szabályból a csúcspontok már meghatározzák
Direct3D primitívjei • Legyenek adottak a következő csúcsok: struct CUSTOMVERTEX { float x,y,z;}; CUSTOMVERTEX Vertices[] = { {-5.0,-5.0,0.0}, {0.0,5.0,0.0}, {5.0,-5.0,0.0}, {10.0,5.0,0.0}, {15.0,-5.0,0.0}, {20.0,5.0,0.0} };
Direct3D primitívjeiPontlisták • A bemeneti csúcspontokat különálló pontokként rendereli le • Anyagjellemzőket és textúrákat rendelhetőek hozzájuk • d3dDevice->DrawPrimitive( D3DPT_POINTLIST, 0, 6 );
Direct3D primitívjeiSzakaszlisták • Különálló szakaszok, 2*n és 2*n+1-edik pont között • Páros számú pontot kell megadni • d3dDevice->DrawPrimitive( D3DPT_LINELIST, 0, 3 );
Direct3D primitívjeiLinestrip • Csatlakozó szakaszsorozat, legalább két pontot meg kell adni • d3dDevice->DrawPrimitive( D3DPT_LINESTRIP, 0, 5 );
Direct3D primitívjeiHáromszög lista • Különálló háromszögek listája, 3*n pontot kell megadni • d3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 2 );
Direct3D primitívjeiHáromszög strip • Egy oldalban csatlakozó háromszögek listája • Legalább 3 pontot kell megadni, utána minden újabb pont az előző kettővel együtt alkot egy háromszöget • d3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 4);
Direct3D primitívjeiHáromszög „legyező” (fan) • Hasonló mint az előző, csak mindegyik háromszögnek van egy közös pontja • d3dDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 4 );
Vertexek • A csúcspontokat (vertexeket) vertex bufferekben tároljuk • A vertex bufferek pedig erőforrások
Erőforrások DirectX-ben • Minden erőforrás bír a következő tulajdonságokkal: • Usage: felhasználási mód, például textúra, vagy renderelési célpont stb. • Format: adatformátum (pl. surface-nél bitmélység) • Pool: a memóriatípus, ahová kerül • Type: típus, vertex buffer, render cél stb.
Erőforrások DirectX-benUsage • Az alkalmazásnak már az erőforrás létrehozásakor meg kell mondania, hogy milyen módon fogja azt használni • Lehetséges értékeit ld. D3DUSAGE • Például pontsprite-okat tartalmazó vertex (és index) buffernek D3DUSAGE_POINTS-ot kell megadnia • D3DUSAGE_WRITEONLY-val azt mondjuk, hogy csak írni fogjuk az adott vertex buffert. Ez lényegesen gyorsíthat!
Erőforrások DirectX-benFormat • Az erőforrás tárolási formátumát adja meg • D3DFORMAT-ban találhatóak a lehetséges értékei • Az erőforrás típusától függnek a megengedett értékek • Mások tehát back bufferekhez, bufferekhez, megjelenítési felületekhez stb.
Erőforrások DirectX-benPool • Ez határozza meg, hogy az adott erőforrás hová kerül (videókártya-memória, rendszermemória stb.) • Nem változtatható meg futás során • Értékeihez ld. D3DPOOL
Memóriaosztályok 1/2 • D3DPOOL_DEFAULT: az adott erőforrás a felhasználása szerinti legjobb helyen kerül tárolásra. Ez túlnyomórészt a videókártya memóriája. • D3DPOOL_MANAGED: amint szükséges a videókártya által is elérhető memóriába másolódnak az így definiált erőforrások. Emellett mindig van egy másolat róluk a rendszermemóriában. Nem kell helyreállítani őket lost device-nál.
Memóriaosztályok 2/2 • D3DPOOL_SYSTEMMEM: rendszermemória (RAM), általában az így elhelyezett dolgok nem érhetőek el a Direct3D Device által. Lost device nem érinti őt sem. • D3DPOOL_SCRATCH: hasonló mint a fenti, de rájuk nem vonatkoznak a device képességeiből fakadó megkötések (méret, formátum stb.). Device nem érheti el őket.
Erőforrások DirectX-benType • A típus futásidőben derül ki az erőforrást létrehozó eljárástól függően, implicit módon • Pl. a IDirect3DDevice9::CreateTexture textúrát hoz létre
Erőforrások DirectX-benMűveletek erőforrásokkal • A színtér kirajzolása közben különböző műveleteket végzünk az erőforrásainkon • Pl. létrehozzuk őket (device-on keresztül vagy D3DXCreateXXX-el, ...) • A tárolt adatok elérését lock-nak hívjuk • Például: • textúra képpontjainak elérése: IDirect3DTexture9::LockRect • Vertex bufferek csúcsainak elérése: IDirect3DVertexBuffer9::Lock
Erőforrások DirectX-benLock • Egy erőforrás lock-olása azt jelenti, hogy hozzáférést biztosítunk a CPU-nak a tárolt adatokhoz • A lock-olás során különböző flag-ek beállításával mondjuk meg, hogy miként szeretnénk használni a megszerzett adatokat: • D3DLOCK_DISCARD • D3DLOCK_READONLY • ...
Erőforrások DirectX-benLock • Egy erőforráson egyszerre csak egy lock lehet • A lockolás visszaad egy struktúrát is, ami azt jellemzi, hogy miként tárolódik fizikailag az adott erőforrás a memóriában
Erőforrások DirectX-benUnlock • Miután elvégeztük a dolgunkat a bufferrel Unlock-olni kell!
Erőforrások DirectX-benVertex bufferek • IDirect3DVertexBuffer9 interfész • Vertexadatokat tartalmazó memóriaterület • A benne tárolt csúcsok transzformálhatóak, világíthatóak stb. • De tárolhatunk már eleve transzformált pontokat (RHW) • Egy vertex buffert a képességei írnak le • amiket egy D3DVERTEXBUFFER_DESC struktúra ad meg
Flexible Vertex Format • Nem akarunk mindig minden csúcsponttal minden lehetséges dolgot megcsinálni • Vannak olyan pontok amikre pl. csak egy textúrát akarunk feszíteni, esetleg nem akarjuk megvilágítani • Az FVF segítségével mondhatjuk meg, hogy az aktuális vertex bufferben tárolt csúcsokkal mit szeretnénk kezdeni
Flexible Vertex Format • D3DFVF_XYZ: 3D koordináták • D3DFVF_XYZRHW: transzformált képpont • D3DFVF_NORMAL: normálvektora is lesz (megvilágításhoz) • D3DFVF_DIFFUSE, D3DFVF_SPECULAR : csúcs színe • ...
Flexible Vertex Format • Létrehozunk egy struktúrát a programunk számára a csúcspont adatait leírni, illetve egy #define-al megadjuk Direct3D-nek a használt FVF tulajdonságokat • Fontos, hogy a struct-ban az adattagok sorrendje a D3DFVF_... konstansok sorrendjében kövesse egymást • Tehát általában pozíció, normális, szín, textúrakoordináták sorrendben jöjjenek
Flexible Vertex Format struct CUSTOMVERTEX { FLOAT x, y, z; DWORD color; }; #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)
1. példa Primitívek
Mit használunk? • Az eredmény ez lesz: http://people.inf.elte.hu/valasek/bevgraf/03/02_Vertices.zip
Új adattag class CDXVerticesApp :public CDXAppBase { ... private: LPDIRECT3DVERTEXBUFFER9 m_pVB; };
FVF deklarációDXVerticesApp.cpp A programunkban az eltárolt csúcspontokat így látjuk, ezeken az adattagokon keresztül struct CUSTOMVERTEX { FLOAT x, y, z, rhw; DWORD color; }; #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE) A videókártya számára ezzel a kifejezéssel mondjuk meg, hogy a vertex bufferben eltárolt adatok csúcspontelemei milyen attribútumait írják le egy-egy pontnak
Mit fogunk tenni? • Létrehozunk egy 3 elemű tömböt aminek az elemei CUSTOMVERTEX típusúak • Létrehozunk egy vertex buffert • Áttöltjük az adatokat a vertexbufferbe • ehhez a korábban említett lock – unlock segítségét vesszük igénybe • A VB-t DEFAULT_POOL-ba tesszük
HRESULT CDXVerticesApp::InitDeviceObjects() HRESULT CDXVerticesApp::InitDeviceObjects() { CUSTOMVERTEX vertices[] = { { 256.0f, 0.0f, 0.5f, 1.0f, 0xffff0000 }, { 512.0f, 396.0f, 0.5f, 1.0f, 0xff00ff00 }, { 0.0f, 396.0f, 0.5f, 1.0f, 0xff0000ff }}; ... x y z w A szín, lehet D3DCOLOR_* makró is
HRESULT CDXVerticesApp::InitDeviceObjects() ... HRESULT hr = m_pD3DDevice-> CreateVertexBuffer(3*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &m_pVB, NULL ); ...
IDirect3DDevice9::CreateVertexBuffer • HRESULT CreateVertexBuffer( UINT Length, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer9** ppVertexBuffer, HANDLE* pSharedHandle ); • Length: a buffer nagysága bájtban; legalább egy vertex tárolására elég kell, hogy legyen