1. díl - XNA a HLSL - První shader

C# .NET XNA game studio HLSL XNA a HLSL - První shader

V tomto seriálu se podíváme na to, jak psát shadery v jazyce HLSL (High Level Shader Language). V XNA to je jediný způsob, jak shadery můžeme psát. Existují i další jazyky (třeba pro OpenGL), ale těmi se tu zabývat nebudeme. Více méně ale vše funguje a vypadá stejně, pokud to není assembler :-)

Co to je shader

Shader je krátký kus programu, který běží na grafické kartě a nějakým způsobem ovlivňuje vykreslování trojúhelníků. Můžeme skrze ně nanést texturu, přidat osvětlení a další jiné věci. Se shaderem jsme vlastně už pracovali BasicEffect není nic jiného než shader. Obsahuje základní vykreslování, budeme se jej snažit nahradit naším vlastním.

První shader

Jako základ bych asi použil pátý díl, kde máme rotující model. Bude se pro naši věc celkem hodit. Neobsahuje žádný komplikovaný kód, který by se nám pletl. Prvně přidáme do projektu nový shader. Dělá se to podobně jako s přidáváním textur. Akorát namísto Add existing item vybereme Add new item a v okně EffectFile. Já jsem ho nazval PrvniShader. Vygeneruje se nám prakticky celý hotový shader. Pojďme se na něj podívat. První, co zkušené oko zaujme, je, že je syntaxe vlastně céčkovská a taky že neexistuje zvýrazňování. Budeme se bez toho muset obejít. Hned nahoře nalezneme naše známe 3 matice:

float4x4 World;
float4x4 View;
float4x4 Projection;

Těch se nezbavíme nikdy. Datový typ float4x4 nám říká, že jedná o matici 4x4. Jsou to takzvané parametry. Jsou pro všechny právě vykreslované vrcholy stejné. Dále následují dvě struktury. Kdo nikdy o strukturách neslyšel, tak je to taková "hloupá" třída:

struct VertexShaderInput{
    float4 Position : POSITION0;
};

První struktura vyjadřuje to, co do shaderu vstupuje. Jistě si vzpomínáte na to, jak jsme tvořili vlastní vertex a právě ta data z vertexu zde reprezentuje tato struktura. Float4 je vektor o 4-řech hodnotách. Za dvojtečkou pak najdeme takzvanou sémantiku. Sémantika jako taková dává oné složce význam. V tomto případě se jedná o pozici vertexu. Máme i další sémantiky, ale o těch se budeme bavit později. Druhá struktura:

struct VertexShaderOutput{
    float4 Position : POSITION0;
};

se příliš od té první neliší. Vlastně vůbec. Říká nám informace o výstupu. Opět chceme, aby vystupovala pozice vertexu, ovšem transformovaná. Ona transformace se děje hned pod:

VertexShaderOutput VertexShaderFunction(VertexShaderInput input){
    VertexShaderOutput output;

    float4 worldPosition = mul(input.Position, World);
    float4 viewPosition = mul(worldPosition, View);
    output.Position = mul(viewPosition, Projection);

    return output;
}

Tomuto úseku se říká vertex shader. Nebo-li část shaderu, která pracuje s vertexy. Toto bude pro nás základní kód. Jen pro představu se v něm odehrává transformace z lokálních souřadnic na souřadnice světa (násobení World maticí), potom jsou souřadnice přepočteny do těch jak je vidí kamera (násobení maticí View) a na závěr transformovány z 3D světa na naši plochou obrazovku (násobení maticí Projection). Funkce mul, jak některým už došlo, slouží pro násobení matic. Další funkce, která následuje, je takzvaný pixel shader:

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0{
    return float4(1, 0, 0, 1);
}

Ten určuje, jakou výslednou barvu bude mít právě vykreslovaný pixel. V našem případě to bude červená. Pořadí barev je následující: červená, zelená, modrá a alfa nebo-li průhlednost. Jednička znamená maximální jas dané barvy. Rozsah je od 0 do 1, ne tedy jak obvykle bývá od 0 do 255-ti. Jistě si pamatujete, jak jsme v bludišti předávali barvu pro podlahy a tu jsme právě museli přepočítat pomocí metody ToVector3. Jedeme dále, už nám zbývá jen kousek:

technique Technique1{
    pass Pass1{
        VertexShader = compile vs_2_0 VertexShaderFunction();
        PixelShader = compile ps_2_0 PixelShaderFunction();
    }
}

Ještě než vysvětlím o co se jedná, dovolím si kus kódu, který jsme dříve při používání shaderů používali:

Effect.CurrentTechnique.Passes[0].Apply();

V jednom shaderu totiž může být několik "technik", které lze použít pro vykreslování a každá může mít několik kol. Většinou je to sice jen jedno, ale třeba takové rozmazání obrazu se musí provádět na dvakrát, jednou vertikálně a podruhé horizontálně. Uvnitř každého kola máme nadefinované, které shadery se mají použít a pod jakou verzí se mají zkompilovat. My si vystačíme s verzí 2, ta je podporována v režimu Reach a pro náročnější věci sáhneme pro verzi 3. Tu lze použít pouze pro Hi-def profil. Mnoho rozdílů mezi nimi není. Pouze v množství příkazů, které můžeme zadat a případně používat nějaké pokročilé funkce. Tak by se dal popsat základní shader.

Používáme shader

První, co musíme udělat, je si shader nahrát. Uděláme tak v metodě LoadContent:

Effect effect;
effect = Content.Load<Effect>("PrvniShader");

