IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

2. diel - XNA a HLSL - Textúry

Naposledy sme si vytvorili jednoduchý shader. Zatiaľ sme vykresľovali konštantný farbu, preto si pridáme textúru. Poďme na to.

Texturujeme

Najprv budeme ale potrebovať textúru získať. Každý model, keď ho nahráme, tak obsahuje svoju inštanciu triedy BasicEffectu a práve v nej sa textúra nachádza. To máme prvý problém, už nám len ostáva do shader pridať príslušný kód. Ako sme si povedali v treťom diele, textúry majú svoj vlastný systém súradníc. Týmto súradniciam sa hovorí tiež UV. Pridáme si ich do štruktúry, ktorá do shader vstupuje:

struct VertexShaderInput{
  float4 Position : POSITION0;
  float2 UV:TEXCOORD0;
};

Meno zložky je len a len na nás, ale názov UV sa mi zdá pomerne dobrý. Je to vektor pre dve čísla a jeho význam je súradnice pre textúry. To máme druhú sémantiku, o ktoré je dobré vedieť. To isté pridáme aj do výstupnej štruktúry z vertex shader:

struct VertexShaderOutput{
  float4 Position : POSITION0;
  float2 UV:TEXCOORD0;
};

Budeme potrebovať súradnice preposlať aj do pixel shader, kde budeme textúrovanie vykonávať. Preto do vertex shader doplníme:

output.UV=input.UV;

Máme všetko pripravené pre samotné textúrovanie. Môžeme si vyskúšať, či ak sa nám súradnice do pixel shader dostávajú. Postačí, keď si ich iba prevedieme na výstup:

return float4(input.UV.x,input.UV.y,0,1);

Ak uvidíte niečo ako na tomto obrázku:

Výstupné súradnice textúry v XNA - Tvorba shaderov v HLSL

Tak je všetko v poriadku a môžeme pokračovať s pridaním textúry. Najprv pridáme textúru do efektu:

Texture Texture;

Prvý Texture je meno dátového typu a druhé je až identifikátor, ten môže byť ľubovoľný. Textúry sa nanášajú cez takzvané samplery. Preto si taky jeden musíme vytvoriť:

sampler TextureSampler = sampler_state {
  texture = <Texture>;
};

Sampler sa volá TextureSampler a má priradenú textúru, ktorú bude nanášať. Môžeme tu nastaviť aj ďalšie parametre, o tých sa zmienime neskôr. Už zostáva len a len textúru pomocou samplera naniesť. To vykonáme v pixel shader. Máme na to funkciu tex2D. Do tej odovzdávame dva parametre, jeden je náš sampler a druhý sú súradnice.

float4 tex=tex2D(TextureSampler,input.UV);

Vracia sa vektor o 4 zložkách 3 farby a jeden alfa kanál. A práve túto farbu len vrátime ako výsledok pixel shader.

return tex;

Shader je hotový. Teraz už len ostáva jeho obsluha. V metóde LoadContent si nastavíme textúru:

foreach (ModelMesh mesh in model.Meshes){
  foreach (ModelMeshPart part in mesh.MeshParts){
    BasicEffect ef = part.Effect as BasicEffect;
    effect.Parameters["Texture"].SetValue(ef.Texture);
    part.Effect = effect;
  }
}

A je tak hotovo všetko, čo bolo treba. Ak teraz program spustíme uvidíte otexturovaný koberec:

Otexturovaný model v C# XNA - Tvorba shaderov v HLSL

Ešte by sa hodilo povoľovať / zakazovať používanie textúry. Preto pridáme do shader nový parameter:

bool TextureEnabled=false;

Môžeme priamo vo shader nastavovať implicitnú hodnotu, pre istotu tu dáme false. Potom už len do pixel shader pridáme podmienku aj tie môžeme vo shadery používať:

if(TextureEnabled)return tex2D(TextureSampler,input.UV);
else return float4(1, 0, 0, 1);

Potom ešte v metóde LoadContent nastavíme tento nový parameter na true:

effect.Parameters["TextureEnabled"].SetValue(true);

A opäť uvidíme otexturovaný koberec. Shader máme pre túto chvíľu hotový.

AddressMode

