DirectX (19.)

V minulΘ lekci jsme probrali ·plnΘ zßklady komponenty Direct3D. Dnes si vytvo°φme prvnφ ukßzkovou aplikace na bßzi Direct3D. Jist∞ tuÜφte, ₧e to nebude hra roku 2003, ale n∞kde zaΦφt musφme.

19.1. Objekt Direct3D

Tak jako ka₧dß komponenta DirectX, i Direct3D mß sv∙j objekt Direct3D8. Jak u₧ to u DirectX b²vß, pracujeme pouze s rozhranφm objekt∙, tak₧e budeme hledat rozhranφ IDirect3D8 (pracujeme s SDK verze 8.0 nebo 8.1).

Abychom mohli pou₧φt vÜechny funkce a struktury Direct3D, musφme vlo₧it do projektu n∞kolik hlaviΦkov²ch soubor∙ a p°ilinkovat pßr knihoven. Pozd∞ji si vytvo°φme samostatnou knihovnu, kde budeme pou₧φvat Direct3D a v hlavnφm hlaviΦkovΘm souboru musφme mφt tyto °ßdky:

//
// Define version of Direct3D
#define DIRECT3D_VERSION 0x0800

//
// Include Direct3D headers
#include <d3d8.h>
#include
<D3dx8core.h>

Prvnφ definicφ upozornφme p°ekladaΦ jakou verzi Direct3D chceme pou₧φt. Dßle pou₧ijeme dva hlaviΦkovΘ soubory pro jßdro D3D a pro rozÜφ°enou knihovnu D3DX. Abychom toto mohli ud∞lat, je d∙le₧itΘ mφt sprßvn∞ nainstalovanΘ DX SDK 8.0 a sprßvn∞ uvedenΘ  cesty v nastavenφ v²vojovΘho prost°edφ.

Dßle je nutnΘ p°ilinkovat dv∞ knihovny: d3d8.lib a D3dx8.lib. To provedeme v dialogu Settings... konkrΘtnφho projektu na kart∞ Linker (Input). Tento postup jsme ji₧ n∞kolikrßt provßd∞li, tak₧e nenφ nutnΘ vÜe podrobn∞ rozepisovat. Op∞t je nutnΘ mφt sprßvn∞ nastavenΘ cesty, tentokrßt pro knihovny.

19.2. Projekt D3DExample1

Vytvo°te si tedy prßzdnou Win32 aplikaci (projekt nazv∞te D3DExample1). Projekt mß obsahovat jen funkci WinMain(). V dneÜnφ lekci nebudeme vytvß°et slo₧it∞jÜφ strukturu projektu a budeme psßt Direct3D k≤d p°φmo do projektu D3DExample1. Pozd∞ji tento k≤d odd∞lφme do samostatnΘ knihovny podobn∞ jako tomu bylo v p°φpad∞ DirectDraw a vlastn∞ vÜech do te∩ probran²ch komponent DirectX.

Na zaΦßtek souboru D3DExample1.cpp vlo₧te v²Üe uveden² k≤d, abychom mohli pou₧φt funkce Direct3D. Nezapome≥te samoz°ejm∞ vlo₧it takΘ knihovnu p°es dialog Settings projektu. Nynφ u₧ mßte projekt p°ipraven² pro Direct3D a m∙₧ete volat libovolnΘ metody. PφÜeme ovÜem grafickou aplikaci, kterß se neobejde bez okna, tak₧e ze vÜeho nejd°φv je nutnΘ zaregistrovat t°φdu okna a potΘ okno vytvo°it. I tento postup jsme ji₧ n∞kolikrßt probφrali, ale pro ·plnost k≤d jeÜt∞ jednou zopakuji.

Vytvo°φme proto novΘ funkce (nezapome≥te vlo₧it prototypy) WinInit() a MainWndProc(). WinInit() zaregistruje t°φdu okna a okno podle tΘto t°φdy vytvo°φ. MainWndProc() je obslu₧nß funkce okna, zde tedy budeme obsluhovat zprßvy p°ichßzejφcφ naÜemu oknu:

