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:
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:
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
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:
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:
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#