[SOLVED] Strange behaviour when rendering 3D model with custom effect

Hello MonoGame Community,
I’ve been trying to render a 3D model using a custom effect:

float4x4 World;
float4x4 View;
float4x4 Projection;

float4 AmbientColor;
float AmbientIntensity;

struct VertexShaderInput
{
    float4 Position : POSITION0;
};
 
struct VertexShaderOutput
{
    float4 Position : POSITION0;
};
 
VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
    VertexShaderOutput output;
 
    float4 worldPosition = mul(input.Position, World);
    float4 viewPosition = mul(worldPosition, View);
    output.Position = mul(viewPosition, Projection);
 
    return output;
}

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
    return AmbientColor*AmbientIntensity;
}

technique Technique1
{
    pass Pass1
    {
        VertexShader = compile vs_2_0 VertexShaderFunction();
        PixelShader = compile ps_2_0 PixelShaderFunction();
    }
}

This effect works perfectly when rendering a cube from a vertex buffer, however when drawing with a model loaded through the content pipeline the model seems to fill the entire screen (it doesn’t with BasicEffect). I think I am rendering it right (I got the code from an rb whitaker tutorial) because the ambient colour appears to be applied.
Any ideas why this might be?

Try SV_POSITION instead of POSTION0 in the vertex shader output.

struct VertexShaderOutput
{
    float4 Position : SV_POSITION;
};

I’m actually not sure if GL really needs SV_POSITION. Maybe your are just missing the internal matrices that are inside the model class?

Thanks for your replies!
The change to the shader didn’t help and I think the matrices are being accounted for but this is the drawing code just in case:

private void DrawModelWithEffect(Model model, Matrix world, Matrix view, Matrix projection)

        {

            foreach (ModelMesh mesh in model.Meshes)

            {

                foreach (ModelMeshPart part in mesh.MeshParts)

                {

                    part.Effect = epicEffect;

                    epicEffect.Parameters["World"].SetValue(world * mesh.ParentBone.Transform);

                    epicEffect.Parameters["View"].SetValue(view);

                    epicEffect.Parameters["Projection"].SetValue(projection);

                }

                mesh.Draw();

            }

        }

Just worked it out, removing the * mesh.ParentBone.Transform, from where world matrix is set seemed to fix it. I think this will prevent animations, but that is not a concern with this project.

Those bone transforms can have parent transforms, this might be why the scale is off.

The model class has a draw function, which you could probably use. Here’s the code for it, see how it’s treating the bone transforms differently:

public void Draw(Matrix world, Matrix view, Matrix projection) 
{       
    int boneCount = this.Bones.Count;
	
	if (sharedDrawBoneMatrices == null ||
		sharedDrawBoneMatrices.Length < boneCount)
	{
		sharedDrawBoneMatrices = new Matrix[boneCount];    
	}
	
	// Look up combined bone matrices for the entire model.            
	CopyAbsoluteBoneTransformsTo(sharedDrawBoneMatrices);

    // Draw the model.
    foreach (ModelMesh mesh in Meshes)
    {
        foreach (Effect effect in mesh.Effects)
        {
			IEffectMatrices effectMatricies = effect as IEffectMatrices;
			if (effectMatricies == null) {
				throw new InvalidOperationException();
			}
            effectMatricies.World = sharedDrawBoneMatrices[mesh.ParentBone.Index] * world;
            effectMatricies.View = view;
            effectMatricies.Projection = projection;
        }

        mesh.Draw();
    }
}

It’s using CopyAbsoluteBoneTransformsTo, which also takes parent transforms into account:

public void CopyAbsoluteBoneTransformsTo(Matrix[] destinationBoneTransforms)
{
	if (destinationBoneTransforms == null)
		throw new ArgumentNullException("destinationBoneTransforms");
    if (destinationBoneTransforms.Length < this.Bones.Count)
		throw new ArgumentOutOfRangeException("destinationBoneTransforms");
    int count = this.Bones.Count;
	for (int index1 = 0; index1 < count; ++index1)
	{
        ModelBone modelBone = (this.Bones)[index1];
		if (modelBone.Parent == null)
		{
			destinationBoneTransforms[index1] = modelBone.transform;
		}
		else
		{
			int index2 = modelBone.Parent.Index;
			Matrix.Multiply(ref modelBone.transform, ref destinationBoneTransforms[index2], out destinationBoneTransforms[index1]);
		}
	}
}