Hi all,
I’ve been experiencing some difficulty porting a bunch of my existing shaders from DX9 to DX11 when trying to get my project to run under DX11 today. In short, after fixing a few compiler errors, everything compiled but it started rendering wrong in ways that indicated some transformation matrix confusion.
So I spent the day having a bit of fun messing around with the built-in matrices under DX11 to see what was wrong. I tested these 5 guys in particular:
_Object2World - The current model matrix
UNITY_MATRIX_V - The current view matrix
UNITY_MATRIX_P - The current projection matrix
UNITY_MATRIX_VP - The concatenation between the current view and projection matrix
UNITY_MATRIX_MVP - The full, concatenated ModelViewProjection matrix
I wrote this simple shader (full code) for it:
Shader "Custom/TestVF"
{
Properties
{
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
pass
{
CGPROGRAM
#include "UnityCG.cginc"
#pragma vertex vert
#pragma fragment frag
struct vertOut
{
float4 position : POSITION;
};
vertOut vert(appdata_full vertIn)
{
vertOut o;
o.position = mul(UNITY_MATRIX_MVP, vertIn.vertex);
return o;
}
void frag(out float4 c_out : COLOR)
{
c_out = float4(0,1,0,1);
}
ENDCG
}
}
FallBack "Diffuse"
}
I.e. a totally basic pass-through. This works as expected. I then started playing around with the matrices in the vertex shader. First, I did this (vertex shader only):
vertOut vert(appdata_full vertIn)
{
vertOut o;
float4 vertWorld = mul(_Object2World, vertIn.vertex);
o.position = mul(UNITY_MATRIX_VP, vertWorld);
return o;
}
That should do exactly the same, it just does the same transformation over 2 matrix calculations instead of one. It inserts a temporary “stop” in world space.
Interestingly, this does not yield the same result. O_O
I was surprised to see my sphere get positioned in the lower left corner of the screen, and also stretched along the x-axis. That behaviour is under DX11 only, it works fine if I untick it in player settings and go back to DX9.
More interestingly, I then split the calculation apart even further and did all 3 calculations step-by-step using the individual matrices, so the vertex shader becomes this:
vertOut vert(appdata_full vertIn)
{
vertOut o;
float4 vertWorld = mul(_Object2World, vertIn.vertex);
float4 vertView = mul(UNITY_MATRIX_V, vertWorld);
o.position = mul(UNITY_MATRIX_P, vertView);
return o;
}
If I do this, then we’re back to working as expected. That vertex shader does exactly the same as the one that uses the standard MVP matrix. I have the deepest respect for Unity’s guys, so I’m a little leery of suggesting something like this, but I can’t find any other explanation for this behaviour than the concatenated view*projection matrix (UNITY_MATRIX_VP) being set wrong under DX11.
It would be wonderful if anyone would be willing to give this a spin on their machine to see if they get the same results. I saved the test project which is very small and attached the zip file to this post.
The project is a testscene with a green sphere, and you can comment and uncomment the relevant lines in the shader to see the effect I’m talking about. Please let me know if I’m just stupid and made some silly mistake in the code above. ![]()
1802466–114919–Dx9VsDX11.zip (1.53 MB)