您的位置:首页 > 移动开发 > Unity3D

Unity shader中的法线详解

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

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

1.

_Object2World

is the transformation from object coordinates to world coordinates.
_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 to
mul(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 because
Unity
(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:

[code]#define SCALED_NORMAL (v.normal * unity_Scale.w)


这个算是一个小知识点,虽然和法线本身无关,但却对写shader有所帮助。
2.o.normal本身是模型坐标系的,通过转化成世界坐标系,可以进行正确的插值。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: