Články

Tisk článku Tisk článku

První aplikace v DirectX

[Zpět na kategorii]

Datum: 19. 4. 2007 22:10       Autor: Tomáš Herceg       Zobrazeno: 13888x

Kategorie: DirectX

Témata: VB.NET

Seriál: Grafika v DirectX 9 - Díl 1.

V tomto prvním dílu si povíme něco o samotném rozhraní DirectX 9, o tom, co je to Managed DirectX, dozvíte se, co si musíte stáhnout, abyste mohli začít programovat. Nakonec si napíšeme úplně jednoduchou 2D aplikaci.


Poznámka na úvod: Tento článek je určen pro pokročilé programátory, kteří již mají nějaké zkušenosti s grafikou. Pokud jste začátečníci, naučte se nejprve dobře programovat. V DirectX musíte všemu rozumět, není možné pouze kopírovat kousky kódu a skládat je k sobě!

Vítejte v prvním dílu seriálu o programování v DirectX. V tomto seriálu si ukážeme klíčové možnosti tohoto rozhraní, přejdeme přes 2D grafiku ke 3D zobrazením, ukážeme si zvuk a mnoho dalších věcí. Tak tedy vzhůru do toho.

Primární funkcí rozhraní DirectX je rychlé vykreslování grafiky. Vykreslovat na obrazovku můžeme například pomocí rozhraní GDI+ přes náš známý jmenný prostor System.Drawing, což je vhodné pro jednoduché kreslení a pro primitivní hry. Ale co do výkonu je toto rozhraní pomalé. Vykresluje totiž přes knihovny operačního systému, které se musí přizpůsobit veškerému hardwaru, tzn. i starým grafickým kartám, které mnoho funkcí nemají a tudíž je po nich nemůžeme chtít. Naproti tomu DirectX přistupuje k hardwaru přímo, komunikuje přímo s grafickou kartou a využívá veškeré její možnosti a funkce.

Většina grafických karet, které se dnes prodávají, má svůj procesor (GPU), a DirectX se postará o to, aby co nejvíc výpočtů prováděl tento procesor. Tím "odlehčíme" procesoru hlavnímu, který se tak může soustředit na různé jiné činnosti, ve hrách třeba na umělou inteligenci, propočítávání fyzikálních situací atd. GPU je také lépe uzpůsoben pro výpočty ohledně grafiky. Pokud karta některou funkci nemá, DirectX má k tomuto účelu tzv. hardware emulation layer, což v praxi znamená, že pokud karta něco neumí, spočítá to procesor, anebo to "se to nějak zašvindluje". Výhoda je, že toto dělá DirectX za nás a my už jen využíváme jeho funkce. Takže nás nezajímá, jestli karta umí to a to. DirectX to zařídí.

Co budeme potřebovat

Abychom mohli s rozhraním DirectX pracovat, musíme si stáhnout DirectX SDK, neboli Software Development Kit, česky něco jako soupravu nástrojů pro vývoj. Je to poměrně velký balík (kolem 500MB), ale obsahuje dokumentaci, ukázkové příklady a spoustu nástroj, zkrátka vše, co by se nám při vývoji mohlo hodit.

V ukázkových příkladech používám DirectX SDK August 2006, kterou si můžete stáhnout z webu Microsoftu.

Až budete aplikaci distribuovat, nemusíte se bát, že by vaše (byť jen jednoduchá hra), musela mít 500MB. SDK se nedodává s žádnými produkty, je to sada nástrojů pro vývojáře. Uživatelé si musí nainstalovat DirectX End User Runtime, které se také dodává s většinou her, takže je velmi pravděpodobné, že jej již mají.

Až budete mít DirectX SDK staženo, nainstalujte jej. Instalace je jednoduchá, předpokládám, že ji zvládnete bez problémů.

Základní filozofie rozhraní DirectDraw

DirectDraw je rozhraní DirectX pro rychlé vykreslování 2D grafiky. Právě tomu se budeme věnovat ze začátku.

Abychom mohli data dostat do grafické karty, potřebujeme jim v paměti vyhradit prostor (tzv. Surface, někdy také Buffer). Monitor má nějakou obnovovací frekvenci (většinou kolem 60 - 90 Hz, tedy snímků za sekundu). Pro každý 1 snímek karta čte data z paměti a posílá je do monitoru. Na monitor můžeme ale vždy vykreslit jen hotový snímek, nesmí se stát, že tam polovina informací nebude.

