A je tu dalÜφ lekce o Direct3D, ve kterΘ se budeme podrobn∞ji v∞novat n∞kter²m detail∙m, kterΘ jsme minule nestihli. Nap°φklad rozÜφ°φme t°φdu XMesh. V druhΘ Φßsti lekce se podφvßme na sv∞tla.
Na zaΦßtku lekce se zmφnφm o materißlech. Podrobn∞ji se jimi budeme zab²vat v poslednφ Φßsti kapitoly, nynφ si jen povφme, co to vlastn∞ je! Materißlem urΦφme, jakΘ sv∞telnΘ slo₧ky se odrß₧ejφ od povrchu a jakΘ naopak povrch pohlcuje. Pozd∞ji se dovφme, ₧e mßme n∞kolik typ∙ osv∞tlenφ scΘny: ambient, diffuse, specular a emissive. V materißlu urΦφme, jak urΦit² povrch reaguje na vÜechny tyto typy sv∞tla. Zatφm se netrapte tφm, ₧e nevφte, jak si kter² typ osv∞tlenφ p°edstavit. To se dozvφte v Φßsti o sv∞tlech. M∙₧eme nap°φklad nastavit, ₧e ambient osv∞tlenφ se od danΘho povrchu ΦßsteΦn∞ odrß₧φ a t°eba jen modrß slo₧ka tohoto sv∞tla je pohlcena. Pak se tento objekt zdß b²t ₧lut², proto₧e do vaÜeho oka dopadajφ pouze ΦervenΘ a zelenΘ slo₧ky sv∞tla. Samoz°ejm∞ takΘ zßle₧φ, jakou barvu mß dopadajφcφ sv∞tlo a jakou barvu mß objekt samotn² (textura, barva vertexu).
V Direct3D je materißl reprezentovßn datovou strukturou D3DMATERIAL8:
typedef struct
_D3DMATERIAL8
{
D3DCOLORVALUE Diffuse;
D3DCOLORVALUE Ambient;
D3DCOLORVALUE Specular;
D3DCOLORVALUE Emissive;
float Power;
} D3DMATERIAL8;
D3DCOLORVALUE je dalÜφ struktura, kterß obsahuje
slo₧ky ΦervenΘ, modrΘ, zelenΘ a alpha kanßlu. Tyto hodnoty nastavujeme v rozmezφ
od 0.0 do 1.0, kde 0.0 je Φernß a 1.0 bφlß. Hodnotami, kterΘ jsou vyÜÜφ ne₧ 1.0
m∙₧ete zp∙sobit dalÜφ efekty "zv²ÜenΘho" odrazu nebo naopak zßporn²mi hodnotami
vytvo°φte "Φernou dφru".
Aby se materißl pou₧il, musφte zavolat metodu za°φzenφ SetMaterial() s ukazatelem na materißl. Materißly se nechovajφ jako zdroje, tudφ₧ je nemusφte uvol≥ovat p°i ztrßt∞ za°φzenφ, ale po resetu za°φzenφ je t°eba op∞tovn∞ nastavit poslednφ materißl.
Nev∞domky jsme tuto strukturu pou₧ili v minulΘ lekci, proto₧e jsme pot°ebovali nastavit n∞jak² zßkladnφ materißl pro vÜechny objekty ve scΘn∞. V dalÜφ Φßsti zjistφte, ₧e meshe majφ pro ka₧dou svou pod-Φßst jin² materißl.
P°φklad pou₧itφ materißlu z minulΘ lekce:
D3DMATERIAL8 mtrl;
ZeroMemory( &mtrl, sizeof(D3DMATERIAL8) );
mtrl.Diffuse.r = mtrl.Ambient.r = 1.0f;
mtrl.Diffuse.g = mtrl.Ambient.g = 1.0f;
mtrl.Diffuse.b = mtrl.Ambient.b = 1.0f;
mtrl.Diffuse.a = mtrl.Ambient.a = 1.0f;
m_lpD3DDevice->SetMaterial(&mtrl);
Nejprve trochu rozÜφ°φme tuto t°φdu z minulΘ lekce. ╪ekli jsme si, ₧e mesh se m∙₧e (a taky v∞tÜinou sklßdß) z vφce Φßstφ. Ka₧dß tato Φßst mß sv∙j materißl a texturu. Informace o materißlech a texturßch jsou ulo₧eny p°φmo v souboru .X, ze kterΘho model naΦφtßme. Nynφ trochu upravφme t°φdu XMesh, abychom zφskali informace o texturßch a materißlech meshe. Za prvΘ musφme p°idat pole textur a materißlu, dßle poΦet materißl∙:
// number of materials
DWORD m_dwNumMat;
// arrays of textures and materials
XTexture *m_pTextures;
D3DMATERIAL8 *m_pMaterials;
Upravφme metodu LoadMeshFromFile(). P°idßme t°etφ parametr typu ukazatel na XResourceManager:
int LoadMeshFromFile(LPCSTR szFileName, LPDIRECT3DDEVICE8 lpDevice, XResourceManager * pResMan);
A upravφme implementaci metody:
if(D3D_OK ==
D3DXLoadMeshFromX(m_szFilePath, 0, lpDevice, NULL, &pD3DXMtrlBuffer, &m_dwNumMat,
&m_lpMesh))
{
TRACE("Mesh '%s' was loaded.", szFileName);
// get material
buffer
D3DXMATERIAL*
d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
// create arrays
of materials and textures
m_pTextures = new
XTexture[m_dwNumMat];
m_pMaterials = new D3DMATERIAL8[m_dwNumMat];
//
// get materials and load textures
for(int i = 0; i
< (int)m_dwNumMat; i++)
{
m_pMaterials[i] =
d3dxMaterials[i].MatD3D;
m_pMaterials[i].Ambient = m_pMaterials[i].Diffuse;
if(d3dxMaterials[i].pTextureFilename)
{
m_pTextures[i].LoadTextureFromFile(d3dxMaterials[i].pTextureFilename,
lpDevice);
pResMan->AddTexture(&m_pTextures[i]);
}
}
pD3DXMtrlBuffer->Release();
}
Nynφ si vysv∞tlφme, co vlastn∞ provßdφme. Volßnφm funkce D3DXLoadMeshFromX() nynφ navφc zφskßme napln∞n² buffer ID3DXBuffer, ve kterΘm jsou ulo₧eny informace o materißlech a jmΘna textur. Ty zφskßme pomocφ objektu D3DXMATERIAL. Ukazatel na tuto strukturu zφskßme p°φmo z ID3DXBufferu. Dßle vytvo°φme pot°ebn² poΦet materißl∙ a textur. Nakonec vÜe v cyklu zinicializujeme. Nesmφme zapomenout p°idat vytvo°enΘ textury do mana₧eru zdroj∙ (to je ten t°etφ parametr metody). Zde je d∙le₧itΘ si uv∞domit, ₧e ne vÜechny materißly majφ k sob∞ p°φsluÜnou texturu. V souboru .x m∙₧e b²t ulo₧ena informace o materißlu, ale samotn² objekt je bez textury. V tomto p°φpad∞ je °et∞zec obsahujφcφ jmΘno textury prßzdn² (null).
Dßle upravφme destruktor t°φdy XMesh tak, aby se zruÜily vÜechny materißly a textury:
XMesh::~XMesh(void)
{
Release();
m_lpDevice = NULL;
SAFE_DELETE_ARRAY(m_pMaterials);
SAFE_DELETE_ARRAY(m_pTextures);
}
Nynφ m∙₧eme mesh vykreslit. Vytvo°φme metodu Draw(). Minule jsme pro ka₧d² mesh m∞li pomocnou prom∞nnou, kde jsme uchovßvali informaci o viditelnosti meshe ve scΘn∞. Nynφ tuto prom∞nnou m_bVisible p°esuneme do samotnΘ t°φdy XMesh.
int XMesh::Draw()
{
if(m_lpDevice && m_bVisible && m_lpMesh)
{
if(m_meshType == CUSTOM)
{
for(int i =
0; i < (int)m_dwNumMat; i++)
{
m_lpDevice->SetMaterial(&m_pMaterials[i]);
m_lpDevice->SetTexture(0, m_pTextures[i].GetTexture());
m_lpMesh->DrawSubset(i);
}
}
else
{
// set default material
D3DMATERIAL8 mtrl;
ZeroMemory( &mtrl,
sizeof(D3DMATERIAL8) );
mtrl.Diffuse.r
= mtrl.Ambient.r = 1.0f;
mtrl.Diffuse.g
= mtrl.Ambient.g = 1.0f;
mtrl.Diffuse.b
= mtrl.Ambient.b = 1.0f;
mtrl.Diffuse.a
= mtrl.Ambient.a = 1.0f;
m_lpDevice->SetMaterial(&mtrl);
m_lpDevice->SetTexture(0,
NULL);
m_lpMesh->DrawSubset(0);
}
return 0;
}
return -1;
}
V tΘto metod∞ nejd°φve zkontrolujeme sprßvnou inicializaci a viditelnost objektu. Dßle metodu rozd∞lφme na dva p°φpady. P°eddefinovanΘ objekty majφ pouze jednu Φßst a nenφ definovßna textura ani materißl (mesh dokonce neobsahuje texturovΘ sou°adnice). Proto je t°eba nastavit standardnφ materißl a texturu "vynulovat". Pokud je mesh nahrßn ze souboru, m∙₧e obsahovat vφce Φßstφ a ke ka₧dΘ se zvlßÜ¥ nastavφ materißl a textura.
K prom∞nnΘ m_bVisible navφc p°ipφÜeme dvojici inline metod, pro nastavenφ a zφskßnφ stavu:
BOOL IsVisible() {
return m_bVisible; }
void Visible(BOOL bVis = TRUE) { m_bVisible = bVis; }
V dalÜφ Φßsti si povφme vφce o sv∞tlech a implementujeme podporu sv∞tel do naÜeho "enginu".
U₧ jsme si pov∞d∞li k Φemu slou₧φ materißl. Materißlem nastavujeme vlastnosti povrchu. V tΘto Φßsti si povφme o osv∞tlenφ scΘny v Direct3D. RozliÜujeme dva zßkladnφ zdroje sv∞tla: tzv. okolnφ (ambient) a sm∞rovΘ (directional) osv∞tlenφ. Okolnφm osv∞tlenφm nastavφme celkovou sv∞tlost scΘny. Toto sv∞tlo nemß ₧ßdnou pozici ani sm∞r - je vÜudyp°φtomnΘ. Jedinou vlastnostφ tohoto sv∞tla je barva. Ambient sv∞tlo nastavφme pomocφ metody za°φzenφ SetRenderState() s parametrem D3DRS_AMBIENT a barvou sv∞tla ve formßtu RGBA. Zde m∙₧ete pou₧it makro D3DCOLOR_RGBA(r, g, b, a), kde jednotlivΘ parametry jsou v rozmezφ 0 - 255. Nap°φklad bφlΘ sv∞tlo nastavφme pomocφ p°φkazu:
m_lpD3DDevice->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_RGBA(255, 255, 255, 255));
Tφmto p°φkazem ovÜem celou scΘnu "p°esv∞tlφte", tak₧e uvidφte vÜechny objekty bφlΘ! Aby sv∞tla zaΦala fungovat, musφte zapnout osv∞tlenφ Direct3D, navφc je t°eba mφt nastaven² n∞jak² materißl. V naÜem p°φkladu nastavujeme standardnφ materißl pro p°eddefinovanΘ meshe a pro tygra nastavujeme vlastnφ materißl. Aby osv∞tlenφ sprßvn∞ fungovalo, musφ mφt ten kter² objekt sprßvn∞ nastavenΘ normßlovΘ vektory - tyto vektory jsou v problematice sv∞tel klφΦovΘ! Normßlov² vektor je vektor kolm² na plochu, nap°φklad:
kde N je prßv∞ normßlov² vektor, podle kterΘho se nßsledn∞ spoΦφtß osv∞tlenφ. Odra₧enΘ sv∞tlo je dßno ·hlem, kter² svφrß paprsek sv∞tla a normßlov² vektor. Sv∞tlo zapneme p°φkazem:
m_lpD3DDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
V p°φpad∞ tygra je t°eba sv∞tlo zase vypnout, proto₧e mesh tygra nemß definovanΘ normßlovΘ vektory a Direct3D nemß podle Φeho spoΦφtat sv∞tlo. V p°φkladu si ukß₧eme mesh, kter² normßlovΘ vektory definovanΘ mß. Zde pak budeme moci pou₧φt osv∞tlenφ Direct3D a mesh bude stφnovan². Samotn²m ambient sv∞tlem vÜak stφnovßnφ neud∞lßme, proto₧e toto sv∞tlo p∙sobφ na vÜechny plochu meshe stejn∞.
V Direct3D je n∞kolik typ∙ t∞chto sv∞tel, ka₧dΘ mß rozdφlnΘ vlastnosti a pou₧itφ. SpoleΦnΘ pro n∞ je ovÜem struktura D3DLIGHT8, kterß p°edstavuje samotnΘ sv∞tlo. M∙₧eme pou₧φt tyto typy:
BodovΘ sv∞tlo - point light
Toto sv∞tlo mß pozici a barvu, ale svφtφ vÜemi sm∞ry stejn∞ intenzivn∞. P°φkladem m∙₧e b²t t°eba ₧ßrovka. Dßle je mo₧nΘ nastavit parametr Range, kter² p°edstavuje dosah paprsk∙. Za touto vzdßlenostφ ji₧ sv∞tlo nebude ovliv≥ovat objekty.
PloÜnΘ sv∞tlo - directional light
PloÜnΘ sv∞tlo mß sm∞r a barvu, nikoliv pozici. Toto sv∞tlo by se dalo p°irovnat ke sv∞tlu Slunce! Paprsky tohoto sv∞tla jsou tudφ₧ rovnob∞₧nΘ, jako kdyby zdroj sv∞tla byl v nekoneΦnu. Toto sv∞tlo takΘ pou₧φvßme v naÜem jednoduchΘm p°φkladu, kde takto osv∞tlujeme rovnom∞rn∞ celou scΘnu. U tohoto sv∞tla parametr Range nenastavujeme. Paprsky majφ stßle stejnou intenzitu.
Sm∞rovΘ sv∞tlo - spot light
Poslednφ typ je spojenφ obou p°edchozφch sv∞tel dohromady, proto₧e mß sm∞r, pozici a samoz°ejm∞ i barvu. Toto sv∞tlo osv∞tluje tzv. vnit°nφ ku₧el rovnom∞rn∞. Vn∞jÜφ ku₧el je osv∞tlen nerovnom∞rn∞, tato nerovnom∞rnost je urΦena parametrem Falloff. Tento parametr v∞tÜino nastavujeme na hodnotu 1.0 pro rovnom∞rnΘ rozlo₧enφ sv∞tla mezi vnit°nφm a vn∞jÜφm ku₧elem. Proto₧e toto sv∞tlo je docela slo₧itΘ, ukß₧eme si vÜechno na obrßzku:
Velikost vnit°nφho a vn∞jÜφho ku₧ele je definovßna dv∞ma ·hly Phi a Theta, kterΘ zadßvßme v radißnech.
Nakonec si jeÜt∞ povφme o parametrech Attenuation0, Attenuation1 a Attenuation2. Pomocφ t∞chto parametr∙ °φdφme intenzitu sv∞tla v prostoru - definujeme vlastn∞ pr∙b∞h klesajφcφ intenzity s rostoucφ vzdßlenosti od zdroje ke vzdßlenosti urΦenΘ parametrem Range (z toho vypl²vß, ₧e tyto parametry op∞t nemajφ v²znam pro ploÜnΘ sv∞tla). Tyto hodnotu mohou b²t v rozsahu od 0 do nekoneΦna, p°iΦem₧ vÜechny najednou by nem∞ly b²t 0. Standardn∞ nastavujeme Attenuation0 a Attenuation2 na 0 a Attenuation1 na 1.0. Pak intenzita klesß nep°φmo ·m∞rn∞ se vzdßlenostφ od zdroje.
Nynφ se podφvejme na strukturu D3DLIGHT8:
typedef struct
_D3DLIGHT8 {
D3DLIGHTTYPE Type;
D3DCOLORVALUE Diffuse;
D3DCOLORVALUE Specular;
D3DCOLORVALUE Ambient;
D3DVECTOR Position;
D3DVECTOR Direction;
float Range;
float Falloff;
float Attenuation0;
float Attenuation1;
float Attenuation2;
float Theta;
float Phi;
} D3DLIGHT8;
VÜechny parametry jsme probrali v²Üe. Ka₧dΘ sv∞tlo mß n∞kolik "sv∞teln²ch"
slo₧ek: diffuse - rozpt²lenΘ sv∞tlo, ambient - sv∞tlo okolφ a
specular - odrazy. VÜechny tyto slo₧ky jsou reprezentovßny strukturou
D3DCOLORVALUE, se kterou jsme se ji₧ setkali v
prvnφ Φßsti a i zde platφ stejnΘ pravidla pro hodnoty jednotliv²ch barevn²ch
slo₧ek. Typ sv∞tla m∙₧e nab²vat t∞chto hodnot:
D3DLIGHT_POINT pro bodovΘ sv∞tlo, D3DLIGHT_SPOT
pro sm∞rovΘ a D3DLIGHT_DIRECTIONAL pro
ploÜnΘ.
Nynφ p°idßme podporu sv∞tel do naÜeho p°φkladu. Nejprve je t°eba otestovat, kolik m∙₧eme mφt maximßln∞ aktivnφch sv∞tel. Ve struktu°e D3DCAPS8 je atribut MaxActiveLights. Tak₧e nejprve ve funkci Init() zavolßme metodu za°φzenφ GetCaps() a zφskßme pot°ebn² parametr, kter² ulo₧φme ve t°φd∞ XDisplay. PotΘ sledujeme poΦet zapnut²ch sv∞tel a tento poΦet omezφme v²Üe uvedenou konstantou (dneÜnφ karty majφ v∞tÜinou 8 sv∞tel). Maximßlnφ poΦet sv∞tel si ulo₧φme nap°φklad do prom∞nnΘ m_iMaxLights.
P°idßme nßsledujφcφ dv∞ metody:
SetLight() - nastavφ sv∞tlo urΦenΘ strukturou D3DLIGHT8 a indexem v rozmezφ 0-(MaxActiveLights-1).
EnableLight() - zapne nebo vypne sv∞tlo urΦenΘ indexem
int XDisplay::EnableLight(int
iIndex, BOOL bEnable)
{
if(m_lpD3DDevice && (iIndex >= 0 && iIndex < m_iMaxLights))
{
return m_lpD3DDevice->LightEnable(iIndex,
bEnable);
}
return -1;
}
int XDisplay::SetLight(int iIndex, D3DLIGHT8 * pLight)
{
if(m_lpD3DDevice && pLight && (iIndex >= 0 && iIndex < m_iMaxLights))
{
return m_lpD3DDevice->SetLight(iIndex,
pLight);
}
return -1;
}
Metody LightEnable() a SetLight() jsme volali ji₧ v minulΘ lekci. Ve scΘn∞ m∙₧ete mφt aktivnφch jen n∞kolik mßlo sv∞tel a to s jak²m prßv∞ pracujete urΦuje prvnφ parametr t∞chto metod.
Na zßv∞r lekce jeÜt∞ vÜechny novΘ funkce vyzkouÜφme v programu Tester.exe. P°idßme dalÜφ mesh a dv∞ sv∞tla. Tento mesh budeme nahrßvat ze souboru .X a koneΦn∞ bude mφt definovanΘ normßlovΘ vertexy, tak₧e na n∞m budou vid∞t sv∞telnΘ efekty jako na p°eddefinovan²ch objektech. Prvnφ sv∞tlo bude jakΘsi slunce, kterΘ svφtφ stßle v jednom sm∞ru modrou barvou. Toto sv∞tlo bude ploÜnΘ. Dßle vytvo°φme jedno bodovΘ sv∞tlo, kterΘ budou obφhat kolem objekt∙ ve scΘn∞.
P°idejme tyto objekty:
XMesh g_Airplane;
D3DLIGHT8 g_PointLight;
D3DLIGHT8 g_Sun;
Dßle upravφme funkci WinMain():
// inicializace Direct3D
g_theDisplay.Init(g_hWnd);
// preddefinovane objekty
g_Sphere.CreateSphere(2.0f, 48, 48, g_theDisplay.GetDevice());
g_Box.CreateBox(1.0f, 1.0f, 6.0f, g_theDisplay.GetDevice());
g_Cylinder.CreateCylinder(1.5f, 2.5f, 4.0f, 24, 8, g_theDisplay.GetDevice());
g_Torus.CreateTorus(1.0f, 2.0f, 64, 64, g_theDisplay.GetDevice());
g_Teapot.CreateTeapot(g_theDisplay.GetDevice());
// model tygra
g_Tiger.LoadMeshFromFile("tiger.x", g_theDisplay.GetDevice(),
g_theDisplay.GetResourceManager());
g_Airplane.LoadMeshFromFile("airplane 2.x", g_theDisplay.GetDevice(), g_theDisplay.GetResourceManager());
// zaregistrovani vsech zdroju
g_theDisplay.GetResourceManager()->AddMesh(&g_Tiger);
g_theDisplay.GetResourceManager()->AddMesh(&g_Sphere);
g_theDisplay.GetResourceManager()->AddMesh(&g_Box);
g_theDisplay.GetResourceManager()->AddMesh(&g_Cylinder);
g_theDisplay.GetResourceManager()->AddMesh(&g_Teapot);
g_theDisplay.GetResourceManager()->AddMesh(&g_Torus);
g_theDisplay.GetResourceManager()->AddMesh(&g_Airplane);
// torus is visible by default
g_Torus.Visible();
// zde vytvorime slunicko
ZeroMemory( &g_Sun, sizeof(D3DLIGHT8)
);
g_Sun.Type = D3DLIGHT_DIRECTIONAL;
g_Sun.Direction.x = -1.0f;
g_Sun.Direction.y = 0.0f;
g_Sun.Direction.z = -1.0f;
g_Sun.Diffuse.r = 0.0f;
g_Sun.Diffuse.g = 0.0f;
g_Sun.Diffuse.b = 0.7f;
g_Sun.Ambient.r = 0.4f;
g_Sun.Ambient.g = 0.4f;
g_Sun.Ambient.b = 0.4f;
g_Sun.Range = 1000.0f;
g_theDisplay.SetLight(0, &g_Sun);
g_theDisplay.EnableLight(0, TRUE);
// dalsi svetlo
ZeroMemory( &g_PointLight, sizeof(D3DLIGHT8)
);
g_PointLight.Type = D3DLIGHT_POINT;
g_PointLight.Position.x = 0.0f;
g_PointLight.Position.y = 0.0f;
g_PointLight.Position.z = 0.0f;
g_PointLight.Diffuse.r = 1.0f;
g_PointLight.Diffuse.g = 1.0f;
g_PointLight.Diffuse.b = 0.0f;
g_PointLight.Range = 1000.0f;
g_PointLight.Attenuation1 = 1.0f;
Nejd°φve vytvo°φme mesh ze souboru airplane 2.x, dßle tento mesh vlo₧φme do sprßvce zdroj∙ a nastavφme, ₧e implicitn∞ bude viditeln² pouze prstenec (torus). V dalÜφ Φßsti vytvo°φme a nastavφme dv∞ sv∞tla. U ploÜnΘho sv∞tla (Slunce) nastavφme pouze sm∞r a barvu. Po tΘ volßme dvojici metod SetLight() a EnableLight(), abychom toto sv∞tlo aktivovali. U bodovΘho sv∞tla nastavφme poΦßteΦnφ pozici, barvu, dosah a rozlo₧enφ intenzity. Samotnß aktivace spolu s vypoΦtenφm novΘ pozice je provedena a₧ ve funkci UpdateFrame(). Po ztrßt∞ za°φzenφ se vÜechno nastavenφ ztratφ, tak₧e i sv∞tla musφme znovu nastavit a aktivovat. Proto p°idejme funkci RestoreUserObjects(), kterß obnovφ u₧ivatelskΘ objekty. Tuto funkci budeme volat v₧dy po funkci RestoreDisplay().
Upravφme proceduru okna tak, aby Üel zobrazit i nßÜ nov² mesh:
case WM_KEYUP:
switch( wParam )
{
case VK_F8:
g_theDisplay.RestoreDisplay();
RestoreUserObjects();
break;
case VK_F1:
g_Sphere.Visible(!g_Sphere.IsVisible());
break;
case VK_F2:
g_Torus.Visible(!g_Torus.IsVisible());
break;
case VK_F3:
g_Box.Visible(!g_Box.IsVisible());
break;
case VK_F4:
g_Cylinder.Visible(!g_Cylinder.IsVisible());
break;
case VK_F5:
g_Teapot.Visible(!g_Teapot.IsVisible());
break;
case VK_F6:
g_Tiger.Visible(!g_Tiger.IsVisible());
break;
case VK_F7:
g_Airplane.Visible(!g_Airplane.IsVisible());
break;
case VK_ESCAPE:
PostQuitMessage(0);
break;
}
break;
Zde takΘ nezapome≥te zavolat ji₧ zmφn∞nou funkci na obnovu sv∞tla. Nakonec upravφme funkci UpdateFrame(), kterß se oproti minulΘ verzi znaΦn∞ zjednoduÜφ:
void UpdateFrame()
{
// svetlo se bude
pohybovat po kruznici
g_PointLight.Position.x
= 0.0f;
g_PointLight.Position.y = 4.0f * sin(double(GetTickCount())/300.0f);
g_PointLight.Position.z = 5.0f * cos(double(GetTickCount())/300.0f);
g_theDisplay.SetLight(1,
&g_PointLight);
g_theDisplay.EnableLight(1, TRUE);
// draw scene
g_theDisplay.UpdateBackground();
g_theDisplay.GetDevice()->BeginScene();
g_Sphere.Draw();
g_Torus.Draw();
g_Box.Draw();
g_Cylinder.Draw();
g_Teapot.Draw();
// tygr nema
definovane normalove vektory, takze je treba vypnout osvetleni
g_theDisplay.GetDevice()->SetRenderState(D3DRS_LIGHTING,
FALSE);
g_Tiger.Draw();
g_theDisplay.GetDevice()->SetRenderState(D3DRS_LIGHTING, TRUE);
g_Airplane.Draw();
g_theDisplay.GetDevice()->EndScene();
if(D3DERR_DEVICENOTRESET == g_theDisplay.Present())
{
RestoreUserObjects();
}
}
Nejprve spoΦφtßme novou pozici bodovΘho sv∞tla (zde vyu₧ijeme trochu matematiky ze st°ednφ Ükoly), dßle toto sv∞tlo nastavφme a aktivujeme. DalÜφ Φßst vykresluje postupn∞ vÜechny objekty. Mesh se samoz°ejm∞ nevykreslφ, pokud nenφ viditeln². U tygra nesmφme zapomenout vypnout osv∞tlenφ. Nakonec musφme u metody Present() sledovat nßvratovou hodnotu D3DERR_DEVICENOTRESET, kterou metoda vracφ po obnovenφ zdroj∙ a je to vhodnß chvφle k op∞tovnΘmu nastavenφ naÜeho slunce.
V dneÜnφ kratÜφ lekci jste se dov∞d∞li n∞co mßlo o sv∞tlech a p°idali jsme pßr nov²ch funkcφ do naÜeho projektu. P°φÜt∞ si budeme hrßt s transformacemi jednotliv²ch objekt∙.
T∞Üφm se p°φÜt∞ nashledanou.