Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

Rotating Normal To World Space

Discussion in 'Shaders' started by ChaseRLewis73003, Dec 11, 2012.

  1. ChaseRLewis73003

    ChaseRLewis73003

    Joined:
    Apr 23, 2012
    Posts:
    85
    I need to take a models normal into world space to compare it to a position to determine how it should be rendered. I assume Unity has a built-in variable to do this or do I need to upload something myself to do this?

    Also is there any way in Unity to do larger than float2 texcoords? Only thing I can think of is pass them through the tangent vector or are the appdata type structs the only options? Creating a shader that does deformable splines completely on the gpu and it works fine but issue is I need 1 more float then is offered by the largest appdata structure if I want lighting and texturing unless I want to compute the normals on the gpu each frame which is pretty wasteful. Gpu's enlarge all structs into 16 byte alignments so there is excess padding / data spaces that exist I simply can't find a way to use : (
     
  2. ilya_ca

    ilya_ca

    Joined:
    Nov 19, 2011
    Posts:
    274
    Do you mean rotating normalmap's normals or object's normals?
    If you simply want to rotate the object's normals from object space to world space then it's as simple as this (in your vertex program):
    Code (csharp):
    1. o.normal = mul( _Object2World, float4(v.normal, 0.0) );
    Otherwise you can use the following awesome tutorial to rotate normalmap's normals from tangent space to world space: http://en.wikibooks.org/wiki/Cg_Programming/Unity/Lighting_of_Bumpy_Surfaces
     
    Rob-Porter likes this.
  3. ChaseRLewis73003

    ChaseRLewis73003

    Joined:
    Apr 23, 2012
    Posts:
    85
    second thanks a lot!
     
  4. Martin-Kraus

    Martin-Kraus

    Joined:
    Feb 18, 2011
    Posts:
    617
    Note that this works only for orthogonal transformations with uniform scaling. (Which should usually be the case in Unity as far as I know.)
     
  5. peacefulshade

    peacefulshade

    Joined:
    Jul 25, 2012
    Posts:
    9
    In case someone still has a problem using

    float3 worldNormal = mul( _Object2World, float4( v.normal, 0.0 ) ).xyz;

    it works if the transformation of the object is not scaled, if you apply scale in your transforms use this:

    float3 worldNormal = mul( float4( v.normal, 0.0 ), _World2Object ).xyz;

    This is because object to world matrices containing scaling mess up the normals:

    Notice that the normal in the triangle of the right is no longer perpendicular to it's surface.

    There's a really nice explanation of this in "Introduction to 3D Game Programming with DirectX 9.0c a shader approach" by Frank D. Luna, pages 246 - 247. If you read it, you'll notice that the correct matrix is the inverse transpose of the _Object2World matrix, that's why the multiplication here:

    float3 worldNormal = mul( float4( v.normal, 0.0 ), _World2Object ).xyz;

    Has the normal as the first parameter and the matrix as the second.
     
    Curious-George likes this.