HRESULT WinInit(HINSTANCE hInstance)
{
    DWORD dwRet;
    WNDCLASSEX wc;
   
//
    // Register the Window Class
   
wc.cbSize = sizeof(WNDCLASSEX);
    wc.lpszClassName = "D3DExample1Class";
    wc.lpfnWndProc = MainWndProc;
    wc.style = CS_VREDRAW|CS_HREDRAW;
    wc.hInstance = hInstance;
    wc.hIcon = NULL;
    wc.hCursor = NULL;
    wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
    wc.lpszMenuName = NULL;
    wc.hIconSm = NULL;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
   
//
    // Register window class
   
if(RegisterClassEx(&wc) == 0 ) {
        dwRet = GetLastError();
        return dwRet;
    }
   
//
    // Create new main window

    g_hWnd = CreateWindow("D3DExample1Class", "D3DExample1Window",
                            0, 0, 0, 1024, 768, NULL, NULL, hInstance, NULL);
    if(!g_hWnd) {
        dwRet = GetLastError();
        return dwRet;
    }
    ShowWindow(g_hWnd, SW_SHOW);
    UpdateWindow(g_hWnd);
    dwRet = ERROR_SUCCESS;

    return dwRet;
}

LRESULT CALLBACK MainWndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch(msg) {
    case WM_SETCURSOR:
        SetCursor(NULL);
        break;

    case WM_DESTROY:
       
// Cleanup and close the app
       
PostQuitMessage( 0 );
        return 0L;

    case WM_SYSCOMMAND:
       
// Prevent moving/sizing and power loss in fullscreen mode
       
switch( wParam )
        {
        case SC_MOVE:
        case SC_SIZE:
        case SC_MAXIMIZE:
        case SC_KEYMENU:
        case SC_MONITORPOWER:
            return 1;
        }
        break;
    }
    return DefWindowProc(hWnd, msg, wParam, lParam);
}

Funkce nebudu blφ₧e rozebφrat, proto₧e se jednß o klasickΘ Windows API. Dßle jeÜt∞ trochu upravφme funkci WinMain() a aplikaci zkusφme zkompilovat:

int APIENTRY WinMain(HINSTANCE hInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR lpCmdLine,
                    int nCmdShow)
{
    // Window initialization
    WinInit(hInstance);


    MSG msg;
    // Run message loop
    while( TRUE )
    {
 
       // Look for messages, if none are found then
        // update the state and display it
 
      if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
        {
            if( 0 == GetMessage(&msg, NULL, 0, 0 ) )
            {
                // WM_QUIT was posted, so exit
                return (int)msg.wParam;
            }

            // Translate and dispatch the message
            TranslateMessage( &msg );
            DispatchMessage( &msg );
        }
        else
        {
       
    UpdateFrame();
        }
}

return 0;
}

Zde je nutnΘ zavolat funkci, kterß vytvo°φ okno a spustit smyΦku zprßv.

Nynφ zaΦneme pou₧φvat Direct3D a zaΦneme s objektem Direct3D. Tento objekt vytvo°φ funkce Direct3DCreate8() a vrßtφ ukazatel na rozhranφ IDirect3D8. Pomocφ tohoto rozhranφ vytvo°φme tzv. D3D za°φzenφ (device).

Ud∞lejme tedy dva globßlnφ objekty:

IDirect3D8       *g_lpD3DObject;
IDirect3DDevice8 *g_lpD3DDevice;

PotΘ ve funkci WinMain() zinicializujeme objekt Direct3D a ulo₧φme rozhranφ do prom∞nnΘ g_lpD3DObject:

// D3D inicialization
g_lpD3DObject = Direct3DCreate8(D3D_SDK_VERSION);
if(!g_lpD3DObject) {
    MessageBox(NULL, "Please, install DirectX 8.1.", "Error", MB_ICONERROR);
    Clean();
    return 1;
}

Tφmto vytvo°φme objekt Direct3D a v p°φpad∞ ne·sp∞chu zobrazφme hlßÜku.  Konstanta D3D_SDK_VERSION zajistφ, ₧e naÜe aplikace bude zkompilovanß se sprßvnou verzi DirectX.

Nynφ nadefinujeme pßr konstant, kter²mi budeme ovlßdat chovßnφ aplikace:

#define WINDOWED     TRUE
#define RES_X         800
#define RES_Y         600
#define DEPTH         16

Jednß se rozliÜenφ a barevnou hloubku (s tou je to trochu slo₧it∞jÜφ, ale  v naÜem jednoduchΘm p°φpad∞ nßm to postaΦφ) a o to, zda-li aplikace b∞₧φ v okn∞ Φi v re₧imu fullscreen. Dßle musφme naplnit strukturu D3DPRESENT_PARAMETERS a vytvo°it device. Tato struktura mß mnoho atribut∙, ale v prvnφm p°φklad∞ nßs toho moc zajφmat nebude:

D3DPRESENT_PARAMETERS d3dDeviceParam;
//
// Set properties of device
ZeroMemory(&d3dDeviceParam, sizeof(d3dDeviceParam));
d3dDeviceParam.Windowed = WINDOWED;
d3dDeviceParam.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dDeviceParam.BackBufferWidth = RES_X;
d3dDeviceParam.BackBufferHeight = RES_Y;
d3dDeviceParam.BackBufferFormat = (DEPTH == 16) ? D3DFMT_R5G6B5 : D3DFMT_X8R8G8B8;
d3dDeviceParam.BackBufferCount = 1;
d3dDeviceParam.hDeviceWindow = g_hWnd;
d3dDeviceParam.MultiSampleType = D3DMULTISAMPLE_NONE;

if(WINDOWED) {
    D3DDISPLAYMODE displaymode;
    RECT rcWindowClient;
    //
    // Get window position
    GetClientRect(g_hWnd, &rcWindowClient);
    // Get current display mode
    g_lpD3DObject->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &displaymode);
    //
    // Set size of back buffer
    d3dDeviceParam.BackBufferWidth = rcWindowClient.right - rcWindowClient.left;
    d3dDeviceParam.BackBufferHeight = rcWindowClient.bottom - rcWindowClient.top;
   
// Set display mode to current
    d3dDeviceParam.BackBufferFormat = displaymode.Format;
}

Nejprve celou strukturu vynulujeme a potΘ zinicializujeme n∞kterΘ atributy. Nastavujeme, zda-li aplikace b∞₧φ v okn∞ Φi nikoliv, typ prohazovßnφ p°ednφho a zadnφho bufferu, velikost a formßt zadnφho bufferu, poΦet zadnφch buffer∙, handle na okno aplikace, typ antialiasingu. Formßt zde nenastavujeme ·pln∞ korektn∞, ale sprßvnß inicializace je na delÜφ Φlßnek a probereme si ji v n∞kter²ch dalÜφch Φlßncφch. V druhΘ Φßsti nastavφme n∞kterΘ atributy zvlßÜ¥ pro p°φpad, kdy₧ aplikace b∞₧φ v okn∞. Zde je pot°eba nastavit velikost zadnφho bufferu stejnou jako je velikost okna a formßt bufferu musφ b²t stejn² jako aktußlnφ formßt nastaven² ve Windows. Tato struktura je velmi d∙le₧itß a tak si ji podrobn∞ probereme v p°φÜtφch lekcφch.

V dalÜφm kroku ji₧ m∙₧eme vytvo°it device pomocφ metody CreateDevice():

//
// Create Device
dwRet = g_lpD3DObject->CreateDevice(0, D3DDEVTYPE_HAL , g_hWnd,
                                    D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                    &d3dDeviceParam, &g_lpD3DDevice);
if(dwRet != D3D_OK) {
    MessageBox(NULL, "Cannot create device.", "Error", MB_ICONERROR);
    Clean();
    return 2;
}

Prvnφ parametr oznaΦuje po°adovΘ Φφslo adaptΘru ve vaÜem systΘmu. Op∞t v tomto jednoduchΘm p°φklad∞ nep°edpoklßdßme vφce ne₧ jeden grafick² adaptΘr. Dßle vy₧adujeme za°φzenφ typu HAL (tj. s hardwarovou akceleracφ). ╚tvrt² d∙le₧it² parametr oznaΦuje typ zpracovßnφ vertex∙, chceme softwarovΘ zpracovßnφ. P°edposlednφ parametr je ukazatel na strukturu D3DPRESENT_PARAMETERS, kterou jsme vytvo°ili v²Üe. V²sledek celΘ operace se ulo₧φ do poslednφho parametru v podob∞ ukazatele na rozhranφ IDirect3DDevice8.

19.3. Prvnφ troj·helnφk

V dalÜφ Φßsti p°φkladu vytvo°φme v okn∞ troj·helnφk tvo°en² t°emi transformovan²mi vertexy. Struktura vertexu musφ obsahovat polohu v 3D prostoru a proto₧e je to transformovan² vertex, musφ takΘ obsahovat atribut rhw. Dßle jsem p°idal do struktury barvu vertexu:

