2. díl - XNA a HLSL - Textury

C# .NET XNA game studio HLSL XNA a HLSL - Textury

Posledně 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:

Výstupní souřadnice textury v XNA

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:

Otexturovaný model v C# XNA

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
Adresní módy textur shaderu v XNA

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:

Filtrování v XNA

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:

Mip mapy v XNA

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ě se podíváme na zoubek základům osvětlování. Budu očekávat komentáře, otázky, stížnosti, postřehy, nápady.


 

Stáhnout

Staženo 129x (1.77 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 (5 hlasů) :
4.64.64.64.64.6


 


Miniatura
Předchozí článek
XNA a HLSL - První shader
Miniatura
Všechny články v sekci
Tvorba shaderů v HLSL
Miniatura
Následující článek
XNA a HLSL - Světla poprvé

 

 

Komentáře

Avatar
cyrilja
Člen
Avatar
cyrilja:

Bude ukázáno také na 3D modelech ?

 
Odpovědět 12.6.2013 18:27
Avatar
vodacek
Redaktor
Avatar
 
Odpovědět 12.6.2013 19:01
Avatar
cyrilja
Člen
Avatar
cyrilja:

Potřeboval bych do 3D modelů zabudovat kouř, výbuch, mrak

 
Odpovědět 13.6.2013 20:35
Avatar
Odpovídá na cyrilja
Luboš Běhounek (Satik):

To se většinou řeší přes částicové systémy, tyhle efekty součástí modelů obvykle nejsou.

Odpovědět  +2 13.6.2013 20:40
:)
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 4 zpráv z 4.