Előadást letölteni
Az előadás letöltése folymat van. Kérjük, várjon
KiadtaTibor Kelemen Megváltozta több, mint 10 éve
1
Számítógépes grafika DirectX 2. gyakorlat
2
Emlékeztető Előző órán áttekintettük a szükséges WinAPI- s alapokat Illetve röviden beletekintettünk a félév során használandó keretrendszerbe
3
Tartalom 1. DirectX Graphics felépítése 2. Első DirectX-es alkalmazás 3. Háromszög kirajzolás
4
DirectX Graphics felépítése Ezt írjuk mi A programunkban a Direct3D API által biztosított függvényeket hívhatjuk Amiket lefordítja a grafikus kártya driverének „nyelvére” az ún. HAL device
5
DirectX Graphics felépítése Az alkalmazásunkban a Direct3D API függvényeit hívjuk. Ezek végrehajtása lehet Hardveresen gyorsított: ilyenkor a HAL-on keresztül mennek a hívások Szoftveresen megvalósított: azaz a CPU-val számítunk mindent, GPU felhasználása nélkül
6
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
7
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)
8
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
9
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
10
Direct3D Object Ez az első DX9-es objektum, amit az alkamazásunk létre kell, hogy hozzon és az utolsó, amit meg kell, hogy semmisítsen A számítógépben elérhető, megjelenítéshez szükséges hardvereket kérdezhetjük le rajta keresztül (monitorok felbontásai, videokártyák képességei stb.)
11
Direct3D Device A DirectX renderelő komponense, rajta keresztül rajzolunk A kirajzoláshoz szükséges állapotokat is tárolja A D3D Object-en keresztül hozzuk létre, miután kiválasztottuk az igényeinket kielégítő, megjelenítéshez használt eszközöket (konkrét monitor, videokártya)
12
Direct3D Device Két fajtája van: HAL device: hardveresen gyorsított D3D implementáció REF device: szoftveres D3D implementáció
13
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
14
Mi jelenik meg a képernyőn? Egy kép (IDirect3DSurface9) a memóriából (grafikus kártyáéban vagy a rendszerében) DX-ben kitüntetett „képek”: 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?
15
„Screen Tearing”
16
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.
17
Vertical retrace
18
Swap chain példa kettő darab offscreen surface-szel
19
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.)
20
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
21
Tartalom 1. DirectX Graphics felépítése 2. Első DirectX-es alkalmazás 3. Háromszög kirajzolás
22
1. példa Ablakos DirectX-es példaprogram
23
Első DX-es program Innen tölthető le: http://cg.inf.elte.hu/~valasek/02/00_DX_Elso_ Ablak.zip http://cg.inf.elte.hu/~valasek/02/00_DX_Elso_ Ablak.zip
24
Mit is kell tennünk? 1. Létre kell hoznunk egy Direct3D objektumot 2. Majd egy Direct3D Device objektumot 3. Rajzolni valamit a képernyőre az előbbin keresztül 4. Megszüntetni a Direct3D Device objektumot 5. Végül megszüntetni a Direct3D objektumot
25
A program váza Ablak létrehozása Direct3D objektum létrehozása Direct3D Device objektum létrehozása Rajzolás Direct3D objektum megsemmisítése Direct3D Device megsemmisítése Ablak törlése Inicializálás Futás „Takarítás”
26
A program váza InitWindow InitD3DRenderCleanUpD3D CleanUpWindow
27
CDXAppBase elvégzi nekünk A program váza InitWindow InitD3DRenderCleanUpD3D CleanUpWindow
28
CMyDXApp Ezeket az eljárásokat viszont már változtatjuk. A program váza InitWindow InitD3DRenderCleanUpD3D CleanUpWindow
29
CDXApp.h
30
CDXMyApp::CDXMyApp CDXMyApp::CDXMyApp(void) { }
31
CDXMyApp::~CDXMyApp CDXMyApp::~CDXMyApp(void) { }
32
HRESULT CDXMyApp::InitD3D() { m_pD3D = Direct3DCreate9( D3D_SDK_VERSION ); if (!m_pD3D) { return E_FAIL; }... DXAppBase.h-ban: class CDXAppBase {... protected: LPDIRECT3D9 m_pD3D;... };
33
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
34
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
35
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;... DXAppBase.h-ban: class CDXAppBase {... protected: D3DPRESENT_PARAMETERS m_d3dpp;... }; void ZeroMemory( PVOID Destination, SIZE_T Length ); Destination: a cím, ahonnan kezdve 0-val töltjük fel a memóriát Length: a 0-val feltöltendő memóriaterület nagysága bájtban
36
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) );
37
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.
38
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.
39
HRESULT CDXMyApp::InitD3D()... HRESULT hr = m_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &m_d3dpp, &m_pD3DDevice);...
40
IDirect3D9::CreateDevice HRESULT CreateDevice( UINT Adapter, 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
41
IDirect3D9::CreateDevice HRESULT CreateDevice( UINT Adapter, D3DDEVTYPE DeviceType, 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).
42
IDirect3D9::CreateDevice HRESULT CreateDevice( UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, 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.
43
IDirect3D9::CreateDevice HRESULT CreateDevice( UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS * pPresParams, IDirect3DDevice9 ** ppRetDeviceInterface ); BehaviorFlags: egyéb opciók a device létrehozásához (hardveres vagy szoftveres vertexfeldolgozás stb.)
44
IDirect3D9::CreateDevice HRESULT CreateDevice( UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS * pPresParams, IDirect3DDevice9 ** ppRetDeviceInterface ); pPresParams: lásd korábban
45
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.
46
HRESULT CDXMyApp::InitD3D()... if( FAILED( hr ) ) { return E_FAIL; } return S_OK; }
47
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; }
48
VOID CDXMyApp :: ReleaseDeviceObjects Az eszközmemóriába kerülő erőforrások felszabadításának kódja kerül ide Mivel most nincs ilyen, ez is üres: VOID CDXMyApp:: ReleaseDeviceObjects() { }
49
VOID CDXMyApp :: CleanUpD3D() { if (m_pD3DDevice) { m_pD3DDevice->Release(); m_pD3DDevice = NULL; } if (m_pD3D) { m_pD3D->Release(); m_pD3D = NULL; } }
50
VOID CDXMyApp :: FrameUpdate() A kirajzolás a Render függvényben fog történni A FrameUpdate()-ben a kirajzolás logikai részét meghatározó műveleteket végezzük majd el (modellek mozgatása, különböző transzformációk elvégzése stb.) Egyelőre ez is üres
51
VOID CDXMyApp ::Render() { if (!m_pD3DDevice) return; if( SUCCEEDED(m_pD3DDevice-> BeginScene() ) ) {... Ha a device pointer valamiért NULL, akkor még ne rendereljünk Bejelentjük, hogy rajzolni fogunk, jelezzük az eszköz felé (vagyis az általa reprezentált grafikus megjelenítésben részt vevő hardverek felé), hogy elkezdjük a színtér kirajzolását.
52
VOID CDXMyApp ::Render()... m_pD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0); }
53
IDirect3DDevice9::Clear HRESULT Clear( DWORD Count, CONST D3DRECT * pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil ); Count: amennyiben több téglalap alakú területen szeretnénk törölni, akkor itt a téglalapok számát kell megadni – ha a pRects!=0, akkor ez sem lehet 0
54
IDirect3DDevice9::Clear HRESULT Clear( DWORD Count, CONST D3DRECT * pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil ); pRects: A törlendő téglalapokat tartalmazó tömbre mutató pointer. Ha NULL, akkor a megjelenítési mező egészét töröljük.
55
IDirect3DDevice9::Clear HRESULT Clear( DWORD Count, CONST D3DRECT * pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil ); Flags: melyik felületet(eket) (surface) töröljük: D3DCLEAR_TARGET: azt, ahová renderelünk D3DCLEAR_ZBUFFER D3DCLEAR_STENCIL Bináris vagy (|) karakterrel többet is választhatunk
56
IDirect3DDevice9::Clear HRESULT Clear( DWORD Count, CONST D3DRECT * pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil ); Color: ha a renderelési felületet is töröljük, akkor ezzel a színnel fogjuk feltölteni. D3DCOLOR_* makrók (* lehet XRGB, ARGB stb.)
57
IDirect3DDevice9::Clear HRESULT Clear( DWORD Count, CONST D3DRECT * pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil ); Z: ha a Z-buffert is töröljük, akkor ez az érték kerül bele a korábbiak helyére A Z-bufferben az értékek 0 és 1 közötti lebegőpontos számok Az adott pixelben látható pont távolsága
58
IDirect3DDevice9::Clear HRESULT Clear( DWORD Count, CONST D3DRECT * pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil ); Stencil: ha a Stencil buffert is töröljük, akkor pedig ez az érték kerül bele a korábbiak helyére 0-tól 2^n-1 –ig terjedhet az értéke, ahol n a stencil buffer bitmélysége
59
VOID CDXMyApp ::Render()... FrameUpdate(); m_pD3DDevice->EndScene(); } m_pD3DDevice->Present( NULL, NULL, NULL, NULL); }
61
Feladat Változtassuk a kirajzolási színt az idő függvényében! timeGetTime(): a Windows indulása óta eltelt milliszekundumok számát adja vissza (DWORD-ben)
62
Tartalom 1. DirectX Graphics felépítése 2. Első DirectX-es alkalmazás 3. Háromszög kirajzolás
63
Program Ezt töltsük le: http://cg.inf.elte.hu/~valasek/02/01_Elso_DX. zip http://cg.inf.elte.hu/~valasek/02/01_Elso_DX. zip
64
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.
66
Pipeline Vertex shader Fragment shader
67
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
68
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} };
69
Direct3D primitívjei Pontlistá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 );
70
Direct3D primitívjei Szakaszlistá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 );
71
Direct3D primitívjei Linestrip Csatlakozó szakaszsorozat, legalább két pontot meg kell adni d3dDevice->DrawPrimitive( D3DPT_LINESTRIP, 0, 5 );
72
Direct3D primitívjei Háromszög lista Különálló háromszögek listája, 3*n pontot kell megadni d3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 2 );
73
Direct3D primitívjei Há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);
74
Direct3D primitívjei Há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 );
75
Vertexek A csúcspontokat (vertexeket) vertex bufferekben tároljuk A vertex bufferek pedig erőforrások
76
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.
77
Erőforrások DirectX-ben Usage 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. D3DUSAGED3DUSAGE 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!
78
Erőforrások DirectX-ben Format Az erőforrás tárolási formátumát adja meg D3DFORMAT-ban találhatóak a lehetséges értékei D3DFORMAT 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.
79
Erőforrások DirectX-ben Pool 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. D3DPOOLD3DPOOL
80
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.
81
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.
82
Erőforrások DirectX-ben Type 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
83
Erőforrások DirectX-ben Mű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
84
Erőforrások DirectX-ben Lock 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 ...
85
Erőforrások DirectX-ben Lock 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
86
Erőforrások DirectX-ben Unlock Miután elvégeztük a dolgunkat a bufferrel Unlock-olni kell!
87
Erőforrások DirectX-ben Vertex 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
88
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
89
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...
90
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
92
Flexible Vertex Format struct CUSTOMVERTEX { FLOAT x, y, z; DWORD color; }; #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)
93
Vertex Buffer használata - létrehozás Először a geometriánkat kell meghatároznunk Ez a rendszermemóriában történik, saját vertex struktúrából felépített tömb segítségével Létrehozzuk a szükséges méretű VB-t (a Device-szon keresztül) Feltöltjük (lock-oljuk) a VB-t = a rendszermemóriából a VB memóriaosztályának megfelelő memóriába másolunk
94
Vertex Buffer használata - kirajzolás A sikeres BeginScene() eljáráshívás után: Be kell állítani az FVF-ünket (SetFVF) A VB bufferünket vertex forrássá (SetStreamSource) Kirajzolni a DrawPrimitive-vel
95
Új adattag class CDXVerticesApp : public CDXAppBase {... private: LPDIRECT3DVERTEXBUFFER9 m_pVB;
96
FVF deklaráció DXVerticesApp.cpp struct VERTEX { D3DXVECTOR3 P; DWORD c; }; static const DWORD FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE; A programunkban az eltárolt csúcspontokat így látjuk, ezeken az adattagokon keresztül 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
97
Mit fogunk tenni? Létrehozunk egy 3 elemű tömböt aminek az elemei VERTEX 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
98
HRESULT CDXVerticesApp:: InitDeviceObjects() { Vertex vertices[] = { { D3DXVECTOR3(0,1,0), D3DCOLOR_XRGB(255,0,0) }, { D3DXVECTOR3(1,-1,0), D3DCOLOR_XRGB(0,255,0) }, { D3DXVECTOR3(-1,-1,0), D3DCOLOR_XRGB(0,0,255) }, };... x y z Szín RGB komponensekből
99
HRESULT CDXVerticesApp:: InitDeviceObjects()... HRESULT hr = m_pD3DDevice-> CreateVertexBuffer( sizeof(vertices), 0, FVF, D3DPOOL_DEFAULT, &m_pVB, NULL );...
100
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
101
IDirect3DDevice9::CreateVertexBuffer HRESULT CreateVertexBuffer( UINT Length, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer9** ppVertexBuffer, HANDLE* pSharedHandle ); Usage: lehet 0, egyébként ugyanaz mint eddig.
102
IDirect3DDevice9::CreateVertexBuffer HRESULT CreateVertexBuffer( UINT Length, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer9** ppVertexBuffer, HANDLE* pSharedHandle ); FVF: a használni kívánt FVF
103
IDirect3DDevice9::CreateVertexBuffer HRESULT CreateVertexBuffer( UINT Length, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer9** ppVertexBuffer, HANDLE* pSharedHandle ); Pool: memóriaosztály
104
IDirect3DDevice9::CreateVertexBuffer HRESULT CreateVertexBuffer( UINT Length, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer9** ppVertexBuffer, HANDLE* pSharedHandle ); ppVertexBuffer: kimeneti érték
105
IDirect3DDevice9::CreateVertexBuffer HRESULT CreateVertexBuffer( UINT Length, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer9** ppVertexBuffer, HANDLE* pSharedHandle ); pSharedHandle: legyen NULL
106
HRESULT CDXVerticesApp:: InitDeviceObjects()... VOID* pVertices; if( FAILED( m_pVB->Lock( 0, sizeof(vertices), &pVertices, 0 ) ) ) return E_FAIL; memcpy(pVertices, vertices, sizeof(vertices) ); m_pVB->Unlock();...
107
IDirect3DVertexBuffer9::Lock HRESULT Lock(UINT OffsetToLock, UINT SizeToLock, VOID ** ppbData, DWORD Flags ); OffsetToLock: a vertexbuffer kezdetéhez képest hány bájttal kezdődően lock-oljunk
108
IDirect3DVertexBuffer9::Lock HRESULT Lock(UINT OffsetToLock, UINT SizeToLock, VOID ** ppbData, DWORD Flags ); SizeToLock: hány bájtnyi vertexadatot lockoljunk
109
IDirect3DVertexBuffer9::Lock HRESULT Lock(UINT OffsetToLock, UINT SizeToLock, VOID ** ppbData, DWORD Flags ); ppbData: kimeneti érték, mutató egy memóriabuffer címére ahová a visszaadott adatokat másolja
110
IDirect3DVertexBuffer9::Lock HRESULT Lock(UINT OffsetToLock, UINT SizeToLock, VOID ** ppbData, DWORD Flags ); Flags: milyen típusú lock-ot akarunk: D3DLOCK_DISCARD: üres adatokat kapunk vissza D3DLOCK_READONLY: csak olvasni stb.
111
HRESULT CDXVerticesApp:: ReleaseDeviceObjects() VOID CDXVerticesApp:: ReleaseDeviceObjects() { if( m_pVB != NULL ) { m_pVB->Release(); m_pVB = NULL; } }
112
VOID CDXVerticesApp::Render()... // színtér renderelése m_pD3DDevice-> SetStreamSource( 0, m_pVB, 0, sizeof(CUSTOMVERTEX));
113
IDirect3DDevice9::SetStreamSource HRESULT SetStreamSource( UINT StreamNumber, IDirect3DVertexBuffer9 * pStreamData, UINT OffsetInBytes, UINT Stride ); StreamNumber: a folyam sorszáma 0-tól maxstream-1-ig
114
IDirect3DDevice9::SetStreamSource HRESULT SetStreamSource( UINT StreamNumber, IDirect3DVertexBuffer9 * pStreamData, UINT OffsetInBytes, UINT Stride ); pStreamData: mutató egy vb interfészre
115
IDirect3DDevice9::SetStreamSource HRESULT SetStreamSource( UINT StreamNumber, IDirect3DVertexBuffer9 * pStreamData, UINT OffsetInBytes, UINT Stride ); OffsetInBytes: a stream és a vertexadat kezdete közti eltérés, bájtban
116
IDirect3DDevice9::SetStreamSource HRESULT SetStreamSource( UINT StreamNumber, IDirect3DVertexBuffer9 * pStreamData, UINT OffsetInBytes, UINT Stride ); Stride: mekkora „léptékben” olvassa ki a vertexbufferből az adatokat
117
VOID CDXVerticesApp::Render()... m_pD3DDevice-> SetFVF(D3DFVF_CUSTOMVERTEX); m_pD3DDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1);...
118
IDirect3DDevice9::SetFVF HRESULT SetFVF( DWORD FVF ); Az aktuális vertex streamhez használandó FVF-t adja meg
119
IDirect3DDevice9::DrawPrimitive HRESULT DrawPrimitive( D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount ); PrimitiveType: milyen típusú primitív rajzolásához való vertexeket adtunk meg (pontlista, szakaszlista, stbÖ
120
IDirect3DDevice9::DrawPrimitive HRESULT DrawPrimitive( D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount ); StartVertex: a vertexbuffer hányadik eleme legyen az első csúcspontja a primitívnek (azt, hogy egy csúcspont mekkora helyet foglal, a stride-ból tudja)
121
IDirect3DDevice9::DrawPrimitive HRESULT DrawPrimitive( D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount ); PrimitiveCount: a kirajzolandó primitívek száma. Ld. primitíveknél, hogy ilyenkor mennyi csúcspontnak kell legalább lennie a vb-ben.
122
Feladat Rajzoljunk ki a képernyő közepére egy fél képernyő magas és fél képernyő széles négyszöget! Razjoljunk ki a képernyő közepére egy szabályos hétszöget!
123
Kiszervezés osztályba Hozzunk létre egy CMyTrig osztályt, ami magába foglalja A kirajzolandó geometriát A létrehozó és megsemmisítő függvényt A frissítési és kirajzolási függvényt
124
CMyTrig.h #pragma once #include struct Vertex { D3DXVECTOR3 p; // pozíció DWORD c; // szín };
125
CMyTrig.h class CMyTrig { public: CMyTrig(void); ~CMyTrig(void); void InitDeviceObjects( LPDIRECT3DDEVICE9 _pD3DDevice ); void ReleaseDeviceObjects( LPDIRECT3DDEVICE9 _pD3DDevice ); void Update(); void Draw( LPDIRECT3DDEVICE9 _pD3DDevice ); void SetVertex(int i, D3DXVECTOR3 p, DWORD c);
126
CMyTrig.h private: void FillBuffer(); LPDIRECT3DVERTEXBUFFER9 m_pVB; static const DWORD FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE; Vertex vertices[3]; };
127
Feladat Valósítsuk meg ezt az osztályt az előző kód alapján, annak megfelelően, ahogyan a http://cg.inf.elte.hu/~valasek/02/02_DX_Ent1. zip kódban hasznljuk! http://cg.inf.elte.hu/~valasek/02/02_DX_Ent1. zip
Hasonló előadás
© 2024 SlidePlayer.hu Inc.
All rights reserved.