struct TLVERTEX {
    float x, y, z, rhw;
    DWORD dwColor;
};

SystΘm Direct3D ovÜem pot°ebuje v∞d∞t, co nßÜ vrchol obsahuje za atributy. Struktura vertexu se dß popsat n∞kolika konstantami:

#define TLVERTEXFORMAT (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)

Takto definujeme formßt vertexu, kter² mß pozici+rhw a dif·znφ barvu. Komponenta RHW v praxi p°edstavuje p°evrßcenou hodnotu vzdßlenosti vertexu od pozorovatele podΘl osy z. Tak₧e nap°φklad pokud jeden z vertex∙ bude mφt rhw=10.0 (ostatnφ 1.0), p°evrßcenß hodnota je 0.1 a tudφ₧ je tento vertex nejblφ₧e k pozorovatelovi (zkuste si to v praxi a uvidφte, ₧e tento vertex mß pak nejv∞tÜφ vßhu).

Nadefinujeme globßlnφ pole t°φ vertex∙ takto:

TLVERTEX arVertices[] = {
        {200.0f, 200.0f, 0.5f, 1.0f, 0xFFFF0000},
        {600.0f, 200.0f, 0.5f, 1.0f, 0xFF0000FF},
        {200.0f, 600.0f, 0.5f, 1.0f, 0xFFFFFF00}};

Poslednφ Φφslo je barva vrcholu: Φervenß, modrß a ₧lutß. M∙₧ete takΘ po₧φt makro D3DCOLOR_XRGB(r, g, b) (a=FF) nebo D3DCOLOR_ARGB(a, r, g, b). Z t∞chto vrchol∙ vytvo°φme nßÜ prvnφ troj·helnφk. Je nutnΘ si uv∞domit, ₧e sou°adnice jednotliv²ch vertex∙ jsou v m∞°φtku okna (2D sou°adnice na monitoru).

Direct3D vykresluje vrcholy z tzv. Vertex bufferu. Vrcholy jdou vykreslovat i p°φmo z naÜeho pole, ale sprßvn∞ se to d∞lß p°es vertexovΘ buffery. Objekt vertex bufferu vytvo°φme pomocφ metody objektu za°φzenφ CreateVertexBuffer() a ulo₧φme si ukazatel na rozhranφ IDirect3DVertexBuffer8.

//
// Create vertex buffer for our triangle
g_lpD3DDevice->CreateVertexBuffer(sizeof(TLVERTEX) * 3, D3DUSAGE_WRITEONLY, TLVERTEXFORMAT, D3DPOOL_DEFAULT, &g_lpD3DVB);

Jak vidφte metoda mß mno₧stvφ parametr∙, kterΘ si vzßp∞tφ vysv∞tlφme. Prvnφ parametr je velikost bufferu v bytech tj. my pot°ebujeme mφsto pro 3 vrcholy tak₧e 3x vynßsobφme velikost struktury TLVERTEX. Druh² parametr nastavuje vlastnosti bufferu, m∙₧ete zadat tyto hodnoty:

- D3DUSAGE_WRITEONLY - buffer urΦen jen pro zßpis tzn., ₧e vy z bufferu nem∙₧ete Φφst data. Direct3D vybere nejvhodn∞jÜφ mφsto v pam∞ti pro takov²to buffer, aby p°φstup k n∞mu byl co nejrychlejÜφ.
- D3DUSAGE_SOFTWAREPROCESSING - tento buffer bude pou₧φvßn v²hradn∞ se softwarov²m zpracovßnφm.
- D3DUSAGE_POINTS - buffer je urΦen pro point sprites. To jsou objekty slo₧enΘ z bod∙ nebo Φßstic.
- D3DUSAGE_DYNAMIC - buffer je dynamick² tj. b∞hem ₧ivota se m∞nφ jeho data. OvladaΦ tento buffer umφsti do AGP pam∞ti mφsto video pam∞tφ (op∞t kv∙li optimalizaci).
- a dalÜφ, kterΘ zatφm nebudeme vyu₧φvat.

DalÜφ parametr je formßt vklßdan²ch vertex∙. Nynφ vyu₧ijeme konstantu, kterou je popsan² nßÜ vrchol. Dßle tu mßme typ pam∞ti:

