C/C++ & Visual C++Kurz DirectX (31.) |
|
V minulΘ lekci jsem slφbil, ₧e se dnes podφvßme na vylepÜenφ vykreslovacφ fronty, proto₧e zp∙sob uveden² minule, byl znaΦn∞ neefektivnφ. Nejv∞tÜφ ₧rout Φasu je toti₧ funkce SetVertexStream() a tedy ΦastΘ p°epφnßnφ vertex buffer∙ vede ke zbyteΦn²m v²konov²m ztrßtßm. NaÜφm ·kolem v dneÜnφ lekci je tedy vytvo°it postup, jak minimalizovat poΦet volßnφ metody SetVertexStream(). 31.1. Dynamick² index bufferMinule jsme pou₧ili jeden index buffer, kter² byl spoleΦn² pro vÜechny listy. Mohli jsme si to dovolit, proto₧e listy se vykreslovaly jeden po druhΘm. Ka₧d² m∞l sv∙j vlastnφ vertex buffer, kter² se musel p°ed vykreslenφm KAÄD╔HO listu nastavit. Zde tedy vznikalo nadm∞rnΘ p°epφnanφ vertex buffer∙. Zato index buffer se nastavil jen jednou pomocφ metody SetIndices(). Dnes si ukß₧eme jin² zp∙sob, kter² je elegantn∞jÜφ aΦkoliv slo₧it∞jÜφ na implementaci. Budeme postupovat opaΦn∞, Φili vytvo°φme jeden velk² vertex buffer pro cel² terΘn a n∞kolik menÜφch index buffer∙, jejich₧ obsah se bude ka₧d² snφmek m∞nit. Takov² index buffer naz²vßme dynamick² a vytvß°φ se s p°φznakem D3DUSAGE_DYNAMIC. Tento p°φznak zajistφ polohu index bufferu v AGP pam∞ti (statickΘ buffery se vytvß°ejφ ve video pam∞ti). Dynamick² index buffer musφme zamykat s p°φznaky D3DLOCK_DISCARD nebo D3DLOCK_NOOVERWRITE. Prvnφ z nich zajistφ, ₧e cely bufferu bude zahozen a funkce Lock() vrßtφ ukazatel na novou oblast pam∞tφ, co₧ zamezφ Φekßnφ na vykreslenφ dat z p°edchozφho snφmku. Druh² zmφn∞n² p°φznak naopak zajistφ, ₧e se nep°epφÜφ ₧ßdnΘ indexy, kterΘ byly vlo₧en² p°edchozφm volßnφm metody Lock(). Tφmto zp∙sobem se dajφ p°idßvat indexy do bufferu. Stejn²m zp∙sobem m∙₧eme pracovat i s vertex bufferem. 31.2. Rozd∞lenφ terΘnuNßÜ terΘn rozd∞lφme na lokace, kterΘ budou mφt p°edem definovanou velikost (nap°φklad 128x128 polφΦek). Ka₧dß takovß lokace bude mφt vlastnφ index buffer. Lokaci definujeme strukturou Location: struct Location
}; Krom∞ zmφn∞nΘho IB struktura obsahuje n∞kolik dalÜφch parametr∙ vyu₧φvan²ch p°evß₧n∞ p°i vykreslovßnφ. Za prvΘ je to poΦet viditeln²ch list∙. Z toho parametru pozd∞ji zjistφme poΦet troj·helnφk∙, kterΘ vykreslit. Dßle jsou tu atributy MinIndex a MaxIndex, pomocφ kter²ch urΦφme rozsah pou₧it²ch vertex∙ p°i volßnφ DrawIndexedPrimitive(). Dßle je tu pomocn² ukazatel na pole index∙, kter² pou₧ijeme p°i zamykßnφ IB. Nakonec okrajovΘ body lokace, abychom mohli p°i°adit list∙m jejich lokaci. Upravme tedy strukturu uzlu QTNode: struct QTNode {
}; Zde tedy p°idßme ukazatel na lokaci, kde se dan² list nachßzφ (prom∞nnou inicializujeme pouze pro listy). Dßle ji₧ nebudeme pot°ebovat vertex buffer, ale mφsto toho ulo₧φme dynamickΘ pole obsahujφcφ indexy vertex∙ listu. JeÜt∞ uklßdßme pomocnou informaci, poΦet index∙ (abychom toho Φφslo nemuseli poΦφtat pozd∞ji a uÜet°ili tak Φas). Hlavnφ rozdφl bude v tom, ₧e cel² terΘn bude po lokacφch ulo₧en v jedinΘm Vertex bufferu. Z toho plyne, ₧e VB bude obsahovat okrajovΘ vrcholy lokacφ dvakrßt. Tφm zajistφme jednoduÜÜφ implementaci, ale zaplatφme vyÜÜφ pam∞¥ovou slo₧itostφ. U ka₧dΘ lokace budeme b∞hem rozpoznßvßnφ uklßdat viditelnΘ listy a proto₧e vφme, v jakΘ lokaci list je, zkopφrujeme danΘ indexy do IB lokace. P°i vykreslovanφ pak budeme op∞t postupovat po jednotliv²ch lokacφch. Vyu₧ijeme vÜechny parametry, kterΘ jsme si uklßdali b∞hem rozpoznßvßnφ viditeln²ch list∙. Podrobnosti si uvedeme u konkrΘtnφho algoritmu. Upravφme takΘ samotnou t°φdu CTerrain. Ji₧ nebude pot°eba jeden IB, ale mφsto n∞j vlo₧φme globßlnφ Vertex buffer. Dßle bude pot°eba dynamickΘ pole lokacφ a poΦet lokacφ: Location *m_arLoc; Krom∞ t∞chto atribut∙ jeÜt∞ vyma₧eme funkci FillLeaves(), proto₧e listy se budou plnit zcela jinak. Nynφ se ji₧ m∙₧eme podφvat na zm∞ny v metodßch t°φdy CTerrain. ZaΦneme metodou InternalInit(), kde jsme minule inicializovali takΘ globßlnφ index buffer. Dnes ovÜem ₧ßdn² takov² buffer nemßme (nov² vertex buffer m∙₧eme inicializovat a₧ pozd∞ji, proto₧e jeÜt∞ nevφme rozm∞ry terΘnu). Nic novΘho v tΘto metod∞ nebude.
Nejd°φve tedy urΦφme poΦet lokacφ. Vφme jak je velk² terΘn a vφme jak je velkß lokace (to je urΦeno konstantou). PotΘ alokujeme p°φsluÜenΘ mφsto a lokace jednu podruhΘ nastavφme. Zde vytvß°φme nov² objekt IIndexBuffer. Do index bufferu se musφ vejφt indexy list∙ celΘ lokace, kterß mß v naÜem p°φpad∞ 128x128 polφΦek. UrΦφme tedy poΦet list∙ v jednΘ lokaci (vφme velikost lokace a velikost listu). Ka₧dΘ polφΦko mß dva troj·helnφky, na ka₧d² jsou t°eba 3 indexy.
Z toho vypoΦφtßme velikost bufferu. VÜimn∞te si, ₧e index buffer vytvß°φme s p°φznakem D3DUSAGE_DYNAMIC. Metody GenerateTerrain() a GenerateTerrainFromFile() z∙stanou nezm∞n∞ny. Za prvΘ spoΦφtßme posun v index bufferu danΘ lokace (zde ji₧ majφ listy odkaz na svou lokaci - viz. dßle). Vφme kolik list∙ je ji₧ v tomto IB a takΘ vφme kolik index∙ jeden list zabere. P°ekopφrujeme indexy funkcφ memcpy(). IB ji₧ mßme otev°en² (viz. metoda Render()) a ukazatel je ulo₧en v atributu pIndices. Dßle urΦφme maximßlnφ a minimßlnφ pou₧it² index. Minimßlnφ index mß vrchol nejblφ₧e k poΦßtku, maximßlnφ je naopak ten nejdßl v rßmci jednoho listu. Tyto hodnoty platφ pro celou lokaci, tudφ₧ je musφme testovat pro ka₧d² list, kter² vklßdßme do IB. Nakonec musφme zv²Üit hodnotu viditeln²ch list∙ (aby se dalÜφ nalezen² list vlo₧il do IB nakonec). Zßznam, ₧e list je vid∞t je d∙le₧it² jen kv∙li map∞, kterou lze zobrazit klßvesou M. Metoda Render() zaznamenala taky spoustu zm∞n. V prvnφ Φßsti p°ipravφme Index buffery. Tato Φßst lze zcela p°eskoΦit (pak je hezky vid∞t vykreslovanß oblast). Dßle provedeme samotnΘ vykreslenφ: Op∞t zde uvßdφm jen ΦßsteΦn² v²pis, zbytek metody je stejn². Jak jsem tedy zmφnil, nejd°φve uzamkneme IB vÜech lokacφ a vynulujeme parametry. VÜimn∞te si jak uklßdßme ukazatele na otev°enΘ IB. Tyto ukazatele vzßp∞tφ pou₧ijeme v metod∞ CullTerrain(). Nakonec je t°eba IB op∞t odemknout. P°ed vykreslenφm nastavφme
standardnφ
v∞ci jako te textura, vertex shader a nßÜ nov² VB. Metoda SetStreamSource() se tedy volß jen jednou za cyklus. Nynφ se podrobn∞ podφvßme na zp∙sob vykreslovßnφ.
Metoda mß za ·kol vytvo°it a naplnit pole index∙ ka₧dΘho listu a p°i°adit list jednΘ lokaci.
Abychom zjistili, ve kterΘ lokaci se dan² list nachßzφ, pou₧ijeme okrajovΘ body lokacφ a listu. Kdy₧ najdeme tu sprßvnou lokaci, hledßnφ ukonΦφme. Poznßmka: Jist∞ jste si vÜimli, ₧e se v k≤du vyskytujφ °ßdky, kterΘ zajistφ v²pis obsahuj Vertex buffer a index buffer do souboru. Tato volba je volitelnß a m∙₧e se hodit p°i lad∞nφ programu. V²pis t∞chto dat do v²stupnφho okna v²vojovΘho prost°edφ nenφ vhodn², proto₧e je p°φliÜ pomal². 30.3. Zßv∞rA co nßs Φekß v p°φÜtφ lekci? Dod∞lßme slφbenou oblohu a pohrajeme se s funkcemi mlhy. Direct3D mß docela sluÜnou podporu mlhy, tak₧e to nebude nic obtφ₧nΘho. T∞Üφm se p°φÜt∞ nashledanou.
|
|