Princip vykreslování spočívá v použití dvou bufferů, tzv. FrontBufferu a BackBufferu. FrontBuffer je oblast, která obsahuje již připravený vykreslený snímek a která se vykresluje na obrazovku. Do BackBufferu vždy vykreslíme 1 kompletní snímek, jakmile je snímek vykreslen, provedeme tzv. flip, což je prohození bufferů. Z BackBufferu, který obsahuje kompletní snímek, se stane FrontBuffer, který vykresluje na obrazovku. Naopak původní FrontBuffer se stane BackBufferem a můžeme jej vymazat a nakreslit na něj nový snímek. Tím máme zaručeno, že se na obrazovku vždy vykreslí hotový snímek se vším, co na něm má být. Také nám nevadí, když budeme stíhat vykreslovat méně nebo více snímků než je obnovovací frekvence monitoru. Pokud vykreslujeme pomaleji, monitor ukáže některé snímky víckrát, pokud vykreslujeme rychleji, monitor některé snímky zobrazit nestihne.

První aplikace v DirectX

Jako první ukázkový příklad si napíšeme jednoduchou aplikaci, která poběží na celé obrazovce. Celou obrazovku vybarví modrofialově a zobrazí na ní zelený čtverec.

Vytvořte ve Visual Basicu novou standardní Windows aplikaci a v průzkumníku souborů projektu dvakrát klikněte na My Project.

Zobrazí se okno vlastností projektu s mnoha nastavovacími prvky. Přejděte na záložku References a použijte tlačítko Add.... Ze seznamu vyberte knihovny Microsoft.DirectX a Microsoft.DirectX.DirectDraw.

Přidání referencí k projektu

Projekt uložte a otevřete okno kódu. Úplně nahoru nad začátek třídy Form1 přidejte ještě tyto dva řádky, které zajistí, že nebudeme muset před použitím objektů DirectX vypisovat celou cestu.

 Imports Microsoft.DirectX 
 Imports Microsoft.DirectX.DirectDraw 

Do globálních deklarací Form1 přidejte tyto 4 řádky:

     Dim dev As Device       'zařízení 
     Dim backBuffer As Surface, backBufferDesc As SurfaceDescription     'BackBuffer a jeho parametry 
     Dim frontBuffer As Surface, frontBufferDesc As SurfaceDescription   'FrontBuffer a jeho parametry 
     Dim clip As Clipper     'oříznutí 

Device je objekt, který reprezentuje zařízení (grafickou kartu resp. výstup na monitor). O BackBufferu a FrontBufferu jsme již mluvili, každý ještě má objekt, který popisuje jeho vlastnosti a použití. Objekt Clipper slouží k vymezení oblasti renderování na formulář, my ale budeme používat režim fullscreen.

Dále budeme potřebovat funkce pro vytvoření a inicializaci zařízení. Stačí vytvořit objekt Device a použije se výchozí zařízení (výběr zařízení se naučíme později). Ještě je potřeba nastavit režim spolupráce metodou SetCooperativeLevel, která nastaví vše potřebné tak, abychom mohli vytvořit buffery a pak už jen renderovat.

Poznámka: Pokud jsme okno minimalizovali (např. klávesami Alt+Tab), a pak zase obnovili, je třeba tuto funkci zavolat znovu.

Napíšeme tedy funkci createDevice:

     Public Sub createDevice() 
         'vytvořit a nastavit zařízení 
         dev = New Device() 
         dev.SetCooperativeLevel(Me, CooperativeLevelFlags.FullscreenExclusive) 
     End Sub

Dále musíme vytvořit buffery. Nejprve nastavíme jejich parametry (objekt SurfaceDescription) a pak vytvoříme objekty Surface, kde také určíme, ke kterému zařízení objekty patří.

FrontBuffer musí být nastaven jako PrimarySurface, protože se zobrazuje přímo na monitor. Dále musíme nastavit, že budeme používat operaci Flip a také nastavíme vlastnost BackBufferCount na 1, abychom řekli, že budeme mít 1 BackBuffer.

BackBufferu musíme akorát nastavit, že je to BackBuffer, pak jej již jen stačí vytvořit.

Nakonec musíme vytvořit Clipper a nastavit jej na okno, do kterého budeme zobrazovat. Také jej připojíme na FrontBuffer.

Takže můžeme napsat proceduru createBuffers.

