I have recently been converting our XNA 3.1 game to XNA 4.0 and am stuck on the shaders. I have the game running, but nothing is drawing to the screen, except things not using a shader.
This is only 2D drawing, using SpriteBatch, which im sure is where the problem is coming from.
In XNA 3.1 everything works fine with my custom vertex and pixel shaders targeting SM 3.0. I cant find any info on what has changed or why its not working. Ive stripped it down as far as I can to try to figure it out, but am not sure. It definitely seems like a coordinate issue with the vertex shader. If I strip our the vertex shader and switch to SM 2.0 for the pixel shader so it uses XNAs default vertex shader for SpriteBatch, it works as expected, but I need 3.0 and custom vertex shader functionality.
Here is stripped down version of things, I cant get PS to output anything anywhere:
// Input parameters.
float2 ViewportSize : register(c0);
float2 TextureSize : register(c1);
float4x4 MatrixTransform : register(c2);
sampler TextureSampler : register(s0);
struct VS_INPUT
{
float4 position : POSITION0;
float4 color : COLOR0;
float2 texCoord : TEXCOORD0;
};
struct VS_OUTPUT
{
float4 position : POSITION0;
float4 color : COLOR0;
float2 texCoord : TEXCOORD0;
};
struct PS_INPUT
{
float4 color : COLOR0;
float2 texCoord : TEXCOORD0;
};
VS_OUTPUT VertexTileShader(VS_INPUT input)
{
VS_OUTPUT output = (VS_OUTPUT)0;
float4 position = input.position;
// Apply the matrix transform.
output.position = mul(position, transpose(MatrixTransform));
// Half pixel offset for correct texel centering.
output.position.xy -= 0.5;
// Viewport adjustment.
output.position.xy /= ViewportSize;
output.position.xy *= float2(2, -2);
output.position.xy -= float2(1, -1);
// Compute the texture coordinate.
output.texCoord = input.texCoord / TextureSize;
// Pass on color
output.color = input.color;
return (output);
}
float4 PSTileLighting(PS_INPUT input) : COLOR
{
return float4(1.0, 1.0, 1.0, 1.0);
}
technique TileLighting
{
pass Pass1
{
VertexShader = compile vs_3_0 VertexTileShader();
PixelShader = compile ps_3_0 PSTileLighting();
}
}
C#:
// Setup matrix
transform = Matrix.CreateTranslation(-bounds.X, -bounds.Y, 0);
// Setup viewport
SectionViewport.X = 0;
SectionViewport.Y = 0;
SectionViewport.Width = bounds.Width;
SectionViewport.Height = bounds.Height;
Engine.GraphicsDevice.SetRenderTarget(background);
Engine.GraphicsDevice.Viewport = SectionViewport;
Engine.GraphicsDevice.Clear(Color.Transparent);
Map.TilesEffect.CurrentTechnique = Map.TilesEffect.Techniques["TileLighting"];
Vector2 viewportSize = new Vector2(SectionViewport.Width, SectionViewport.Height);
Map.TilesEffect.Parameters["ViewportSize"].SetValue(viewportSize);
Map.TilesEffect.Parameters["TextureSize"].SetValue(new Vector2(2048, 2048));
Engine.SpriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, null, null, null, Map.TilesEffect, transform);
DrawTiles(tileLayer, 0, 5, bounds, Color.White);
Engine.SpriteBatch.End();
DrawTiles calls the draw function on all the tiles within the bounds rectangle. They are all in a large 2048x2048 sprite sheet. Map is broken up into blocks of these which the transform matrix is used to offset.
This all works in XNA 3.1. I stripped the pixel shader to absolutely nothing, just outputs white (or is supposed to). Im sure its not any of the specific drawing code because like I said if I switch to the default SpriteBatch vertex shader (IE not defining one, and rolling the PS back to 2.0). Then it works as expected. It draws white pixels everywhere it should.
There must be something wrong im doing with the matrix / viewport manipulations, but am not sure what. Ive looked at SpriteBatches default shader, but it uses a lot of macros and sets the matrix up before going to the shader and not sure how to correlate it with mine.
Any help is appreciated, thanks.