Už vyššie sme sa zmienil aj o ďalších parametroch, ktoré môžeme samplerům nastavovať. Prvým z nich je adresné mód. Ten nám hovorí, ako sa má sampler zachovať, pokiaľ nie sú súradnice v rozmedzí 0 - 1. Grafická karta pozná tri možnosti, ako sa s tým vysporiadať:

  • wrap: nanesie do oných častí textúru akoby bola v rozmedzí 0 - 1, možno tak urobiť opekování
  • clamp: na časť ktorá je v rozsahu nanesie textúru normálne ale na zostávajúce miesta roztiahne jej okraje
  • mirror: vykoná zrkadlenie, viď obrázok
Adresné módy textúr shader v XNA - Tvorba shaderov v HLSL

Na obrázku vidíte všetky tri možné adresné módy. Možno je dokonca pre každú os nastaviť zvlášť. Defaultne je nastavený režim wrap. Nastavovanie môžeme robiť buď priamo v samplera, alebo tiež prostredníctvom XNA. Poďme sa pozrieť na prvú možnosť tu robíme vnútri samplera:

sampler TextureSampler = sampler_state {
  texture = <Texture>;
  AddressU=clamp;
  AddressV=clamp;
};

A vnútri XNA potom máme v triede GraphicsDevice kolekcii SamplerStates, kde môžeme jednotlivé stavy nastavovať. napríklad:

GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;

a pre režim mirror sa musíme uchýliť k menšej ľsti:

GraphicsDevice.SamplerStates[0] = new SamplerState(){
  AddressU=TextureAddressMode.Mirror,
  AddressV=TextureAddressMode.Mirror
};

Nastavenie odovzdávané z XNA prepisuje nastavenia zapísané vo shader.

Filtrovanie

Samplery majú tiež ešte jeden dôležitý parameter a tým je filtrovanie. K filtrovanie dochádza vtedy, ak sa na požadovaných súradniciach textúry netrafíme na stred pixelu ale niekam inam. Potom grafická karta použije nastavený filter. Máme k dispozícii tieto filtre:

  • point - hodnota je zaokrúhlená na najbližší pixel
  • linear - lineárna interpolácia
  • anisotropic - iná interpolácia

Na nasledujúcom obrázku je viditeľný rozdiel medzi filtrovaním na body a zvyškom:

Filtrovanie v XNA - Tvorba shaderov v HLSL

Máme k dispozícii tri možnosti nastavenia filtrov. Jeden filter pre situácie, keď je textúra zmenšovaná, jeden keď je textúra naopak zväčšovaná. Tretí filter môžeme nastaviť pre takzvané mipmapování. Mip mapping je technika, pri ktorej nepoužívame len jednu veľkosť textúry, ale aj jej zmenšené kópie a podľa textúrované plochy si grafická karta vyberie príslušnú veľkosť textúry, ktorá sa najlepšie hodí. Môžeme XNA prikázať, aby ich generovalo a to v nastavení textúry, ako je zrejmé na nasledujúcom obrázku:

Mip mapy v XNA - Tvorba shaderov v HLSL

Poďme sa pozrieť ako filtre nastaviť skrze HLSL:

sampler TextureSampler = sampler_state {
    texture = <Texture>;
    MinFilter=Point;
    MagFilter=Point;
    MipFilter=Point;
};

V XNA môžeme použiť opäť predpripravených nastavení samplerov alebo si nadefinovať vlastný, obdobne ako sme to urobili vyššie. Filtre majú niektoré obmedzenia. Nie sú vhodné pre úplne všetky formáty textúr. Ale pre naše skromné účely na ne zatiaľ nenarazíme.

To by bolo pre dnešné diel všetko. V zdrojových kódoch nájdete tiež oba projekty sa štvorcami. Nabudúce sa pozrieme na zúbok základom osvetľovanie. Budem očakávať komentáre, otázky, sťažnosti, postrehy, nápady.


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 136x (1.77 MB)
Aplikácia je vrátane zdrojových kódov v jazyku C#

 

Predchádzajúci článok
XNA a HLSL - Prvý shader
Všetky články v sekcii
Tvorba shaderov v HLSL
Preskočiť článok
(neodporúčame)
XNA a HLSL - Svetlá druhýkrát
Článok pre vás napísal vodacek
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
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.
Aktivity