Poznámka: Pokud je okno minimalizováno, objekty Surface se přestanou používat a při pokusu o manipulaci se vyvolá výjimka SurfaceLostException. Po obnovení okna musíme zavolat proceduru createBuffers, která musí zavolat SetCooperativeLevel a pokud objekty Surface již existují, pouze na nich zavolá metodu Restore, není nutné je znovu vytvářet. Také je důležité kontrolovat, jestli je okno v popředí, jinak nemá cenu objekty Surface vytvářet, automaticky hned zaniknou.

     Public Sub createBuffers() 
         'kontrola 
         If Not Me.Focused Then Exit Sub 
  
         'nastavit zařízení 
         dev.SetCooperativeLevel(Me, CooperativeLevelFlags.FullscreenExclusive) 
  
         'vytvořit FrontBuffer 
         If frontBuffer IsNot Nothing Then 
             frontBuffer.Restore() 
         Else 
             frontBufferDesc = New SurfaceDescription() 
             frontBufferDesc.SurfaceCaps.PrimarySurface = True 
             frontBufferDesc.SurfaceCaps.Flip = True 
             frontBufferDesc.SurfaceCaps.Complex = True 
             frontBufferDesc.BackBufferCount = 1 
             frontBuffer = New Surface(frontBufferDesc, dev) 
         End If 
  
         'vytvořit BackBuffer 
         If backBuffer IsNot Nothing Then 
             backBuffer.Restore() 
         Else 
             backBufferDesc = New SurfaceDescription() 
             backBufferDesc.SurfaceCaps.BackBuffer = True 
             backBuffer = frontBuffer.GetAttachedSurface(backBufferDesc.SurfaceCaps) 
         End If 
  
         'nastavit oříznutí 
         clip = New Clipper(dev) 
         clip.Window = Me 
         frontBuffer.Clipper = clip 
     End Sub

Teď máme vše připraveno, můžeme začít renderovat.

Pro jednoduchost umístíme na formulář komponentu Timer, příště si ukážeme lepší způsoby. Při každém "tiknutí" tohoho časovače musíme nejprve zkontrolovat, jestli je okno v popředí a jestli existují buffery.

Pak jen na BackBuffer vykreslíme vše, co má na snímku být, a nakonec zavoláme metodu Flip. Vykreslování a volání metody Flip musí být umístěno v Try...Catch...End Try bloku, a pokud nastane výjimka SurfaceLostException, znamená to, že se okno po minimalizaci zase obnovilo, ale buffery nejsou nastaveny, takže zavoláme proceduru createBuffers a vše se dá dopořádku. V příštím tiku cyklu můžeme renderovat.

     Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick 
         'kontrola 
         If Not Me.Created Then Exit Sub 
         If frontBuffer Is Nothing Or backBuffer Is Nothing Then Exit Sub 
         If Not Me.Focused Then Exit Sub 
  
         Try 
  
             'vykreslit scénu na BackBuffer 
             backBuffer.ColorFill(Color.DarkSlateBlue) 
  
             'nastavíme výplň na 1 (jednolitá) a barvu výplně na zelenou 
             backBuffer.FillStyle = 1 
             backBuffer.FillColor = Color.Green 
             'vykreslíme čtverec 
             backBuffer.DrawBox(200, 200, 500, 500) 
  
             'převrátit buffery 
             frontBuffer.Flip(backBuffer, FlipFlags.Wait) 
  
         Catch ex As Exception 
  
             'po obnovení z minimalizace 
             If ex.GetType() Is GetType(SurfaceLostException) Then 
                 createBuffers() 
             End If 
  
         End Try 
     End Sub

Ještě musíme napsat proceduru Form1_Load, která vytvoří zařízení, nastaví buffery a spustí časovač. A nezapomeneme na proceduru Form1_KeyDown, která odchytí klávesu Escape a ukončí aplikaci.

     Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown 
         'ukončení programu 
         If e.KeyCode = Keys.Escape Then 
             Timer1.Enabled = False 
             End 
         End If 
     End Sub 
  
     Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 
         'vytvořit a nastavit zařízení 
         createDevice() 
         'vytvořit buffery 
         createBuffers() 
         'spustit časovač 
         Timer1.Enabled = True 
     End Sub

To je protentokrát vše. Příště se naučíme používat obrázky a nahradíme časovač smyčkou.

Výsledná obrazovka


> Na začátek

 

Hodnocení:

Hlasů: 9
Zvolte své hodnocení

Tomáš Herceg

Jsem hlavním softwarovým architektem ve společnosti Riganti. Mám dlouholeté zkušenosti s technologiemi ASP.NET, Silverlight, WPF a XNA. Působím též jako lektor ve společnosti Gopas a již třetím rokem jsem držitelem ocenění Microsoft Most Valuable Professional.

Podpořte vznik dalších článků

Související články

DílNázev článku 
Díl 1. První aplikace v DirectX 19. 4. 2007
Díl 2. Smyčka a animace 19. 4. 2007
Díl 3. Poslední DirectDraw aneb sněhu není nikdy dost 20. 4. 2007

RSS Feed RSS Feed

Diskuse

Kapesní počítače

Datum: 16.4.2008 20:22
Autor: neregistrovaný (89.103.181.100)
Hodnocení autora: není
Příspěvků: 0
Dobrý den, jaká je nejlepší volba pro programování her pro kapesní počítače? Nepředpokládám že by directX na těchto zařízeních byl vůbec někdy dostupný, ale už jsem viděl velice výkonné aplikace, a to na zařízeních bez gpu s taktem okolo 400 Mhz. Například velice plynulé 3d hry a podobně. Jak na to?
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...

Re: Kapesní počítače

Datum: 16.4.2008 20:36
Autor: Tomáš Herceg
Hodnocení autora: 1673
Příspěvků: 3536
I na PocketPC existuje mobilní verze DirectXu. Nečekejte žádný výkonový zázrak, PDA nemají grafické karty, ale 30fps se z toho vyrazit dá.
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...

Animace

Datum: 18.5.2008 21:00
Autor: neregistrovaný (85.160.59.211)
Hodnocení autora: není
Příspěvků: 0
Dobrý den, mám za úkol napsat v C# aplikaci, která pustím ve full-screenu AVI, MPEG soubor nebo zobrazí obrázek či bude rolovat text. Jelikož takovýto typ aplikace jsme nikdy nedělal, co by bylo nejlepší k tomu použít? Děkuji
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...

Co je Clipper?

Datum: 23.7.2008 20:17
Autor: Karel Vlk
Hodnocení autora: 0
Příspěvků: 6
Muzu prosim pozadat o presnejsi vysvetleni co ten Clipper vlastne orezava? Myslel jsem, ze na to prijdu sam, kdyz ho z kodu uplne vypreparuji, ale program porad bezi uplne stejne.
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...

Re: Co je Clipper?

Datum: 24.7.2008 7:52
Autor: Tomáš Herceg
Hodnocení autora: 1673
Příspěvků: 3536
Clipper ořezává oblast, která se renderuje. Na fullscreenu se to neprojeví, kdybyste ale chtěl renderovat do okna a mít něco kolem, musíte mít clipper nastaven.
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...

Poradi FillStyle a FillColor

Datum: 24.7.2008 19:32
Autor: Karel Vlk
Hodnocení autora: 0
Příspěvků: 6
Asi se zas ptam na blbost. Proc

.ColorFill(Color.Khaki)
.FillStyle = 1
.FillColor = Color.BurlyWood
.DrawBox(100,100,200,200)
 
funguje a

.ColorFill(Color.Khaki)
.FillColor = Color.BurlyWood
.FillStyle = 1
.DrawBox(100,100,200,200)
 
ne (Vykresli se bez vyplne.)? Kdyz zmenim hodnotu FillStyle na jine cislo, tak funguji oba pripady. Dekuji za odpoved.
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...

Re: Poradi FillStyle a FillColor

Datum: 1.9.2008 18:00
Autor: Ondřej Lysoněk
Hodnocení autora: 0
Příspěvků: 1
To bude asi tím, že když dáš DirectXku příkaz aby ten čtverec vyplnil, tak ještě nemáš nastavený FillStyle, takže DirectX neví jakým způsobem má ten čtverec vyplnit. Teda tak si to myslím já. Jestli to říkám blbě tak mě prosím někdo opravte :).
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...

Re: Poradi FillStyle a FillColor

Datum: 29.1.2012 15:32
Autor: neregistrovaný (178.41.95.206)
Hodnocení autora: není
Příspěvků: 0
No, ja si myslím, že by to malo fungovať rovnako.Len vymenil nastavenie dvoch vlastností. V kóde vlastností nezvykne byť nič mimoriadne, ak to má robiť niečo low-level, tak sa väčšinou použije samostatná metóda na nastavovanie, či nie?
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...

