Jump to content
  • Advertisement
Sign in to follow this  
Spa8nky

Fx Composer 2 Metal Shader Doesn'T Draw Correctly With Xna?

This topic is 2808 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm using a metal shader obtained from FX and I've commented it so it makes more sense to me. The problem is that the vertex shader:



// Data from application vertex buffer [XNA]
struct appdata
{
float3 Position : POSITION0;
float4 UV : TEXCOORD0;
float4 Normal : NORMAL0;
float4 Tangent : TANGENT0;
float4 Binormal : BINORMAL0;
};


vertexOutput VertexShaderFunction(appdata IN,
uniform float4x4 WorldITXf, // our four standard "untweakable" xforms
uniform float4x4 WorldXf,
uniform float4x4 ViewIXf,
uniform float4x4 WvpXf,
uniform float3 LampDir
)
{
vertexOutput OUT = (vertexOutput)0;

OUT.WorldNormal = mul(WorldITXf,IN.Normal).xyz;
OUT.WorldTangent = mul(WorldITXf,IN.Tangent).xyz;
OUT.WorldBinormal = mul(WorldITXf,IN.Binormal).xyz;

float4 Po = float4(IN.Position.xyz,1); // Homogeneous location coordinates (object)
float4 Pw = mul(WorldXf,Po); // Convert to "world" space

#ifdef OBJECT_SPACE_LIGHTS
float4 Lo = float4(LampDir.xyz,0.0); // Light in object space
float4 Lw = mul(WorldXf,Lo); // Convert to "world" space
OUT.LightVec = -normalize(Lw).xyz;
#else /* !OBJECT_SPACE_LIGHTS -- standard world-space lights */
OUT.LightVec = -normalize(LampDir);
#endif

#ifdef FLIP_TEXTURE_Y
OUT.UV = float2(IN.UV.x,(1.0-IN.UV.y));
#else
OUT.UV = IN.UV.xy;
#endif

OUT.WorldView = normalize(float3(ViewIXf[0].w,ViewIXf[1].w,ViewIXf[2].w) - Pw.xyz);
OUT.HPosition = mul(WvpXf,Po);

return OUT;
}



is producing this result:

MetalShaderProblem.png


instead of draw a box.

I'm setting the HLSL parameters as follows:




effect.Parameters["gViewIXf"].SetValue(Matrix.Invert(game.ActiveCamera.ViewMatrix));
effect.Parameters["gWorldXf"].SetValue(worldTransform);
effect.Parameters["gWorldITXf"].SetValue(Matrix.Invert(Matrix.Transpose(worldTransform)));
effect.Parameters["gWvpXf"].SetValue(worldTransform * game.ActiveCamera.ViewProjectionMatrix);


The model used has all the correct elements in its vertex format for input:




struct appdata
{
float3 Position : POSITION0;
float4 UV : TEXCOORD0;
float4 Normal : NORMAL0;
float4 Tangent : TANGENT0;
float4 Binormal : BINORMAL0;
};


My view matrix is created as follows:



// Make our view matrix
Matrix.CreateFromQuaternion(ref orientation, out matrix_View);

matrix_View.M41 = -Vector3.Dot(Right, position);
matrix_View.M42 = -Vector3.Dot(Up, position);
matrix_View.M43 = -Vector3.Dot(-Forward, position);
matrix_View.M44 = 1.0f;

// Create the combined view-projection matrix
Matrix.Multiply(ref matrix_View, ref matrix_Projection, out matrix_ViewProj);



My projection matrix is created like so:



private void Perspective(float aspect_Ratio, float z_NearClipPlane, float z_FarClipPlane)
{
nearClipPlaneZ = z_NearClipPlane;
farClipPlaneZ = z_FarClipPlane;

float yZoom = 1.0f / (float)Math.Tan(MathHelper.ToRadians(GlobalSettings.FOV_X) * 0.5f);
float xZoom = yZoom / aspect_Ratio;

matrix_Projection.M11 = xZoom;
matrix_Projection.M12 = 0.0f;
matrix_Projection.M13 = 0.0f;
matrix_Projection.M14 = 0.0f;

matrix_Projection.M21 = 0.0f;
matrix_Projection.M22 = yZoom;
matrix_Projection.M23 = 0.0f;
matrix_Projection.M24 = 0.0f;

matrix_Projection.M31 = 0.0f;
matrix_Projection.M32 = 0.0f;
matrix_Projection.M33 = z_FarClipPlane / (nearClipPlaneZ - farClipPlaneZ);
matrix_Projection.M34 = -1.0f;

matrix_Projection.M41 = 0.0f;
matrix_Projection.M42 = 0.0f;
matrix_Projection.M43 = (nearClipPlaneZ * farClipPlaneZ) / (nearClipPlaneZ - farClipPlaneZ);
matrix_Projection.M44 = 0.0f;
}


Can anyone please explain what might be causing this issue as I can't figure it out.