Máme efekt nahraný a připravený k použití. Aby ho bylo možné použít pro vykreslování modelu, musíme jím nahradit BasicEffect který model nyní používá. Proto projdeme všechny části modelu a nastavíme jim náš shader:

foreach (ModelMesh mesh in model.Meshes){
  foreach (ModelMeshPart part in mesh.MeshParts){
    part.Effect = effect;
  }
}

A už jen stačí efekt použít při vykreslování. Nejprve nastavíme společné parametry, není je potřeba nastavovat pokaždé znovu:

effect.Parameters["View"].SetValue(Matrix.CreateLookAt(new Vector3(100, 150, 0), new Vector3(0, 0, 0), Vector3.Up));
effect.Parameters["Projection"].SetValue(Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver2, GraphicsDevice.DisplayMode.AspectRatio, 1, 1000));

A pro každou část modelu nastavit matici World:

foreach (ModelMesh mesh in model.Meshes){
  foreach (ModelMeshPart part in mesh.MeshParts){
    part.Effect.Parameters["World"].SetValue(transforms[mesh.ParentBone.Index]*rotace);
  }
  mesh.Draw();
}

Jak jste si všimli, parametry shaderu jsou v kolekci a přistupujeme k nim přes jejich název. Pokud nyní hru pustíte uvidíte něco takovéhoto:

Použití shaderu v HLSL v XNA

Gratuluji. Napsali jste první shader. Příště si do něj přidáme texturu. Čekám na nápady, komentáře, otázky dole pod články ostatně jako vždy skoro marně.


 

Stáhnout

Staženo 138x (1.58 MB)
Aplikace je včetně zdrojových kódů v jazyce C# .NET

 

  Aktivity (1)

Článek pro vás napsal vodacek
Avatar
Vodáček dělá že umí C#, naplno se již pět let angažuje v projektu ŽvB. Nyní studuje na FEI Upa informatiku, ikdyž si připadá spíš na ekonomice. Není mu také cizí PHP a SQL. Naopak cizí mu je Java a Python.

Jak se ti líbí článek?
Celkem (6 hlasů) :
4.54.54.54.54.5


 


Miniatura
Všechny články v sekci
Tvorba shaderů v HLSL
Miniatura
Následující článek
XNA a HLSL - Textury

 

 

Komentáře

Avatar
Petr Nymsa
Redaktor
Avatar
Petr Nymsa:

Nedávno jsem an toto narazil při hledání nějakého efektivního svělta pro 2D. zatím jsem si vytvořil vlastní "světlo" ale opravdu "světlo " s velkými ". Spíše ztmavuju a zesvětluju kusy textur. Funguje to, no zaítm stačí. Každopádně lze využívat HLSL pohodlně i pro 2D ? Nebo to je čistě spíše pro 3D a ve 2D šáhnout po něčem jednodušším ? Pokud lze pro 2D, potřebuju si přečíst celý seriál zpět nebo bude stačit několik dílů ? :D Díky :)

Odpovědět 8.6.2013 17:09
Pokrok nezastavíš, neusni a jdi s ním vpřed
Avatar
vodacek
Redaktor
Avatar
Odpovídá na Petr Nymsa
vodacek:

2D nebo 3D vše kreslí trojúhelníky -- použít to de ale světla ve 2D sou nad moje chápání

Editováno 8.6.2013 17:50
 
Odpovědět 8.6.2013 17:49
Avatar
Petr Nymsa
Redaktor
Avatar
Odpovídá na vodacek
Petr Nymsa:

A já si myslel že 3D je na pochopení horší :D. Jo díky :). Zatím mám mapu, která je představována menšími kusy -> klasická Tile mapa. No aj ka si tka chodím v bludišti, okolní tiles vykreslím plně, již navštívené překreslím trochou šedi a vypadá to jako tmavší barva a tam kde jsi nebyl je tma :). Funguje to celkem pěkně.

Ještě je další řešení posouvat nad hráčem texturu kde je kruh, který se od hráče ztmavuje. Ale to mi nepřijde jako úplně dobrý řešení

Editováno 8.6.2013 17:57
Odpovědět 8.6.2013 17:57
Pokrok nezastavíš, neusni a jdi s ním vpřed
Avatar
vodacek
Redaktor
Avatar
 
Odpovědět 8.6.2013 18:00
Avatar
Petr Nymsa
Redaktor
Avatar
Odpovídá na vodacek
Petr Nymsa:

Jak to funguje, tak to stačí to jo :) Ale mě by zajímalo jak tovří něco takového http://www.youtube.com/watch?… . Zatím na to nemám ani zkušenosti ale i tka zajímalo by mě to :D

Odpovědět 8.6.2013 18:19
Pokrok nezastavíš, neusni a jdi s ním vpřed
Avatar
vodacek
Redaktor
Avatar
Odpovídá na Petr Nymsa
vodacek:

tak tam sou světelný mapy, každý světlo má svoji texturu a přes blend mode additive se na sebe naskládaj

 
Odpovědět 8.6.2013 18:31
Avatar
Odpovídá na vodacek
Michael Olšavský:

Super článek. Pěkně si to vysvětlil. Předtím jsem četl jen pár anglických tutoriálů a kromě jednoho velmi kvalitního na http://www.riemers.net/ to bylo docela otřesné :-) Těším se, až budeš rozebírat ostatní funkce jako saturaci, dot,... A také na ten postprocessing :-)

 
Odpovědět 8.6.2013 20:41
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 7 zpráv z 7.