Istalace

Datum: 11.8.2008 12:05
Autor: Jozef Hollý
Hodnocení autora: 33
Příspěvků: 82
Když kliknu na ten odkaz, chce microsoft ověřit systém či co... Stahne to program, ten mi da kod a ja ho dam microsoftu, a on napíše že nemúže nalézt stránku. program se nestáhne a já nevím co dělat.
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...

Re: Istalace

Datum: 11.8.2008 12:24
Autor: Tomáš Herceg
Hodnocení autora: 1673
Příspěvků: 3536
Tak systém ověřte pomocí ActiveX komponenty, která se vám sama nainstaluje. Bude nutné na tohle použít Internet Explorer, ostatní prohlížeče ActiveX neumí.
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...

co to znamená?

Datum: 21.8.2008 11:54
Autor: Jozef Hollý
Hodnocení autora: 33
Příspěvků: 82
LoaderLock was detected
Message: Knihovna DLL C:\Windows\assembly\GAC\Microsoft.DirectX\1.0.2902.031bf3856ad364e35\Microsoft.DirectX.dll se pokouší o spravované spuštění uvnitř zámku zaváděcího modulu operačního systému. Nepokoušejte se spouštět spravovaný kód uvnitř funkce inicializace obrázku nebo funkce DllMain, neboť tato akce může způsobit zablokování aplikace.
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...

Re: co to znamená?

Datum: 27.10.2010 20:09
Autor: petr b.
Hodnocení autora: 0
Příspěvků: 1
dobrý den, řeším ten samý problém, znáte li řešení mohl by jste poradit?
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...

Re: co to znamená?

Datum: 29.1.2012 15:35
Autor: neregistrovaný (178.41.95.206)
Hodnocení autora: není
Příspěvků: 0
No, ja som to LoaderLock kdesi vypol, fungovalo mi to, avšak fakt si nie som istý, či to je bezpečné, asi nie.
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...

Aplikace v okně

Datum: 20.9.2008 12:46
Autor: neregistrovaný (77.48.34.7)
Hodnocení autora: není
Příspěvků: 0
Prosím, jak to mám udělat aby ta aplikace neběžela ve fullscreen ale jenom v okně? Když změním CooperativeLevelFlags třeba na Normal tak se mi okno vůbec nezobrazí. Prosím poraďte.
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...

Re: Aplikace v okně

Datum: 20.9.2008 12:49
Autor: neregistrovaný (77.48.34.7)
Hodnocení autora: není
Příspěvků: 0
... a ještě k tomu to vrací Me.Focused = False
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...

visual c#

Datum: 5.1.2010 21:53
Autor: neregistrovaný (85.161.205.53)
Hodnocení autora: není
Příspěvků: 0
Zdravim
diky za krasnou prace..
mam apikace ve visual c# 2005.
potreboval bych 2D na 3D ..poradis nejake reseni nebo musim na direct X? diky predem za odpoved
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...

instalace sdk - problém

Datum: 4.9.2010 19:44
Autor: neregistrovaný (213.194.221.67)
Hodnocení autora: není
Příspěvků: 0
Připadám si jak největší ňouma, ale asi mám problém s instalací SDK... :( SDK (June 2010) jsem nainstaloval bez problémů, ale když (podle návodu výše) spustím Visual Basic 2010, vytvořím nový projekt (Windows Forms Application), kliknu na My Project, zvolím References, tak žádný Windows.DirectX a Windows.DirectX.DirectDraw zde nevidím (vše ostatní ano).

Můžu se tedy zeptat, jak zde tyto dvě knihovny dostanu? Jedu na Windows 7 (64bit).

Předem děkuji za odpověď.
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...

Re: instalace sdk - problém

Datum: 28.5.2011 20:38
Autor: neregistrovaný (86.63.214.121)
Hodnocení autora: není
Příspěvků: 0
C:\Windows\assembly\GAC\Microsoft.DirectX\1.0.2902.031bf3856ad364e35\Microsoft.DirectX.dll
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...

Re: instalace sdk - problém

Datum: 3.9.2011 21:37
Autor: Ladislav Šesták
Hodnocení autora: 0
Příspěvků: 2
Moc děkuji, měl jsem stejný problém
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...
 

VBNET.CZ | © 2007 Tomáš Herceg, Tomáš Jecha | Kopírování a přejímání jakéhokoliv obsahu z tohoto webu je bez písemného svolení autorů zakázáno.