500 likes | 633 Views
Számítógépes grafika. DirectX 7. gyakorlat. Emlékeztető. Múlt órán mesheket és transzformációkat használtunk Most primitívkirajzoláshoz nézünk meg egy hasznos dolgot. Tartalom. Index pufferek Függvénykirajzoló. Egy apró kényelmetlenség.
E N D
Számítógépes grafika DirectX 7. gyakorlat
Emlékeztető • Múlt órán mesheket és transzformációkat használtunk • Most primitívkirajzoláshoz nézünk meg egy hasznos dolgot
Tartalom • Index pufferek • Függvénykirajzoló
Egy apró kényelmetlenség • Az eddig megismert primitívjeink (triangle list/strip/fan stb) használatával néha túlságosan redundáns csúcsponttárolásr kényszerülünk • Háromszöglistával például egy egyszerű kocka tárolására 36 csúcspont kell • Ha mi adhatnánk meg, hogy milyen sorrendben történjen a csúcsok összekötése jelentős megtakarításokat érhetnénk el
Index buffer • Ha indexelt primitíveket használunk, akkor két tárolónk van: • Egy vertexbuffer a csúcspontoknak • És egy indexbuffer, ami vertexbufferbeli indexeket tárol. A benne lévő sorrendben köti össze a csúcsokat a D3D primitívkirajzoláskor
2. példa Indexelt primitívek
Mit csinálunk? • Egy kockát rajzolunk ki indexelt primitívek segítségével • Ez lesz az eredmény: http://people.inf.elte.hu/valasek/bevgraf/07/01_Indices.zip
Vertex shader 1/2 struct vertexIn { float3 p : POSITION; float4 c : COLOR0; }; struct hvertexOut { float4 p : POSITION; float4 c : COLOR0; };
Vertex shader 2/2 hvertexOut main(vertexIn IN, uniformfloat4x4 worldViewProj ) { hvertexOut OUT; float4 v = float4(IN.p.x,IN.p.y,IN.p.z,1.0); OUT.p = mul( worldViewProj, v); OUT.c = IN.c; return OUT; }
Pixel shader 1/2 struct fragment { float4 p : POSITION; float4 c : COLOR0; }; struct pixel { float4 c : COLOR; };
Pixel shader 2/2 pixel main( fragment IN, uniform float4 cl ) { pixel OUT; OUT.c = cl; return OUT; }
DXMyApp.h A CG Context a shader programjaink tárolója class CDXMyApp :public CDXAppBase{ ... private: CGcontext m_CGcontext; CGprogram m_CGprogram_vertex; CGprogram m_CGprogram_pixel; CGparameter m_CGparam_color; CGparameter m_CGparam_worldViewProj; ... A CGprogram típusú változók a shadereink azonosítóit fogják tartalmazni, amiken keresztül tud kommunikálni az alkalmazásunk a shader programokkal A CGparameter típusú változók a shaderprogramjaink „paraméterei” (uniform típusú változók), amelyeknek értéket adhatunk az alkalmazásunkból (pl. az m_CGparam_color a kirajzolási színt fogja jelenteni)
DXMyApp.h ... D3DXMATRIXA16 matProj; LPDIRECT3DVERTEXBUFFER9 m_pVB; LPDIRECT3DINDEXBUFFER9 m_pIB; float m_angleY; staticconstDWORD FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE; struct Vertex{ D3DXVECTOR3 p; DWORD c;}; }
CDXMyApp::CDXMyApp() CDXMyApp::CDXMyApp() { m_pVB = NULL; m_pIB = NULL; }
HRESULTCDXMyApp::InitDeviceObjects() HRESULTCDXMyApp::InitDeviceObjects() { m_pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE); CUSTOMVERTEX vertices[8]; ...
HRESULTCDXMyApp::InitDeviceObjects() HRESULT CDXMyApp::InitDeviceObjects() { Vertex vertices[] ={ {D3DXVECTOR3(-1,-1,-1), 0xffff0000 },{D3DXVECTOR3( 1,-1,-1), 0xff00ff00 },{D3DXVECTOR3( 1, 1,-1), 0xff0000ff },{D3DXVECTOR3(-1, 1,-1), 0xff808080}, }; ...
HRESULTCDXMyApp::InitDeviceObjects() ... if(FAILED( m_pD3DDevice-> CreateVertexBuffer( 8*sizeof(CUSTOMVERTEX), D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &m_pVB, NULL ) ) ) return E_FAIL; ...
HRESULTCDXMyApp::InitDeviceObjects() ... VOID* pVertices; if( FAILED( m_pVB->Lock( 0, sizeof(vertices), &pVertices, 0 ) ) ) return E_FAIL; memcpy( pVertices, vertices, sizeof(vertices) ); m_pVB->Unlock(); ...
HRESULTCDXMyApp::InitDeviceObjects() ... WORD indices[] = {0,3,1,3,2,1}; m_pD3DDevice->CreateIndexBuffer( sizeof(indices)*sizeof(WORD), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &m_pIB, NULL); ...
IDirect3DDevice9::CreateIndexBuffer • HRESULT CreateIndexBuffer( UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer9** ppIndexBuffer, HANDLE* pSharedHandle ); • Length: a létrehozandó indexbuffer mérete bájtban
IDirect3DDevice9::CreateIndexBuffer • HRESULT CreateIndexBuffer( UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer9** ppIndexBuffer, HANDLE* pSharedHandle ); • Usage: felhasználási mód, most D3DUSAGE_WRITEONLY
IDirect3DDevice9::CreateIndexBuffer • HRESULT CreateIndexBuffer( UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer9** ppIndexBuffer, HANDLE* pSharedHandle ); • Format: a buffer formátuma: • D3DFMT_INDEX16, D3DFMT_INDEX32: 16 vagy 32 bites indexeket használunk
IDirect3DDevice9::CreateIndexBuffer • HRESULT CreateIndexBuffer( UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer9** ppIndexBuffer, HANDLE* pSharedHandle ); • Pool: memóriaosztály
IDirect3DDevice9::CreateIndexBuffer • HRESULT CreateIndexBuffer( UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer9** ppIndexBuffer, HANDLE* pSharedHandle ); • ppIndexBuffer: a kimeneti érték, egy indexbuffer interfészre mutató pointer címe
IDirect3DDevice9::CreateIndexBuffer • HRESULT CreateIndexBuffer( UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer9** ppIndexBuffer, HANDLE* pSharedHandle ); • pSharedHandle: kötelezően NULL
HRESULTCDXMyApp::InitDeviceObjects() ... m_pIB->Lock( 0, sizeof(indices), &pIndices,0); memcpy( pIndices, indices, sizeof(indices) ); m_pIB->Unlock(); ...
CDXMyApp::InitDeviceObjects() Létrehozzuk a context-et és beállítjuk a CG-nek a device-unkat A shadereink txt fájlokban vannak, ezeket le kell fordítanunk. Itt a CG-n keresztül lekérdezzük az adott hardveren elérhető legújabb vertex és fragment shader verziókat m_CGcontext = cgCreateContext(); cgD3D9SetDevice( m_pD3DDevice ); CGprofile vertexProfile = cgD3D9GetLatestVertexProfile(); CGprofile pixelProfile = cgD3D9GetLatestPixelProfile(); constchar **vertexOptions[] ={ cgD3D9GetOptimalOptions( vertexProfile ),NULL,}; constchar **pixelOptions[] ={ cgD3D9GetOptimalOptions( pixelProfile ),NULL,}; Beállítjuk a shadereink fordítási paramétereit – a legújabb profilra akarunk fordítani
CDXMyApp::InitDeviceObjects() Hogyan hozzuk létre a shadert:CG_SOURCE: forrásfájlbólCG_OBJECT: lefordított objektum kódból ... m_CGprogram_vertex = cgCreateProgramFromFile( m_CGcontext, CG_SOURCE, "vs.cg", vertexProfile, "main", *vertexOptions ); ... Context amibe rakjuk a shadert Fordítandó shader fájlneve Fordítási cél shader modell A shader belépési pontja Compiler opciók
CDXMyApp::InitDeviceObjects() ... m_CGprogram_pixel = cgCreateProgramFromFile( m_CGcontext, CG_SOURCE, "ps.cg", pixelProfile, "main", *pixelOptions ); ...
CDXMyApp::InitDeviceObjects() A D3D-nek megfelelő shader létrehozása a lefordított CG shaderekből cgD3D9LoadProgram( m_CGprogram_vertex, TRUE, 0 ); cgD3D9LoadProgram(m_CGprogram_pixel, TRUE, 0 ); m_CGparam_worldViewProj = cgGetNamedParameter( m_CGprogram_vertex, "worldViewProj" ); m_CGparam_color = cgGetNamedParameter( m_CGprogram_pixel, "cl" ); ... A cgGetNamedParameter az első paraméterben megadott shaderből a második paraméterben megadott nevű, uniform változó azonosítóját adja vissza, hogy annak értékét a CG-n keresztül tudjuk a programunkból módosítani
CDXMyApp::InitDeviceObjects() ... D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI/2, m_BBWidth/(float)m_BBHeight, 0.1f, 100); return S_OK; }
VOID CDXMyApp:: ReleaseDeviceObjects() • VOID CDXMyApp::ReleaseDeviceObjects() • { cgD3D9SetDevice(NULL); cgDestroyProgram(m_CGprogram_vertex); cgDestroyProgram(m_CGprogram_pixel); cgDestroyContext(m_CGcontext); • if (m_pIB != NULL){ • m_pIB->Release(); • m_pIB = NULL; • } • if (m_pVB != NULL){ • m_pVB->Release(); • m_pVB = NULL; • } • }
VOID CDXMyApp::FrameUpdate() VOID CDXMyApp::FrameUpdate() { D3DXMATRIXA16 matWorld; D3DXMATRIXA16 matView; D3DXMatrixIdentity(&matWorld); D3DXMatrixRotationY(&matWorld, m_angleY); D3DXVECTOR3 vEye(0, 4, 4); D3DXVECTOR3 vAt(0, 0, 0); D3DXVECTOR3 vUp(0, 1, 0); ...
VOID CDXMyApp::FrameUpdate() ... D3DXMatrixLookAtLH(&matView, &vEye, &vAt, &vUp); D3DXMATRIX worldViewProj = matWorld * matView * matProj ; D3DXMatrixTranspose(&worldViewProj, &worldViewProj); cgD3D9SetUniformMatrix( m_CGparam_worldViewProj,&worldViewProj ); } A cgD3D9SetUniformMatrixsegítségével shadereink uniform float4x4 típusú paramétereinek adhatunk értéket, a második paraméterben megadott memóriacímen található tartalommal
VOIDCDXMyApp::Render() A cgD3D9SetUniform-mal egy shader uniform paraméternek adhatunk értéket (kivéve sampler-nek!) – az, hogy ez hány bájtnyi adat kell hogy legyen, a cgD3D9TypeToSize és cgGetParameterType segítségével kérdezhető le ... m_pD3DDevice->SetFVF(FVF); D3DXVECTOR4 vConstColor( 0.4f, 1.0f, 0.7f, 0.0f ); cgD3D9SetUniform( m_CGparam_color, &vConstColor ); cgD3D9BindProgram( m_CGprogram_vertex ); cgD3D9BindProgram( m_CGprogram_pixel ); m_pD3DDevice->SetStreamSource(0,m_pVB,0,sizeof(Vertex)); m_pD3DDevice->SetIndices( m_pIB ); m_pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 4, 0, 2); ... Aktiváljuk a vertex és fragment shadereinket
IDirect3DDevice9:: DrawIndexedPrimitive • HRESULT DrawIndexedPrimitive(D3DPRIMITIVETYPE Type,INT BaseVertexIndex, UINT MinIndex, UINT NumVertices, UINT StartIndex, UINT PrimitiveCount); • Type: kirajzolandó primitív típus
IDirect3DDevice9:: DrawIndexedPrimitive • HRESULT DrawIndexedPrimitive( D3DPRIMITIVETYPE Type,INT BaseVertexIndex, UINT MinIndex, UINT NumVertices, UINT StartIndex, UINT PrimitiveCount); • BaseVertex: a vertexpuffer hányadik eleme lesz a nullás indexű tag
IDirect3DDevice9:: DrawIndexedPrimitive • HRESULT DrawIndexedPrimitive( D3DPRIMITIVETYPE Type,INT BaseVertexIndex, UINT MinIndex, UINT NumVertices, UINT StartIndex, UINT PrimitiveCount); • MinIndex: legalacsonyabb vertex index érték, amit használunk a kirajzoláskor
IDirect3DDevice9:: DrawIndexedPrimitive • HRESULT DrawIndexedPrimitive( D3DPRIMITIVETYPE Type,INT BaseVertexIndex, UINT MinIndex, UINT NumVertices, UINT StartIndex, UINT PrimitiveCount); • NumVertices: felhasznált csúcspontok száma
IDirect3DDevice9:: DrawIndexedPrimitive • HRESULT DrawIndexedPrimitive( D3DPRIMITIVETYPE Type,INT BaseVertexIndex, UINT MinIndex, UINT NumVertices, UINT StartIndex, UINT PrimitiveCount); • StartIndex: indexpufferbeli offset
IDirect3DDevice9:: DrawIndexedPrimitive • HRESULT DrawIndexedPrimitive( D3DPRIMITIVETYPE Type,INT BaseVertexIndex, UINT MinIndex, UINT NumVertices, UINT StartIndex, UINT PrimitiveCount); • Type: kirajzolt primitívek száma
Feladat • Készítsünk egy kockát!
Feladat • Az egér fel/le mozgatásával az X tengely körül forogjon a kocka
Feladat • Csináljunk egy „repülő kamerát” • D3DXVec3Normalize(D3DXVECTOR3 *pOut,CONST D3DXVECTOR3 *pV) : egységvektorrá alakítja pV-t • D3DXVec3Cross( D3DXVECTOR3 * pOut, CONST D3DXVECTOR3 * pV1, CONST D3DXVECTOR3 * pV2 ) : pOut = pV1 x pV2
Tartalom • Index pufferek • Függvénykirajzoló
Letölteni • Innen: http://people.inf.elte.hu/valasek/bevgraf/07/02_Functions.zip