Search Unity

  1. Check out our Unite Austin 2017 YouTube playlist to catch up on what you missed. More videos coming soon.
    Dismiss Notice
  2. Unity 2017.2 is now released.
    Dismiss Notice
  3. The Unity Gear Store is here to help you look great at your next meetup, user group or conference. With all new Unity apparel, stickers and more!
    Dismiss Notice
  4. Introducing the Unity Essentials Packs! Find out more.
    Dismiss Notice
  5. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice
  6. Unity 2017.3 beta is now available for download.
    Dismiss Notice

_Object2World or UNITY_MATRIX_IT_MV?

Discussion in 'Shaders' started by sbin3776, Nov 19, 2011.

  1. sbin3776

    sbin3776

    Joined:
    Oct 31, 2011
    Posts:
    18
    In unity's vertex shader,I need transform v.normal to world space, but I don't understand _Object2World and UNITY_MATRIX_IT_MV. Which one should I use?
    mul( (float3x3)_Object2World, v.normal) or mul( (float3x3)UNITY_MATRIX_IT_MV, v.normal ) ?
     
  2. Daniel-Brauer

    Daniel-Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,317
    UNITY_MATRIX_IT_MV is for rotating normals from object into eye space.
     
  3. sbin3776

    sbin3776

    Joined:
    Oct 31, 2011
    Posts:
    18
    That means that I should use _Object2World for rotating v.normal from objectspace into worldspace?
     
  4. kev42100

    kev42100

    Joined:
    Apr 17, 2010
    Posts:
    44
    I think you wanted to say : UNITY_MATRIX_IT_MV is for rotating normals from eye into object space.
    Inverse Transpose matrix.

    To sbin3776 : Yes, use _Object2World, the name is quite explicit ;)
     
  5. Daniel-Brauer

    Daniel-Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,317
    No, what I wrote is correct. You can read a derivation of inverse transpose model view matrix (also called the normal matrix) here.
     
  6. Martin-Kraus

    Martin-Kraus

    Joined:
    Feb 18, 2011
    Posts:
    617
    To transform normals from object to world space, use _World2Object but multiply it from the right hand side to the vector (this makes sure that you multiply the vector with the transposed matrix). (The "IT" in "UNITY_MATRIX_IT_MV" stands for Inverse Transpose" which is what you need for the correct transformation of normal vectors.)

    If you are sure that your model matrix is orthogonal (no scaling), you can also use _Object2World (from the left hand side).
     
  7. Daniel-Brauer

    Daniel-Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,317
    This is incorrect. The transpose of World2Object is the transpose of the inverse of the Object2World matrix.
    • MV transforms points from object to eye space
    • IT_MV rotates normals from object to eye space
    And similarly:
    • Object2World transforms points from object to world space
    • IT_Object2World (which, as you point out, is the transpose of World2Object) rotates normals from object to world space
    If it is orthogonal, the upper-left 3x3 of Object2World will be equal to that of IT_Object2World, and so will also rotate normals from object to world space.
     
    Jeremy-Lv and chrismarch like this.
  8. Martin-Kraus

    Martin-Kraus

    Joined:
    Feb 18, 2011
    Posts:
    617
    What is incorrect?
     
  9. Daniel-Brauer

    Daniel-Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,317
    Oops. For some reason I read "world to object" instead of "object to world" in your post. You're right, and I pretty much just repeated what you said.
     
  10. sbin3776

    sbin3776

    Joined:
    Oct 31, 2011
    Posts:
    18

    thanks for your answer
    but
    How can I know the model matrix is orthogonal ?
    if it is not orthogonal ,Should I use _World2Object buy multiply it from the right hand side to the normal vector ?
    Which of the following is correct:
    1 mul( (float3x3) _Object2World ,v.normal ) ; //model matrix is orthogonal
    2 mul ( v.normal, (float3x3) _World2Object ) ;// model matrix is not orthogonal
    3 mul ( v.normal, (float3x3) transpose( _World2Object) ) ;// model matrix is not orthogonal
    4 mul ( (float3x3) transpose( _World2Object) , v.normal ) ;// model matrix is not orthogonal
    -------------------------------------------------------------
    I think 3 is incorrect and 2==4
     
    Last edited: Nov 22, 2011
  11. stford

    stford

    Joined:
    Sep 7, 2010
    Posts:
    5
    Related question
    how do I grab the matrix in GLSL from the setMatrix() over in javaScript

    steve
     
  12. Martin-Kraus

    Martin-Kraus

    Joined:
    Feb 18, 2011
    Posts:
    617
    You think correctly.

    A 3x3 matrix is orthogonal if all row vectors (or all column vectors) are of unit length and the dot product of any two row vectors (or column vectors) is 0.
     
  13. Martin-Kraus

    Martin-Kraus

    Joined:
    Feb 18, 2011
    Posts:
    617
    You define a uniform matrix outside of main():

    uniform mat4 mymatrix;

    You can set the variable mymatrix with setMatrix() (even though you cannot define a property).
     
  14. Trung-Hieu

    Trung-Hieu

    Joined:
    Feb 18, 2013
    Posts:
    31
    Isn't that the definition of orthonormal matrices ?
    In orthogonal matrices, only all the row vector (or all the column vectors) are perpendicular to each other.
     
  15. 00christian00

    00christian00

    Joined:
    Jul 22, 2012
    Posts:
    644
    Is it possible to rotate the normals into eye space specifying the camera position manually, ignoring the current camera position?
     
  16. Billy4184

    Billy4184

    Joined:
    Jul 7, 2014
    Posts:
    3,195
    Hey guys, if you're making an endless runner moving along the z axis and you need to use a projection matrix that is relative to the camera but is not affected by rotation, then just subtract the camera world position z from the vPos.z, i.e.:

    Code (CSharp):
    1.  
    2. float4 vPos = mul (_Object2World, v.vertex);
    3. float zOff = (vPos.z - _WorldSpaceCameraPos.z)/_Dist;     // offset relative to camera along the z axis
    4. vPos += _QOffset*zOff*zOff; //
    5. v.vertex = mul (_World2Object, vPos);
    6.