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