XNA 4 Deferred Rendering deforms the model
- by Tomáš Bezouška
I have a problem when rendering a model of my World - when rendered using BasicEffect, it looks just peachy. Problem is when I render it using deferred rendering. See for yourselves:
what it looks like: http://imageshack.us/photo/my-images/690/survival.png/
what it should look like: http://imageshack.us/photo/my-images/521/survival2.png/
(Please ignora the cars, they shouldn't be there. Nothing changes when they are removed)
Im using Deferred renderer from
www.catalinzima.com/tutorials/deferred-rendering-in-xna/introduction-2/
except very simplified, without the custom content processor. Here's the code for the GBuffer shader:
float4x4 World;
float4x4 View;
float4x4 Projection;
float specularIntensity = 0.001f;
float specularPower = 3;
texture Texture;
sampler diffuseSampler = sampler_state
{
Texture = (Texture);
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
MIPFILTER = LINEAR;
AddressU = Wrap;
AddressV = Wrap;
};
struct VertexShaderInput
{
float4 Position : POSITION0;
float3 Normal : NORMAL0;
float2 TexCoord : TEXCOORD0;
};
struct VertexShaderOutput
{
float4 Position : POSITION0;
float2 TexCoord : TEXCOORD0;
float3 Normal : TEXCOORD1;
float2 Depth : TEXCOORD2;
};
VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
VertexShaderOutput output;
float4 worldPosition = mul(input.Position, World);
float4 viewPosition = mul(worldPosition, View);
output.Position = mul(viewPosition, Projection);
output.TexCoord = input.TexCoord; //pass the texture coordinates further
output.Normal = mul(input.Normal,World); //get normal into world space
output.Depth.x = output.Position.z;
output.Depth.y = output.Position.w;
return output;
}
struct PixelShaderOutput
{
half4 Color : COLOR0;
half4 Normal : COLOR1;
half4 Depth : COLOR2;
};
PixelShaderOutput PixelShaderFunction(VertexShaderOutput input)
{
PixelShaderOutput output;
output.Color = tex2D(diffuseSampler, input.TexCoord); //output Color
output.Color.a = specularIntensity; //output SpecularIntensity
output.Normal.rgb = 0.5f * (normalize(input.Normal) + 1.0f); //transform normal domain
output.Normal.a = specularPower; //output SpecularPower
output.Depth = input.Depth.x / input.Depth.y; //output Depth
return output;
}
technique Technique1
{
pass Pass1
{
VertexShader = compile vs_2_0 VertexShaderFunction();
PixelShader = compile ps_2_0 PixelShaderFunction();
}
}
And here are the rendering parts in XNA:
public void RednerModel(Model model, Matrix world)
{
Matrix[] boneTransforms = new Matrix[model.Bones.Count];
model.CopyAbsoluteBoneTransformsTo(boneTransforms);
Game.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
Game.GraphicsDevice.BlendState = BlendState.Opaque;
Game.GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
foreach (ModelMesh mesh in model.Meshes)
{
foreach (ModelMeshPart meshPart in mesh.MeshParts)
{
GBufferEffect.Parameters["View"].SetValue(Camera.Instance.ViewMatrix);
GBufferEffect.Parameters["Projection"].SetValue(Camera.Instance.ProjectionMatrix);
GBufferEffect.Parameters["World"].SetValue(boneTransforms[mesh.ParentBone.Index] * world);
GBufferEffect.Parameters["Texture"].SetValue(meshPart.Effect.Parameters["Texture"].GetValueTexture2D());
GBufferEffect.Techniques[0].Passes[0].Apply();
RenderMeshpart(mesh, meshPart);
}
}
}
private void RenderMeshpart(ModelMesh mesh, ModelMeshPart part)
{
Game.GraphicsDevice.SetVertexBuffer(part.VertexBuffer);
Game.GraphicsDevice.Indices = part.IndexBuffer;
Game.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList,
0, 0, part.NumVertices,
part.StartIndex, part.PrimitiveCount);
}
I import the model using the built in content processor for FBX. The FBX is created in 3DS Max. I don't know the exact details of that export, but if you think it might be relevant, I will get them from my collegue who does them.
What confuses me though is why the BasicEffect approach works... seems the FBX shouldnt be a problem.
Any thoughts? They will be greatly appreciated :)