960 likes | 1.14k Views
Számítógépes grafika. DirectX 2. gyakorlat. Emlékeztető. Előző órán szó volt a COM modellről, amiben az objektumok eljárásait az általuk megvalósított felületeken keresztül érhetjük el
E N D
Számítógépes grafika DirectX 2. gyakorlat
Emlékeztető • Előző órán szó volt a COM modellről, amiben az objektumok eljárásait az általuk megvalósított felületeken keresztül érhetjük el • WinAPI-ról is volt néhány szó, megismertük mi az a leíró, röviden megnéztük az üzenetfeldolgozást, a WinMain-t stb. • Láttuk, hogy a DirectX több komponensből áll
Tartalom • 1. DirectX Graphics felépítése • 2. Első DirectX-es alkalmazás • 3. Képek megjelenítése • 4. Szövegkirajzolás
DirectX Graphics felépítése Ezt írjuk mi Amiket lefordítja a grafikus kártya driverének „nyelvére” az ún. HAL device A programunkban a Direct3D API által biztosított függvényeket hívhatjuk
DirectX Graphics felépítése • Az alkalmazás és a hardver közötti szoftveres réteg két részből áll: • Direct3D API • HAL
Direct3D API • A Direct3D API-t programozzuk az alkalmazásunkból • Ez felületek és függvények halmaza, amiken keresztül elérhetjük az aktuális DX verzió által nyújtott összes szolgáltatást • Azonban ez nem jelenti azt, hogy a hardver is támogatja mindet
Hardware Abstraction Layer • A HAL-nak köszönhetően vonatkoztathatunk el a tényleges gépi konfigurációtól • Rajta keresztül történik a kommunikáció a hardverrel • Megtudhatjuk például tőle, hogy milyen szolgáltatásokat valósít meg az aktuális hardver a D3D felületén keresztül elérhetőkből
Hardware Abstraction Layer • Ugyanis csak azokat a dolgokat tudja „lefordítani” a videókártya nyelvére ez a réteg, amiket meg is valósítanak az adott hardverben • Mivel közvetlenül használja a hardver nyújtotta szolgáltatásokat (a DDI-n keresztül), ezért a hardver gyártók fejlesztik (amit ki is használnak, ld. 3D Mark botrányok)
Mi van a nem megvalósított szolgáltatásokkal? • Úgynevezett pluggable software device-okban minden szoftveresen meg van valósítva • Ilyen például az SDK-val jövő Reference Rasterizer • Ami tehát az aktuális DX verzió összes szolgáltatását megvalósítja • Pontosságra és nem sebességre optimalizált
Mi van a nem megvalósított szolgáltatásokkal? • Amikor létrehozzuk a Device-ot (ld. később) megadhatjuk, hogy HAL-on vagy Reference Rasterizer-en keresztül dolgozzon-e • Illetve ha van, egyéb, harmadik fél által gyártott psd-vel
A Direct3D grafikus szerelőszalagja Nézeti gúlával vágás, hátrafelé néző lapok eldobása, attríbútum kiértékelések és fragmenteken interpolálása stb. A képernyő adott pixelébe kerülő színének meghatározása (a fragment átmegy kül. teszteken még) „Csempézés”, magasabbrendű felületek síklapokkal való közelítése. A modelleket felépítő transzformálatlan csúcspontok, vertexek Fragment végső színének kialakítása (textúrázás, megvilágítás stb.) Különböző transzformációk alkalmazása a csúcspontokra (világ, nézet, perspektív, egyéb) A geometriai primitívek (vonal, háromszög stb.), amik a Vertex Data-beli csúcspontok különböző szabályok szerinti összekötésével definiáltak
Direct3D device • A Direct3D renderelő komponense • Tárolja a működését befolyásoló renderelési állapotokat • Három modulból áll: • Transform module • Lighting module • Rasterizer • Két fő típusa: • HAL device (hardveresen gyorsított) • REF device (referencia eszköz, szoftveres)
Direct3D object • Ahhoz, hogy létrehozhassunk egy Direct3D Device-ot (renderelő komponenst), szükségünk van egy Direct3D objektumra (ami nagyjából a fizikai erőforrások összességét képviseli, tőle kérdezhetjük le a hardver képességeit, megjelenítők számát stb.) • Egy-egy Direct3D Device a megjelenítéshez szükséges funkcionálisan teljes részhalmaza lesz a rendelkezésre álló megjelenítéshez szükséges eszközök halmazának • Tehát Device-ban egy konkrét monitor stb.
Direct3DDevice • A létrehozandó eszköz megjelenítési tulajdonságait egy D3DPRESENT_PARAMETERS típusú struktúra kitöltésével adhatjuk meg • Itt állíthatjuk be a felbontást és egyebeket
Mi jelenik meg a monitoron? • A videókártya memóriájának egyik darabja • A memóriában tárolt képeket DirectX-ben az IDirect3DSurface9 interfészen keresztül érhetjük el
Direct3D surface(IDirect3DSurface9) • Egy kép a memóriában (grafikus kártyáéban vagy a rendszerében) • Kitüntetett felületek: • Front Buffer: amikor frissít a monitor, a grafikus kártya a front buffer tartalmát küldi át neki megjelenítésre. Nem írunk rá programból. • Back Buffer: szintén négyszögletes kép, őt írjuk. • Megjelenítéskor ezek váltogatják egymást (double bufferingnél) • Miért nem a Front Buffert írjuk?
Swap Chain • Ha frissítés közben változtatnánk a front buffert, akkor a képernyő egy (felső) részén a régebbi kép(rész), az alsón pedig az újabb lenne (tearing) • Ezt többféle módon is el lehet kerülni: • a vertical retrace-t megvárni • back buffering: nem a megjelenített felületre rajzolunk, hanem egy back bufferre, amit majd cserélünk a front bufferrel. • Flipping: a back buffer és a front buffer felcserélése • A swap chain egy vagy több back buffer lánca.
Flipping • A grafikus kártya egyszerűen egy memória hivatkozással tartja számon az aktuális front buffert, ezért egy pointer átállítással megoldható a flip. • Presentation interval: a flipping időbeli módját határozza meg • DEFAULT: megvárja flip előtt a vsync-et • IMMEDIATE: nem várja meg a vsync-et • stb. • Továbbá az is megadható, hogy miként váljon az eddigi front buffer back bufferré (törlődjön a tartalma, maradjanak az adatok stb.)
Swap Chain és a D3D Device • A swap chain a Direct3D Device egy belső adattagja • Minden device-nak legalább egy swap chain-je van • Általában minden swap chainhez egy-egy színtérbeli nézetet társítunk • A front buffer azonban nem érhető el, a device belső tulajdonságának tekintjük
Tartalom • 1. DirectX Graphics felépítése • 2. Első DirectX-es alkalmazás • 3. Képek megjelenítése • 4. Szövegkirajzolás
1. példa Ablakos DirectX-es példaprogram
Mit is kell tennünk? • Létre kell hoznunk egy Direct3D objektumot • Majd egy Direct3D Device objektumot • Rajzolni valamit a képernyőre az előbbin keresztül • Megszüntetni a Direct3D Device objektumot • Végül megszüntetni a Direct3D objektumot
A program váza Direct3D Device objektum létrehozása Rajzolás Direct3D Device megsemmisítése Direct3D objektum létrehozása Futás Direct3D objektum megsemmisítése Ablak létrehozása Ablak törlése Inicializálás „Takarítás”
A program váza InitD3D Render CleanUpD3D InitWindow CleanUpWindow
A program váza InitD3D Render CleanUpD3D CDXAppBase elvégzi nekünk InitWindow CleanUpWindow
A program váza CMyDXApp Ezeket az eljárásokat viszontmár változtatjuk. InitD3D Render CleanUpD3D InitWindow CleanUpWindow
A program • Innen indulunk ki: http://people.inf.elte.hu/valasek/bevgraf/02/01_MyDXApp.zip • Ez lesz a vége: http://people.inf.elte.hu/valasek/bevgraf/02/01_MyDXApp_Ready.zip
CDXMyApp::CDXMyApp CDXMyApp::CDXMyApp(void) { }
CDXMyApp::~CDXMyApp CDXMyApp::~CDXMyApp(void) { }
HRESULT CDXMyApp::InitD3D() HRESULT CDXMyApp::InitD3D() { m_pD3D = Direct3DCreate9( D3D_SDK_VERSION ); if(!m_pD3D) { return E_FAIL; }... DXAppBase.h-ban:class CDXAppBase {...protected:LPDIRECT3D9 m_pD3D;...};
Direct3D objektum létrehozása • A D3D_SDK_VERSION az egyetlen megengedett paramétere a Direct3DCreate9-nak • Sikeres végrehajtás után a visszatérési érték egy mutató lesz a létrehozott objektum IDirect3D9 interfészére • A Direct3D objektum az első amit létrehozunk és az utolsó amit megsemmisítünk
Direct3D objektum létrehozása • Rajta keresztül ellenőrizhetjük, hogy milyen képességekkel rendelkezik az aktuális hardver • De csak a létrehozásának pillanatában is már a rendszerhez csatlakoztatott megjelenítőket kezeli • Rajta keresztül hozzuk létre a Direct3D Device objektumot
HRESULT CDXMyApp::InitD3D() ... ZeroMemory(&m_d3dpp, sizeof(m_d3dpp) ); m_d3dpp.BackBufferWidth = 800; m_d3dpp.BackBufferHeight= 600; m_d3dpp.BackBufferFormat=D3DFMT_UNKNOWN; m_d3dpp.Windowed= TRUE; m_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; ... voidZeroMemory( PVOIDDestination, SIZE_TLength );Destination: a cím, ahonnan kezdve 0-val töltjük fel a memóriátLength: a 0-val feltöltendő memóriaterület nagysága bájtban DXAppBase.h-ban:class CDXAppBase {...protected:D3DPRESENT_PARAMETERSm_d3dpp;...};
Direct3D Device objektum létrehozása • D3DPRESENT_PARAMETERS: A megjelenítés paramétereit adhatjuk meg vele (felbontás, teljes képernyős vagy ablakos alkalmazás-e stb.) • D3DPRESENT_PARAMETERS d3dpp; • Nullázzunk le minden értéket: • ZeroMemory( &d3dpp, sizeof(d3dpp) );
D3DPRESENT_PARAMETERS • typedef struct D3DPRESENT_PARAMETERS {…UINT BackBufferWidth, BackBufferHeight;…} • A háttérpuffer (back buffer) felbontása. Teljes képernyős módban ennek az adott videokártyán és monitoron használható különböző megjelenítési módok egyikének szélességével és magasságával kell megegyeznie, ablakosan nem szükséges. Ablakos alkalmazásnál ha 0, akkor az ablak kliensterületének megfelelő érték kerül oda.
D3DPRESENT_PARAMETERS • typedef struct D3DPRESENT_PARAMETERS {... D3DSWAPEFFECT SwapEffect; ...} • A front buffer back bufferré válásának módja: • D3DSWAPEFFECT_DISCARD: törlődik a tartalma • D3DSWAPEFFECT_FLIP: több back bufferből álló swap chain-nél használják, felcseréli a front buffert a soron következő back bufferrel. • D3DSWAPEFFECT_COPY: csak egy back buffer használata esetén választhatjuk.
HRESULT CDXMyApp::InitD3D() ... HRESULT hr = m_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,m_hWnd,D3DCREATE_HARDWARE_VERTEXPROCESSING,&m_d3dpp, &m_pD3DDevice); ...
IDirect3D9::CreateDevice • HRESULT CreateDevice(UINTAdapter,D3DDEVTYPE DeviceType,HWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS *pPresParams,IDirect3DDevice9 **ppRetDeviceInterface); • Adapter: a használni kívánt megjelenítő eszköz sorszáma, D3DADAPTER_DEFAULT a rendszer elsődleges megjelenítője
IDirect3D9::CreateDevice • HRESULT CreateDevice(UINT Adapter,D3DDEVTYPEDeviceType,HWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS *pPresParams,IDirect3DDevice9 **ppRetDeviceInterface); • DeviceType: a device típusa, a D3DDEVTYPE enum egy értékét várja (D3DDEVTYPE_HAL, D3DDEVTYPE_REF stb).
IDirect3D9::CreateDevice • HRESULT CreateDevice(UINT Adapter,D3DDEVTYPE DeviceType,HWNDhFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS *pPresParams,IDirect3DDevice9 **ppRetDeviceInterface); • hFocusWindow: annak az ablaknak a leírója, ami figyelmezteti a Direct3D-t, hogy az alkalmazás háttérbe került • Ablakos módban lehet NULL, ha a d3dpp hDeviceWindow adattagjának értéke érvényes.
IDirect3D9::CreateDevice • HRESULT CreateDevice(UINT Adapter,D3DDEVTYPE DeviceType,HWND hFocusWindow,DWORDBehaviorFlags,D3DPRESENT_PARAMETERS *pPresParams,IDirect3DDevice9 **ppRetDeviceInterface); • BehaviorFlags: egyéb opciók a device létrehozásához (hardveres vagy szoftveres vertexfeldolgozás stb.)
IDirect3D9::CreateDevice • HRESULT CreateDevice(UINT Adapter,D3DDEVTYPE DeviceType,HWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS *pPresParams,IDirect3DDevice9 **ppRetDeviceInterface); • pPresParams: lásd korábban
IDirect3D9::CreateDevice • HRESULT CreateDevice(UINT Adapter,D3DDEVTYPE DeviceType,HWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS *pPresParams,IDirect3DDevice9 **ppRetDeviceInterface); • ppRetDeviceInterface: a paraméterben kapott címen lévő mutató a létrehozott Direct3D Device objektum interfészére fog mutatni.
HRESULT CDXMyApp::InitD3D() ... if( FAILED( hr ) ) { return E_FAIL; } InitDeviceObjects(); return S_OK; }
HRESULT CDXMyApp::InitDeviceObjects() • Ide majd az eszközmemóriába kerülő erőforrások létrehozásának kódja kerül • Egyelőre csak ennyi: HRESULT CDXMyApp::InitDeviceObjects() { return S_OK; }