The difference is… there isn’t one. They’re the same value. UNITY_MATRIX_M is a macro for unity_ObjectToWorld.
#define UNITY_MATRIX_M unity_ObjectToWorld
A 3x4 transform matrix is the full transform matrix without support for perspective transforms like those used in UNITY_MATRIX_VP and UNITY_MATRIX_P. A 3x3 transform matrix is scale and rotation without translation, and is what you should be using for transforming non-position vectors. You’ll have to normalize the vector afterwards if it’s supposed to be a normalized direction vector.
First, that’s not a branch. That’s a shader preprocessor condition.
Second, I’m not that familiar with the HDRP shader code, so my original answer wasn’t correct. My answer applies to the built in rendering path only. That snippet of code tells me you should not use ObjectToWorld3x4() at all because that’s explicitly for ray tracing. I was incorrectly assuming that’d been a typo on your part as 3x4 matrices aren’t generally used by Unity shaders since they not allowed by some rendering APIs. But if Unity is using them for ray tracing shaders that makes sense.
And third, if you don’t know if you’re writing a ray tracing shader or not, you aren’t.
ObjectToWorld3x4() works only in ray tracing hit shaders. If this is your case then to correctly transform the normal from local space to world space you can do:
Thanks for help, but it still confusing for me… why ObjectToWorld3x4() can be used in TransformObjectToWorldDir when shader is not ray tracing, and why can’t invoke this alone even though including SpaceTransform.hlsl(you know there is no definition and also no #include, but only used in)?
sorry to bother you. just because of my curiosity…
I really hope so… I thought there is some kind of formula like normal vector transform(it was easily misunderstood to wrong code for me). Even if it’s a bug, there’s a problem that why still can not invoke ObjectToWorld3x4() alone. According to this, and when shader is not ray tracing, TransformObjectToWorld doesn’t have a problem but TransformObjectToWorldDir must not work because it use ObjectToWorld3x4() when shader is not ray tracing.
I don’t understand how unity_ObjectToWorld can be the same as UNITY_MATRIX_M.
Because when i replace one by the other, the behavior of my shader changes…
For example I had a shader with GPU instancing that is drawn with Graphics.RenderMeshInstanced, that didn’t work with unity_ObjectToWorld, I just replaced it to UNITY_MATRIX_M and it started working.
The same shader would work with both unity_ObjectToWorld and UNITY_MATRIX_M though when using Graphics.RenderMesh without gpu instancing..
When not instancing, the transform matrix comes from a single variable, the unity_ObjectToWorld. The UNITY_MATRIX_M then gets defined as a macro for that variable.
When instancing, the transform matrices come from an array.
In the built in rendering path, this is done by redefining the unity_ObjectToWorld to be a macro to get the transform out of that array, thus both unity_ObjectToWorld and UNITY_MATRIX_M continue to work.
However for the URP and HDRP, this was changed so that they instead redefine UNITY_MATRIX_M directly be what gets data from the array.
And unity_ObjectToWorld got redefined to be passive aggressive.
It gets defined to nothing. My expectation is when using that shader with instancing, you’re getting a shader compilation error that you’re missing and either drawing nothing, or it’s falling back to the non-instanced version of the shader.