Are not normals (read from NORMAL semantic) in object space?

when converting normals from object space to world space, the predefined matrix _Object2World works like a charm: (mul (_Object2World, normal)). both rotation and scaling (uniformly) gave the expected matrix through color check elements in rows and columns, but why does some code use normals so that the left multiplies the inverse of the _World2Object matrix to transform the object space, is that the unity version thing (I'm using 4.5 .2) or normals live in some other space other than object space and why the two matrices don't respond to uneven scaling.

+3


source to share


1 answer


are not normals (read from NORMAL semantics) in object space

Yes, they are.

normals live in some other space other than object space and why the two matrices don't respond to uneven scaling.

There is no identical space, but in the general case (not unity) the orthogonal matrix non does not correctly transform the normals.

If you want to do the correct normal transformation in general, you need to use the inverse transpose matrix . (In shader units, this is equivalent mul(normal,_World2Object)

.

_Object2World works like a charm: (mul (_Object2World, normal)). both rotation and scaling (uniformly) gave the expected matrix through color check elements in rows and columns

It's a bit difficult to explain (I hope to remember this correctly). You can assume that the scale is always uniform because Unity

(at least up to 4.x. I think it will change in 5.x) does not apply uneven scale in the vertex shader, but transform the processor part of the mesh first.



The shaders provide the following forms:

  • _Object2World

    : contains world matrix including scale
  • unity_Scale

    : component w contains the inverse of the uniform scale factor ( w = 1/scale

    )
  • _World2Object

    : contains the matrix of the inverse world without scaling

To convert the normal from object to world correctly, you have 3 options:

  • convert scaled normal :float3 worldN = mul((float3x3)_Object2World, SCALED_NORMAL);

  • you can avoid using scaled normal mode if you normalize normal after conversion (maybe this is your case, otherwise AFAIK the conversion shouldn't be 100% correct)
  • use reverse transpose :mul(normal,_World2Object)

SCALED_NORMAL

is defined as follows:

#define SCALED_NORMAL (v.normal * unity_Scale.w)

      

+2


source







All Articles