Share this post


Link to post
Share on other sites
Advertisement
Are you setting the LampDir parameter anywhere? Your screenshot is too dark to see what's going on...is the geometry being transformed properly? In other words...if you set the pixel shader to just output 1, does the box still have the correct shape?

You also want to be careful with your normals, tangents, and binormals. These vectors are directions, not positions, and thus you only want to rotate them and not translate them. Typically in a vertex shader you take them as float3 inputs, and then transform them by your matrix cast to a (float3x3). Or alternatively, you can set the W component to 0. This ensures that no translation occurs.

OUT.WorldNormal = mul(IN.Normal.xyz, (float3x3)WorldITXf);
OUT.WorldNormal = mul(float4(IN.Normal.xyz, 0.0f), WorldITXf).xyz;

Share this post


Link to post
Share on other sites
[color="#1C2837"][color=#000000][font=arial, verdana, tahoma, sans-serif][size=2]
[color=#1C2837][size=2]Thanks MJP.[/font]
[color=#1C2837][size=2]

[color=#1C2837][size=2]
[color=#1C2837][size=2]Are you setting the LampDir parameter anywhere?
[color=#1C2837][size=2]


[color=#1C2837][size=2]

[color=#1C2837][size=2]Yes, it is constant for the time being as I'm not setting it in XNA:
[color=#1C2837][size=2]

[color=#1C2837][size=2]
[color=#1C2837][size=2]
float3 gLamp0Dir : DIRECTION <
string Object = "DirectionalLight0";
string UIName = "Lamp 0 Direction";
string Space = (LIGHT_COORDS);
> = {0.7f,-0.7f,-0.7f};
[color=#1C2837][size=2]
[color=#1C2837][size=2]

[color=#1C2837][size=2]

[color=#1C2837][size=2]

[color=#1C2837][size=2]Your screenshot is too dark to see what's going on...is the geometry being transformed properly? In other words...if you set the pixel shader to just output 1, does the box still have the correct shape?
[color=#1C2837][size=2]

[color=#1C2837][size=2]

[color=#1C2837][size=2]The geometry is not being transformed properly:
[color=#1C2837][size=2]

MetalShaderProblem2.png
[color="#1C2837"]

[color="#1C2837"]

[color="#1C2837"]You also want to be careful with your normals, tangents, and binormals. These vectors are directions, not positions, and thus you only want to rotate them and not translate them. Typically in a vertex shader you take them as float3 inputs, and then transform them by your matrix cast to a (float3x3). Or alternatively, you can set the W component to 0. This ensures that no translation occurs.
[color="#1C2837"][/quote]

[color="#1C2837"]

[color="#1C2837"]Casting the transform matrix to a (float3x3) also made no difference:
[color="#1C2837"]

[color="#1C2837"]
[color="#1C2837"]
//OUT.WorldNormal = mul(WorldITXf,IN.Normal).xyz;
//OUT.WorldTangent = mul(WorldITXf,IN.Tangent).xyz;
//OUT.WorldBinormal = mul(WorldITXf,IN.Binormal).xyz;

OUT.WorldNormal = mul((float3x3)WorldITXf,IN.Normal).xyz;
OUT.WorldTangent = mul((float3x3)WorldITXf,IN.Tangent).xyz;
OUT.WorldBinormal = mul((float3x3)WorldITXf,IN.Binormal).xyz;
[color="#1C2837"]


[color="#1C2837"]

[color="#1C2837"]If I change the input struct as follows:
[color="#1C2837"]

[color="#1C2837"]
[color="#1C2837"]
// Data from application vertex buffer [XNA]
struct appdata
{
float3 Position : POSITION0;
float2 UV : TEXCOORD0;
float3 Normal : NORMAL0;
float3 Tangent : TANGENT0;
float3 Binormal : BINORMAL0;
};
[color="#1C2837"]


[color="#1C2837"]

[color="#1C2837"]Then that made no difference either.
[color="#1C2837"]

[color="#1C2837"]Changing the order of multiplication for the transforms:
[color="#1C2837"]

[color="#1C2837"]
[color="#1C2837"]
OUT.WorldNormal = mul(IN.Normal,WorldITXf).xyz;
OUT.WorldTangent = mul(IN.Tangent,WorldITXf).xyz;
OUT.WorldBinormal = mul(IN.Binormal,WorldITXf).xyz;
[color="#1C2837"]


[color="#1C2837"]

[color="#1C2837"]Didn't change a thing.
[color="#1C2837"]

[color="#1C2837"]What else could it be?

Share this post


Link to post
Share on other sites
OK I've solved it!

I must remember:

1) XNA != DirectX even though XNA is wrapper for DirectX.
2) Coordinate handedness is Left for DirectX BUT Right for XNA

FX Composer must export .fx files for DirectX?!

Therefore I just need change transform mul order and everything is good again. :)

Thanks for the help.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!