Search Unity

Difference between UnityObjectToWorldDir and UnityObjectToWorldNormal?

Discussion in 'Shaders' started by yxliang01, Oct 8, 2016.

  1. yxliang01

    yxliang01

    Joined:
    Oct 8, 2016
    Posts:
    5
    Those two helpers functions are in unity.cginc . They are so useful! However, although their implementations are different, I can't really understand why they are different. Thanks!
     
    IgorAherne likes this.
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    WorldDir is applying the rotation from the transform matrix.
    WorldNormal is apply the rotation from the inverse transpose matrix.

    There are a number of pages on the internet that try to explain why, though most do so with a lot of math and text when I feel like three images can be enough.

    http://web.archive.org/web/20120228...Illumination/Tut09 Normal Transformation.html

    On this page scroll down a little until you see a circle and two elipses with arrows drawn on them. The first elipse is what the normals look like if you have a squished circle and do the equivalent of UnityObjectToWorldDir() to the normals. Notice the normals are also squished and are no longer perpendicular to the surface. The second elipse is what the normals look like using the equivalent of UnityObjectToWorldNormal(). Notice the normals are properly perpendicular to the surface.
     
    IgorAherne, Pheonix14 and Audgess like this.
  3. ifurkend

    ifurkend

    Joined:
    Sep 4, 2012
    Posts:
    350
    I assume UnityObjectToWorldDir(tangent) and UnityObjectToWorldNormal(normal) are practically identical for a simple unbend quad then.
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    For a flat quad with no scaling, yes, those two functions produce identical results. UnityObjectToWorldDir(myVector) is effectively, if not literally:
    mul((float3x3)unity_ObjectToWorld, myVector)
    Just your basic rotation multiplication of the objec to world matrix.

    Where UnityObjectToWorldNormal(myVector) is a little different and does an inverse transpose rotation matrix, which as of 5.6 I think looks like this:
    mul(myVector, (float3x3)unity_WorldToObject)

    If the mesh is uniformly scaled those will produce algebraicly identical results, and if not it'll prevent the normals from being squashed.
    https://paroj.github.io/gltut/Illumination/Tut09 Normal Transformation.html