Az előadás letöltése folymat van. Kérjük, várjon

Az előadás letöltése folymat van. Kérjük, várjon

Számítógépes grafika DirectX 2. gyakorlat. Emlékeztető Előző órán áttekintettük a szükséges WinAPI- s alapokat Illetve röviden beletekintettünk a félév.

Hasonló előadás


Az előadások a következő témára: "Számítógépes grafika DirectX 2. gyakorlat. Emlékeztető Előző órán áttekintettük a szükséges WinAPI- s alapokat Illetve röviden beletekintettünk a félév."— Előadás másolata:

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); }

60

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.

65

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

91

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


Letölteni ppt "Számítógépes grafika DirectX 2. gyakorlat. Emlékeztető Előző órán áttekintettük a szükséges WinAPI- s alapokat Illetve röviden beletekintettünk a félév."

Hasonló előadás


Google Hirdetések