- D3DPOOL_DEFAULT - buffer je umφst∞n do takovΘ pam∞ti, kterß je nejlepÜφ pro dan² ·Φel vertex bufferu. NejΦast∞ji je to video nebo AGP pam∞¥. Pokud se device "ztratφ" je nutnΘ tyto buffery zcela zruÜit a znovu vytvo°it, p°φpadn∞ naplnit. O ztrßtßch za°φzenφ si povφme v dalÜφch lekcφch.
- D3DPOOL_MANAGED - buffer je vytvo°en v systΘmovΘ pam∞ti, ale pokud je pot°eba, je zkopφrovßn do pam∞ti vhodnΘ pro device. Dφky tomu, ₧e data jsou v RAM, nenφ pot°eba tyto buffery ruÜit p°i ztrßt∞ device.

Do poslednφho parametru je ulo₧ena adresa rozhranφ IDirect3DVertexBuffer8.

Dßle je nutnΘ vytvo°en² buffer naplnit daty:

TLVERTEX *pVertices;
// Fill vertex buffer
if(SUCCEEDED(g_lpD3DVB->Lock(0, 0, (BYTE**) &pVertices, 0))) {

    pVertices[0] = arVertices[0];
    pVertices[1] = arVertices[1];
    pVertices[2] = arVertices[2];

    g_lpD3DVB->Unlock();
}

Metodou Lock() uzamkneme buffer a m∙₧eme tak zapisovat p°φmo do bufferu. Metoda Lock() mß 4 parametry:

1. Offset v bytech odkud se majφ data zamknout. Pokud zadßte 0, je buffer uzamΦen od zaΦßtku.
2. Tento parametr urΦuje, jak velk² kus vertex bufferu bude uzamΦen. Pokud zadßte 0, je uzamΦen (zp°φstupn∞n) cel² buffer.
Pomocφ 3. parametru budeme p°istupovat k obsahu vertex bufferu.
4. Vlastnosti zamykßnφ, kterΘ si probereme v n∞kterΘ dalÜφ lekci.

V dalÜφm kroku p°ekopφrujeme obsah pole s vertexy do vertex bufferu. Mßme jen t°i vrcholy, tak₧e nenφ nutnΘ psßt cyklus. Nakonec buffer op∞t odemkneme. Stejn² buffer m∙₧ete uzamknout i n∞kolikrßt, ale pro ka₧dΘ volßnφ metody Lock() je nutnΘ volat i metodu Unlock().

Nakonec vytvo°φme funkci UpdateFrame(), ve kterΘ nßÜ troj·helnφk vykreslφme:

void UpdateFrame()
{
    if(g_lpD3DDevice) {
 
      //
        // Clear the back buffer to a blue color
  
     g_lpD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(100, 100, 100), 0, 0);
   
    //
        // Begin rendering
   
    if(SUCCEEDED(g_lpD3DDevice->BeginScene())) {
            //
            // Set current vertex buffer
            g_lpD3DDevice->SetStreamSource(0, g_lpD3DVB, sizeof(TLVERTEX));
            // and type of vertex data
            g_lpD3DDevice->SetVertexShader(TLVERTEXFORMAT);
            //
            // Draw triangle
            g_lpD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);
            g_lpD3DDevice->EndScene();
        }
        // Flip front/back buffers
        g_lpD3DDevice->Present(NULL, NULL, NULL, NULL);
    }
}

