Texture Blending
Autor: Astror Enales
Inhaltsverzeichnis
^ Einleitung
Inspiriert von den CryEngine3 Entwickler-Videos musste ich einen ziemlich schicken Effekt der Engine nachbauen und möchte diesen nun hier für Alle bereit stellen.
Es handelt sich dabei um einen Effekt mit dem man zwei Texturen (z.b. Wand rot und Wand weiß) über eine Noise Maske übereinander blenden kann.
Wie dies aussieht habe ich einmal in einem kleinen Video zusammengefasst:
http://vimeo.com/11309657
Interesse geweckt? Dann nichts wie los.
^ Informationen
Die Maske folgt in meinem Beispiel einer gewissen Richtlinie. Und zwar benutze ich den Alpha-Bereich von 0-255 um die Texturen zu "blenden". Wir geben unserem Shader einen Strength Wert, den wir beliebig verändern können, je nachdem wie stark die Texturen geblendet werden sollen. Der Alpha-Wert gibt dabei an wie "früh" die Texturen geblendet werden.
Im Download am Ende der Artikels findet ihr Beispiel-Texturen die eine gute Impression geben wie man die Textur machen kann. (Die Wand-Textur ist von http://www.cgtextures.com/)
^ Der Shader
Fangen wir also mit der Deklaration unserer Variablen und Textur-Samplern an:
float4x4 World;
float4x4 View;
float4x4 Projection;
float Strength;
texture Texture0;
sampler2D sampler0 = sampler_state
{
Texture = (Texture0);
MIPFILTER = LINEAR;
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
};
texture Texture1;
sampler2D sampler1 = sampler_state
{
Texture = (Texture1);
MIPFILTER = LINEAR;
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
};
texture TextureMask;
sampler2D samplerMask = sampler_state
{
Texture = (TextureMask);
MIPFILTER = LINEAR;
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
};
float4x4 View;
float4x4 Projection;
float Strength;
texture Texture0;
sampler2D sampler0 = sampler_state
{
Texture = (Texture0);
MIPFILTER = LINEAR;
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
};
texture Texture1;
sampler2D sampler1 = sampler_state
{
Texture = (Texture1);
MIPFILTER = LINEAR;
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
};
texture TextureMask;
sampler2D samplerMask = sampler_state
{
Texture = (TextureMask);
MIPFILTER = LINEAR;
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
};
Neben den obligatorischen Variablen für Welt-, Kamera- und Projektionsmatrix, kommt eine float-Variable welche die Stärke des Effektes repräsentiert. Es folgen die drei Texturen, die wir in unserem Fall benötigen: Textur 1 und 2 sowie die Maske.
Nun kommen wir zum Vertex-Shader:
struct VertexShaderInput
{
float4 Position : POSITION0;
float2 TexCoords : TEXCOORD0;
};
struct VertexShaderOutput
{
float4 Position : POSITION0;
float2 TexCoords : TEXCOORD0;
};
VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
VertexShaderOutput output;
output.Position = mul(input.Position, mul(mul(World, View), Projection));
output.TexCoords = input.TexCoords;
return output;
}
{
float4 Position : POSITION0;
float2 TexCoords : TEXCOORD0;
};
struct VertexShaderOutput
{
float4 Position : POSITION0;
float2 TexCoords : TEXCOORD0;
};
VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
VertexShaderOutput output;
output.Position = mul(input.Position, mul(mul(World, View), Projection));
output.TexCoords = input.TexCoords;
return output;
}
Kommen wir nun zum interessanten Teil, dem Pixel-Shader.
float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
float4 color0 = tex2D(sampler0, input.TexCoords);
float4 color1 = tex2D(sampler1, input.TexCoords);
float4 mask = tex2D(samplerMask, input.TexCoords);
if(Strength >= mask.a)
return color1;
else
return color0;
}
technique TextureBlend
{
pass Pass1
{
VertexShader = compile vs_2_0 VertexShaderFunction();
PixelShader = compile ps_2_0 PixelShaderFunction();
}
}
{
float4 color0 = tex2D(sampler0, input.TexCoords);
float4 color1 = tex2D(sampler1, input.TexCoords);
float4 mask = tex2D(samplerMask, input.TexCoords);
if(Strength >= mask.a)
return color1;
else
return color0;
}
technique TextureBlend
{
pass Pass1
{
VertexShader = compile vs_2_0 VertexShaderFunction();
PixelShader = compile ps_2_0 PixelShaderFunction();
}
}
Dieser Teil ist allerdings auch leicht erklärt.
Zuerst holen wir uns die Farbinformationen des Texels aus den Texturen 1, 2 sowie der Maske. Nun vergleichen wir ob die Stärke, welche wir dem Shader angegeben haben, größer ist als der Alpha-Wert der Maske. Wenn dies der Fall ist, geben wir Textur 2 zurück, sonst Textur 1.
Und das ist schon Alles. Gar nicht so schwer oder?
^ Ende
Über Lob und Kritik freue ich mich natürlich immer gern
Downloaden könnt ihr ein Beispielprojekt mit Content unter folgender Url:
TextureBlend_Tutorial.zip

