I’m converting an XNA project into MonoGame, and I have just one more issue to sort! However, I’ve been pouring over it for a few hours, and cannot work out why it’s doing this.
I have a vertex structure defined as follows (note the s in Normals, to distinguish):
public struct VertexPositionNormalsTexture : IVertexType
{
public Vector4 Position;
public Vector3 Normal;
public Vector3 Binormal;
public Vector3 Tangent;
public Vector2 TextureCoordinates;
static VertexDeclaration vertexDeclaration;
static VertexPositionNormalsTexture()
{
vertexDeclaration = new VertexDeclaration(
new VertexElement(0, VertexElementFormat.Vector4, VertexElementUsage.Position, 0),
new VertexElement(16, VertexElementFormat.Vector3, VertexElementUsage.Normal, 0),
new VertexElement(28, VertexElementFormat.Vector3, VertexElementUsage.Normal, 1),
new VertexElement(40, VertexElementFormat.Vector3, VertexElementUsage.Normal, 2),
new VertexElement(52, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0)
);
}
public VertexDeclaration VertexDeclaration { get { return vertexDeclaration; } }
public VertexPositionNormalsTexture(Vector3 position, Vector3 normal, Vector3 binormal, Vector3 tangent, Vector2 texCoord)
{
Position = new Vector4(position, 1);
Normal = normal;
Binormal = binormal;
Tangent = tangent;
TextureCoordinates = texCoord;
}
}
When I draw using a custom effect, it acts as though the incoming vertex data is all zeroes, except for the position. Even if I try outputting any of them as a colour in the pixel shader, it’s black. However, if I assign a literal value to them in the vertex shader, it works just fine. So it seems that the matter is as it’s being passed in to the vertex shader. There are no error messages, warnings, or exceptions given.
Here are the relevant bits of my effect:
float4x4 World;
float4x4 View;
float4x4 Projection;
//other parameters here
struct VertexShaderInput
{
float4 Position : POSITION0;
float3 Normal : NORMAL0;
float3 Binormal : NORMAL1;
float3 Tangent : NORMAL2;
float2 TexCoord : TEXCOORD0;
};
struct VertexShaderOutput
{
float4 Position : POSITION0;
float3 Normal : TEXCOORD0;
float3 Binormal : TEXCOORD1;
float3 Tangent : TEXCOORD2;
float2 TexCoord : TEXCOORD3;
float2 ScreenPosition : TEXCOORD4;
};
//sampler states here
VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
VertexShaderOutput output;
output.Normal = normalize(mul(input.Normal, (float3x3)World));
output.Binormal = normalize(mul(input.Binormal, (float3x3)World));
output.Tangent = normalize(mul(input.Tangent, (float3x3)World));
output.TexCoord = input.TexCoord;
float4 worldPosition = mul(input.Position, World);
float4 viewPosition = mul(worldPosition, View);
output.Position = mul(viewPosition, Projection);
output.ScreenPosition = output.Position.xy * .5 * float2(1, -1) + .5;
return output;
}
//other pixel shaders here
float4 LightMapPixelShaderFunction(VertexShaderOutput input) : COLOR0
{
return float4(input.Tangent, 1);
//even this fails, displaying just black, even though the incoming vertex data has a Tangent of (1, 0, 0).
}
//other techniques here
technique LightMap
{
pass Pass1
{
// TODO: set renderstates here.
VertexShader = compile vs_2_0 VertexShaderFunction();
PixelShader = compile ps_2_0 LightMapPixelShaderFunction();
}
}
So, am I just overlooking something really stupid? Did I miss something in the conversion? Or perhaps is Monogame doing some sort of unfortunate optimisation?