Olá pessoal, tudo certo?!
Este é o primeiro post sobre XNA que escrevo desde o TechEd. Fiquei realmente feliz e satisfeito ao perceber tantas pessoas presentes nas minhas palestras.
No post de hoje, mostro a aplicação de uma técnica simples de multitexturing no “game” que estamos desenvolvendo. Veja o resultado:
O post de hoje pode ser percebido como uma “continuação” da parte 13. Se está chegando agora, recomendo a leitura dos outros posts dessa série.
Todo o código fonte está disponível em https://github.com/ElemarJR/VamosAprenderXNA.
IMPORTANTE: O post de hoje é inspirado nas idéias presentes no livro . Realmente achei interessante a proposta do autor e por isso reproduzo o conceito aqui.
Multitexturing, muitas texturas
Multitexturing faz sentindo quando desejamos aplicar mais de uma textura em um mesmo modelo. No “terreno” acima foram utilizadas quatro texturas: Rocha, Areia, Grama e Neve.
Para decidir que textura aplicar, utilizei um mapa de cores.
Basicamente, aplico:
- grama no preto;
- areia no vermelho;
- rocha no verde;
- neve no azul.
O bacana dessa técnica é que podemos modificar a “posição das texturas” simplesmente alterando esse bitmap.
Construindo o Effect
O effect proposto no livro é extramemente simples. Começa pelas texturas e samplers. Observe:
texture RTexture; sampler RTextureSampler = sampler_state { texture =; AddressU = Wrap; AddressV = Wrap; MinFilter = Anisotropic; MagFilter = Anisotropic; }; texture GTexture; sampler GTextureSampler = sampler_state { texture = ; AddressU = Wrap; AddressV = Wrap; MinFilter = Anisotropic; MagFilter = Anisotropic; }; texture BTexture; sampler BTextureSampler = sampler_state { texture = ; AddressU = Wrap; AddressV = Wrap; MinFilter = Anisotropic; MagFilter = Anisotropic; }; texture BaseTexture; sampler BaseTextureSampler = sampler_state { texture = ; AddressU = Wrap; AddressV = Wrap; MinFilter = Anisotropic; MagFilter = Anisotropic; }; texture WeightMap; sampler WeightMapSampler = sampler_state { texture = ; AddressU = Wrap; AddressV = Wrap; MinFilter = Anisotropic; MagFilter = Anisotropic; };
Depois, parâmetros básicos e estrutura de dados:
float4x4 World; float4x4 View; float4x4 Projection; float3 LightDirection = float3(1, -1, 0); float TextureTiling = 6; struct VertexShaderInput { float4 Position : POSITION0; float2 UV : TEXCOORD0; float3 Normal : NORMAL0; }; struct VertexShaderOutput { float4 Position : POSITION0; float2 UV : TEXCOORD0; float3 Normal : TEXCOORD1; };
Por fim, os shaders:
VertexShaderOutput VertexShaderFunction(VertexShaderInput input) { VertexShaderOutput output; float4 worldPosition = mul(input.Position, World); float4 viewPosition = mul(worldPosition, View); output.Position = mul(viewPosition, Projection); output.Normal = input.Normal; output.UV = input.UV; return output; } float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0 { float light = dot( normalize(input.Normal), normalize(LightDirection) ); light = clamp(light + 0.4f, 0, 1); float3 rtex = tex2D(RTextureSampler, input.UV * TextureTiling); float3 gtex = tex2D(GTextureSampler, input.UV * TextureTiling); float3 btex = tex2D(BTextureSampler, input.UV * TextureTiling); float3 base = tex2D(BaseTextureSampler, input.UV * TextureTiling); float3 weightMap = tex2D(WeightMapSampler, input.UV); float3 output = clamp(1.0f - weightMap.r - weightMap.g - weightMap.b, 0, 1); output *= base; output += weightMap.r * rtex + weightMap.g * gtex + weightMap.b * btex; return float4(output * light, 1); } technique Technique1 { pass Pass1 { VertexShader = compile vs_2_0 VertexShaderFunction(); PixelShader = compile ps_2_0 PixelShaderFunction(); } }
Repare como a combinação entre as texturas é feita de forma extremamente simples. Basicamente, utilizamos a “intensidade” de cada elemento no WeightMap para aplicar a textura que desejamos.
A configuração no Game também é bastante simples:
var effect = Content.Load("MultitextureTerrainEffect"); effect.Parameters["WeightMap"].SetValue(Content.Load ("WeightMap")); effect.Parameters["BaseTexture"].SetValue(Content.Load ("grass")); effect.Parameters["RTexture"].SetValue(Content.Load ("sand")); effect.Parameters["GTexture"].SetValue(Content.Load ("rock")); effect.Parameters["BTexture"].SetValue(Content.Load ("snow"));
Bacana!
Era isso!
Publicado em 11/10/2011
0