První aplikace v DirectX

1. díl - První aplikace v DirectX

Tomáš Herceg       19.04.2007       VB.NET, DirectX, Grafika       16618 zobrazení

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

 

hodnocení článku

0       Hodnotit mohou jen registrované uživatelé.

 

Všechny díly tohoto seriálu

3. Poslední DirectDraw aneb sněhu není nikdy dost 20.04.2007
2. Smyčka a animace 19.04.2007
1. První aplikace v DirectX 19.04.2007

 

Mohlo by vás také zajímat

Windows Presentation Foundation (WPF) - díl 6.: Základy pozicování

Pozicování je velká přednost technologie WPF. Dovoluje připravovat dynamické rozložení prvků s předvídatelným chováním při změně nejen velikosti okna, ale i elementů uvnitř něj. V tomto díle se věnuji základním principům pozicování.

Windows Presentation Foundation (WPF) - díl 8.: Canvas, StackPanel, WrapPanel

Článek se věnuje dalším široce používaným pozicovacím komponentám WPF. Canvas pro absolutní pozicování, StackPanel pro skládání elementů vedle sebe nebo nad sebe a WrapPanel zalamující jejich tok do řádků nebo sloupců.

Co je to .NET Framework 4.5?

V tomto článku se snažím nastínit rozdíl mezi .NET 4 a .NET 4.5 z pohledu zpětné kompatibility.

 

 

Nový příspěvek

 

poukaz na neplatný odkaz

na sajtě http://www.dotnetportal.cz/clanek/7/Prvn...

je neplatný link "Stáhnout zdrojové kódy" (pod screenshotem)

http://cdn.dotnetportal.cz/files/24_Dire...

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Diskuse: První aplikace v DirectX

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ěď.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

C:\Windows\assembly\GAC\Microsoft.DirectX\1.0.2902.031bf3856ad364e35\Microsoft.DirectX.dll

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Moc děkuji, měl jsem stejný problém

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Dobrý den,

mám stejný problém, ale tohle řešení mi nefunguje.

Program mi vždy spadne s chybou: "Sestavení smíšeného režimu je sestaveno s verzí v1.1.4322 modulu runtime a bez dalších konfiguračních údajů je nelze načíst do verze 4.0 modulu runtime."

(píšete sice 1.0.29..., ale takovou složku tam nemám)

Zkoušel jsem i nainstalovat 2006 verzi, ale žádná změna.

Děkuji.

(XNA je pochopil-li jsem správně pro pokročilejší, ale nejde-li už DirectX pod VB.NETem, tak C++ se mi učit nechce.)

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Diskuse: První aplikace v DirectX

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.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

dobrý den, řeším ten samý problém, znáte li řešení mohl by jste poradit?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

No, ja som to LoaderLock kdesi vypol, fungovalo mi to, avšak fakt si nie som istý, či to je bezpečné, asi nie.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Diskuse: První aplikace v DirectX

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.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

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 :).

nahlásit spamnahlásit spam 0 odpovědětodpovědět

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?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Diskuse: První aplikace v DirectX

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

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Diskuse: První aplikace v DirectX

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.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

... a ještě k tomu to vrací Me.Focused = False

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Diskuse: První aplikace v DirectX

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.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

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í.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Diskuse: První aplikace v DirectX

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.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

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.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Diskuse: První aplikace v DirectX

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

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Diskuse: První aplikace v DirectX

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?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

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á.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.

Nyní zakládáte pod článkem nové diskusní vlákno.
Pokud chcete reagovat na jiný příspěvek, klikněte na tlačítko "Odpovědět" u některého diskusního příspěvku.

Nyní odpovídáte na příspěvek pod článkem. Nebo chcete raději založit nové vlákno?

 

  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:  
Heslo:  

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback