Unity shader中的法线详解

来源:互联网 发布:天蝎网络第三季百度云 编辑:程序博客网 时间:2024/04/24 19:48

         一次写shader的时候,根据法线调整视觉效果,却发现坐标不同的情况下,会有颜色突变的情况。不解。故寻找计算法线部分的知识。

首先看一下大神文章了解下大概:http://blog.csdn.net/candycat1992/article/details/41605257


  1.

  1. _Object2World
is the transformation from object coordinates to world coordinates.
  1. _World2Object * unity_Scale.w
is the transformation from world coordinates to object coordinates.

Unity sometimes (for non-uniform scale factors) scales the vertex coordinates before handing them to the shader. (Supposedly such that _Object2World is an orthogonal matrix.) For uniform scale factors, however, it doesn't do this vertex scaling but integrates the scaling into _Object2World (making it a scaled orthogonal matrix). However, for some strange reason (and this is probably an inconsistency that just never got fixed and now too much code relies on it) this scaling was never included in _World2Object. Thus, you have to scale _World2Object with unity_Scale.w (if scale is important) but _Object2World is already scaled with the reciprocal factor.


No the space is the same, but in a general case (not unity) a non orthogonal matrix doesn't transform normals correctly.

If you want to perform a correct normal transformation in the general case you need to use theinverse transpose matrix. (In unity shaders this is equivalent tomul(normal,_World2Object).

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

This is a bit tricky to explain (I hope to remember it correctly).You can assumescale is always uniform becauseUnity(at least until 4.x version. I think it will change in 5.x) doesn't apply non-uniform scale in the vertex shader but pre-transform the mesh CPU side.

Following uniforms are provided to shaders:

  • _Object2World: contains the world matrix including the scale
  • unity_Scale: the w component contains the inverse of the uniform scale factor (w = 1/scale)
  • _World2Object: contains the inverse world matrix without scale

In order to correctly transform the normal from object to world space, you have 3 possibility:

  • transform the scaled normal : float3 worldN = mul((float3x3)_Object2World, SCALED_NORMAL);
  • you can avoid to use the scaled normal if you normalize the normal after the transform (probably this is your case otherwise AFAIK the transformation shouldn't be 100% correct)
  • use the inverse transpose : mul(normal,_World2Object)

SCALED_NORMAL is defined this way:

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

这个算是一个小知识点,虽然和法线本身无关,但却对写shader有所帮助。

2.o.normal本身是模型坐标系的,通过转化成世界坐标系,可以进行正确的插值。


0 0
原创粉丝点击