Zkontrolujeme platnost ukazatele na za°φzenφ a vyΦistφme zadnφ buffer (a nastavφme mu takovou podivnou Üedivou barvu). Metodou Clear() m∙₧eme vyΦistit i Z-buffer, ale ten zatφm nepou₧φvßme. Dßle je nutnΘ volat metody BeginScene(), abychom mohli zaΦφt vykreslovat vrcholy. Metodou SetStreamSource() nastavφme vstupnφ vertex buffer, ze kterΘho se budou Φφst vertexovß data (pozor, tato metoda je Φasov∞ velmi nßroΦnß a proto je dobrΘ ji volat co nejmΘn∞). DalÜφm p°φkazem nastavφme vertex shader, v naÜem p°φpad∞ ne programovateln². Toto je pot°eba ud∞lat v₧dy (i kdy₧ nepou₧φvßte programovateln² vertex shader), aby se v∞d∞lo, co se s vrcholy bude d∞lat (zda jsou transformovanΘ, osv∞tlenΘ atd.) No a nakonec zavolßme metodu DrawPrimitive(), kterß vykreslφ po₧adovan² troj·helnφk. Prvnφ parametr udßvß typ vykreslovan²ch dat:
- D3DPT_POINTLIST - ve vertex bufferu je ulo₧eno pole bod∙ a jako polygon se bere bod.
- D3DPT_LINELIST -  ve vertex bufferu je ulo₧eno pole Φar a jako polygon se bere spojnice dvou bod∙. Spojujφ se dva sousednφ vertexy (1. vrchol s 2., 3. se 4. atd.).
- D3DPT_LINESTRIP  - vrcholy se spojujφ vÜechny popo°ad∞ tj. 1. vrchol s 2., 2. vrchol s 3., 3. vrchol se 4. atd.
- D3DPT_TRIANGLELIST - z vertex bufferu se vezmou 3 vrcholy a vyrenderuje se troj·helnφk, potΘ se vezmou dalÜφ t°i vrcholy a renderuje se dalÜφ troj·helnφk nezßvisle na tom prvnφm.
- D3DPT_TRIANGLESTRIP - nejprve se vyrenderuje prvnφ troj·helnφk, potΘ se vezme 4. vrchol a vyrenderuje se dalÜφ troj·helnφk, kter² je tvo°en 2.,3. a 4. vrcholem. Vznikne pßs troj·helnφk∙.
- D3DPT_TRIANGLEFAN - je to podobnΘ jako u pas∙, akorßt vÜechny troj·helnφky sdφlejφ jeden vrchol a vznikne takov² v∞jφ°. Podrobn∞ji si tyto typy renderovan²ch polygon∙ probereme v p°φÜtφ lekci.

Druh² parametr je po°adφ vertexu, kter² se bude vykreslovat jako prvnφ. A nakonec t°etφ udßvß poΦet polygon∙, kterΘ se majφ vykreslit. Zde je t°eba dßt pozor na to, jak² typ polygonu vykreslujeme. Mßme-li ve vertexu bufferu 3 vrcholy, tak mu₧eme vytvo°it 1 troj·helnφk pomocφ D3DPT_TRIANGLELIST nebo 3 body pomocφ  D3DPT_POINTLIST! V prvΘm p°φpad∞ bude poΦet polygon∙ rovno jednΘ a ve druhΘ t°em!!! Nezapome≥te ukonΦit scΘnu metodou EndScene().

Na ·pln² zßv∞r je t°eba prohodit zadnφ a p°ednφ buffer metodou Present().

Pro ·plnost jsem jeÜt∞ p°idal metodu Clean(), kterß uvolnφ vÜechny objekty Direct3D p°i ukonΦenφ aplikace Φi v p°φpad∞ n∞jakΘ chyby:

void Clean() {

    if(g_lpD3DDevice) {
        g_lpD3DDevice->Release();
    }
    if(g_lpD3DObject) {
        g_lpD3DObject->Release();
    }
    if(g_lpD3DVB) {
        g_lpD3DVB->Release();
    }
}

19.4. Zßv∞r

V dneÜnφ lekci jsme vytvo°ili jednoduch² p°φklad zalo₧en² na Direct3D, i kdy₧ to pravΘ 3D samoz°ejm∞ nebylo, proto₧e jsme vykreslovali pouze transformovanΘ vrcholy. TakΘ jsme se nauΦili pou₧φvat vertex buffery, ve kter²ch jsou ulo₧eny vrcholy objekt∙.

V p°φÜtφ lekci si povφme n∞co tzv. index bufferech. V t∞chto bufferech je ulo₧eno po°adφ vrchol∙, kterΘ tvo°φ jednotlivΘ polygony. Nap°φklad si p°edstavte, ₧e chcete nakreslit Φtverec, kterß mß 4 vrcholy. Kdybychom ovÜem m∞li k dispozici jen vertex buffer, museli bychom pou₧φt vrchol∙ 6, proto₧e Φtverec mß dva troj·helnφky. Dφky index buffer∙m ovÜem staΦφ skuteΦn∞ 4 vrcholy a n∞kterΘ se vyu₧ijφ vφcekrßt.

T∞Üφm se p°φÜt∞ nashledanou.

Ji°φ Formßnek