Lekce 2 - XNA a HLSL - Textury
Posledně, XNA a HLSL - První shader, jsme si vytvořili jednoduchý shader.
Zatím jsme vykreslovali konstantní barvu, proto si přidáme texturu. Pojďme na to.
Texturujeme
Nejprve budeme ale potřebovat texturu získat. Každý model, když ho
nahrajeme, tak obsahuje svou instanci třídy BasicEffectu
a
právě v ní se textura nalézá. To máme první problém, už nám jen
zbývá do shaderu přidat příslušný kód. Jak jsme si řekli ve třetím
díle, textury mají svůj vlastní souřadnicový systém. Těmto
souřadnicím se říká také UV. Přidáme si je do struktury, která do
shaderu vstupuje:
struct VertexShaderInput{
float4 Position : POSITION0;
float2 UV:TEXCOORD0;
};
Jméno složky je jen a jenom na nás, ale název UV se mi zdá poměrně dobrý. Je to vektor pro dvě čísla a jeho význam je souřadnice pro textury. To máme druhou sémantiku, o které je dobré vědět. To samé přidáme i do výstupní struktury z vertex shaderu:
struct VertexShaderOutput{
float4 Position : POSITION0;
float2 UV:TEXCOORD0;
};
Budeme potřebovat souřadnice přeposlat i do pixel shaderu, kde budeme texturování provádět. Proto do vertex shaderu doplníme:
output.UV=input.UV;
Máme vše připravené pro samotné texturování. Můžeme si vyzkoušet, zda-li se nám souřadnice do pixel shaderu dostávají. Postačí, když si je pouze převedeme na výstup:
return float4(input.UV.x,input.UV.y,0,1);
Pokud uvidíte něco jako na tomto obrázku:
Tak je vše v pořádku a můžeme pokračovat s přidáním textury. Prvně přidáme texturu do efektu:
Texture Texture;
První Texture
je jméno datového typu a druhé je až
identifikátor, ten může být libovolný. Textury se nanášejí přes
takzvané samplery. Proto si taky jeden musíme vytvořit:
sampler TextureSampler = sampler_state { texture = <Texture>; };
Sampler se jmenuje TextureSampler
a má přiřazenou texturu,
kterou bude nanášet. Můžeme zde nastavit také další parametry, o těch se
zmíníme později. Už zbývá jen a pouze texturu pomocí sampleru nanést. To
provedeme v pixel shaderu. Máme na to funkci tex2D. Do té předáváme dva
parametry, jeden je náš sampler a druhý jsou souřadnice.
float4 tex=tex2D(TextureSampler,input.UV);
Vrací se vektor o 4 složkách 3 barvy a jeden alfa kanál. A právě tuto barvu pouze vrátíme jako výsledek pixel shaderu.
return tex;
Shader je hotový. Teď už jen zbývá jeho obsluha. V metodě
LoadContent
si nastavíme texturu:
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še, co bylo potřeba. Pokud nyní program spustíme uvidíte otexturovaný koberec:
Ještě by se hodilo povolovat/zakazovat používání textury. Proto přidáme do shaderu nový parametr:
bool TextureEnabled=false;
Můžeme přímo ve shaderu nastavovat implicitní hodnotu, pro jistotu zde dáme false. Pak už jen do pixel shaderu přidáme podmínku i ty můžeme ve shaderech používat:
if(TextureEnabled)return tex2D(TextureSampler,input.UV); else return float4(1, 0, 0, 1);
Pak ještě v metodě LoadContent
nastavíme tento nový
parametr na true:
effect.Parameters["TextureEnabled"].SetValue(true);
A opět uvidíme otexturovaný koberec. Shader máme pro tuto chvíli hotový.
AddressMode
Už výše jsme se zmínil i o dalších parametrech, které můžeme samplerům nastavovat. Prvním z nich je adresní mód. Ten nám říká, jak se má sampler zachovat, pokud nejsou souřadnice v rozmezí 0 – 1. Grafická karta zná tři možnosti, jak se s tím vypořádat:
- wrap: nanese do oněch částí texturu jakoby byla v rozmezí 0 – 1, lze tak udělat opekování
- clamp: na část která je v rozsahu nanese texturu normálně ale na zbývající místa roztáhne její okraje
- mirror: provede zrcadlení, viz obrázek
Na obrázku vidíte všechny tři možné adresní módy. Lze je dokonce pro každou osu nastavit zvlášť. Defaultně je nastaven režim wrap. Nastavování můžeme dělat buď přímo v sampleru nebo také prostřednictvím XNA. Pojďme se podívat na první možnost tu děláme uvnitř sampleru:
sampler TextureSampler = sampler_state { texture = <Texture>; AddressU=clamp; AddressV=clamp; };
A uvnitř XNA pak máme ve třídě GraphicsDevice
kolekci
SamplerStates
, kde můžeme jednotlivé stavy nastavovat.
Kupříkladu:
GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;
a pro režim mirror se musíme uchýlit k menší lsti:
GraphicsDevice.SamplerStates[0] = new SamplerState(){ AddressU=TextureAddressMode.Mirror, AddressV=TextureAddressMode.Mirror };
Nastavení předávané z XNA přepisuje nastavení zapsané ve shaderu.
Filtrování
Samplery mají také ještě jeden důležitý parametr a tím je filtrování. K filtrování dochází tehdy, pokud se na požadovaných souřadnicích textury netrefíme na střed pixelu ale někam jinam. Pak grafická karta použije nastavený filtr. Máme k dispozici tyto filtry:
- point – hodnota je zaokrouhlena na nejbližší pixel
- linear – lineární interpolace
- anisotropic – jiná interpolace
Na následujícím obrázku je patrný rozdíl mezi filtrováním na body a zbytkem:
Máme k dispozici tři možnosti nastavení filtrů. Jeden filtr pro situace, když je textura zmenšována, jeden když je textura naopak zvětšována. Třetí filtr můžeme nastavit pro takzvané mipmapování. Mip mapping je technika, při které nepoužíváme jen jednu velikost textury, ale také její zmenšené kopie a podle texturované plochy si grafická karta vybere příslušnou velikost textury, která se nejlépe hodí. Můžeme XNA přikázat, aby je generovalo a to v nastavení textury, jak je patrné na následujícím obrázku:
Pojďme se podívat jak filtry nastavit skrze HLSL:
sampler TextureSampler = sampler_state { texture = <Texture>; MinFilter=Point; MagFilter=Point; MipFilter=Point; };
V XNA můžeme použít opět předpřipravených nastavení samplerů nebo si nadefinovat vlastní, obdobně jako jsme to udělali výše. Filtry mají některá omezení. Nejsou vhodné pro úplně všechny formáty textur. Ale pro naše skromné účely na ně zatím nenarazíme.
To by bylo pro dnešní díl vše. Ve zdrojových kódech naleznete také oba projekty se čtverci.
Příště, XNA a HLSL - Světla podruhé, si přidáme další světla, konkrétně ambientní a směrové.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 136x (1.77 MB)
Aplikace je včetně zdrojových kódů v jazyce C# .NET