2013. április 15., hétfő

HLSL #2 Textura

Folytatva az előzőekben megkezdett HLSL ismertetőt, ebben a részben a texturák használatával még látványosabb lesz mindaz amit a képernyőn meg kívánunk jeleníteni.
Továbbra is az FxComposer használatával, egy új üres effect-re lesz szükség.

Egy tetszőleges kép megjelenítéséhez az alábbiakra van szükség:
- model
- kép
- UV koordináták
- Sampler

A model továbbra is az előző részben beillesztett négyzet marad.
A kép tetszőleges lehet, akár saját vagy akár az internetről letöltött
Az UV koordinátákat jelen esetben a program adja a modellhez

A sampler definiáláshoz az alábbi kódsorok szükségeltetnek:
texture diffuseMap
<
    string UIName = "Diffuse Texture";
>;

sampler2D diffuseMapSampler = sampler_state
{
 Texture = <diffuseMap>;
};

Első lépésben egy texture kerül bevezetésre. Ez látható a properties panelen "Diffuse Texture" néven.

A sampler2D definiál minden egyéb paramétert a shader számára, hogy az adott texturát milyen módon kell megjeleníteni.(pl hogyan kell sokszorosítani, stb)

Egyenlőre egyetlen hivatkozás bőven elég, amely meghatározza, hogy az adott sampler melyik képhez tartozik: Texture = <diffuseMap>;
Ahol a diffuseMap az előbb létrehozott texture neve

Fontos megjegyezni, hogy ahány texture kerül bevezetésre, pontosan annyi sampler kell.

A kép megjelenítéséhez szükség van UV koordinátákra, ezért a vertexshader bemenete megváltozik.
struct app2vertex {
 float4 position  : POSITION;
 float2 texCoord  : TEXCOORD0;
};

A vertexsahder minden esetben elvárja a vertex pozícióját: float4 position : POSITION;

A textura koordináták a struktura texCoord elemén keresztül érhetőek el:
float2 texCoord : TEXCOORD0;
A TEXCOORD0 SEMANTICS utasítja az FXComposert, hogy a model első UV koordinátáit adja át.

Amennyiben egy modellhez több UV koordináta is tartozik, úgy azokat a sorszámok növelésével lehet elérni. (TEXCOORD1, TEXCOORD2...)

Mivel az UV koordinátákra a pixelshader-ben is szükség lesz, ezért annak a bemenetét is változtatni kell.
struct vertex2pixel {
  float4 position  : POSITION;
  float2 texCoord  : TEXCOORD0;  
};

Noha jelen esetben a két struktúra megegyezik, ez a legritkább esetben fordul csak elő.

Általánosságban elmondható, hogy mindig vagy egy struktúra amely a programtól a vertexshader felé tartalmaz bemenetet (app2vertex) és van egy struktúra amely a vertexshadertól a pixelshader felé tartalmazza a szükséges adatokat (vertex2pixel)

Mivel a pixelshader a vertexshadertól várja a már előkészített paramétereket, ezért logikus, hogy a vertexshader kimenete a vertex2pixel struktúra.
Bemenete pedig az app2vertex struktúra.

A végső vertexshader az alábbi:
vertex2pixel mainVS(app2vertex In)
{
  vertex2pixel Out; 
  Out.position = mul(In.position, WorldViewProj); 
  Out.texCoord = In.texCoord;
  return Out;
}

A pozíció a már megismert módon kiszámításra kerül.
A textura UV koordináta pedig minden  változtatás nélkül továbbadásra kerül a pixelshader felé.

Mivel a vertexshader kimenete egy vertex2pixel struktúra, ebből következőleg a pixelshader bemenetének is muszáj annak lennie.

float4 mainPS(vertex2pixel In) : COLOR
{
 float4 diffuseTexture = tex2D(diffuseMapSampler, In.texCoord);
 return diffuseTexture;
}

A tex2D függvény készíti el a végső képet és 2 paramétert vár.
Az első a sampler neve, a második a modellhez tartozó UV koordináta, amely immáron a vertexshader kimeneteként jön mint paraméter: vertex2pixel In

A végső shader az alábbi:
/*****************************************************/
// **                AUTO GENERATED
/*****************************************************/

float4x4 WorldViewProj : WorldViewProjection;


/*****************************************************/
// **                TEXTURES
/*****************************************************/

texture diffuseMap
<
    string UIName = "Diffuse Texture";
>;

sampler2D diffuseMapSampler = sampler_state
{
 Texture = <diffuseMap>;
};

/*****************************************************/
// **                IO STRUCTURES
/*****************************************************/

// input from application
struct app2vertex {
 float4 position  : POSITION;
 float2 texCoord  : TEXCOORD0;
};

// output to pixelshader
struct vertex2pixel {
 float4 position  : POSITION;
 float2 texCoord  : TEXCOORD0;  
};


/*****************************************************/
// **                PROGRAMS
/*****************************************************/

vertex2pixel mainVS(app2vertex In)
{
 vertex2pixel Out; 

 Out.position = mul(In.position, WorldViewProj);    
 Out.texCoord = In.texCoord;

 return Out;
}


float4 mainPS(vertex2pixel In) : COLOR
{
 float4 diffuseTexture = tex2D(diffuseMapSampler, In.texCoord);
 return diffuseTexture;
}

/*****************************************************/
// **
// **                TECNIQUES
// **
/*****************************************************/

technique technique0 {
 pass p0 {
  CullMode = none;
  VertexShader = compile vs_3_0 mainVS();
  PixelShader = compile ps_3_0 mainPS();
 }
}



Nincsenek megjegyzések:

Megjegyzés küldése