您的位置:首页 > 其它

一个有趣的模拟光照的shader(类似法线贴图)

2013-10-30 04:25 423 查看
  最近使用unity,碰到到一个很有趣的例子.场景无光线,却模拟出了光照,效果挺好.其思路与法线贴图原理异曲同工.



  原作者提供的效果印象深刻.

  模型除了使用原来的diffuse贴图外,还用到了一张模拟记录了"光照"信息的贴图(见机器人头上的贴图).这一点与法线贴图是一致的.

  这个方法比较简单,也比较死.思路很巧.

  分析一下贴图,有效范围基本是一个圆形.以前在学习法线贴图时,就遇到过法线投射在贴图的情景(/article/6024661.html).当各个方向的法线投影到一个正平面时,它形成一个圆.

  法线贴图本质就是为了预先保存法线信息.那几乎就可以引申出来了,我们也可以保存一个冒充的法线(光线)的信息,根据这个信息我们可以还原一个"伪"的光照过程.这个贴图就反过来利用了这一点.将模型的法线转换到model-view空间,再假设法线被投影到一个正平面(贴图上).于是法线的投影点可换算为贴图的uv坐标.此时在该点我们保存一个颜色值,可以与模型的diffuse贴图颜色进行计算,模拟出光照的效果.  

struct v2f
{
float4 pos    : SV_POSITION;
float2 uv     : TEXCOORD0;
float2 cap    : TEXCOORD1;
};
uniform float4 _MainTex_ST;

v2f vert (appdata_base v)
{
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);

half2 capCoord;
capCoord.x = dot(UNITY_MATRIX_IT_MV[0].xyz,v.normal);
capCoord.y = dot(UNITY_MATRIX_IT_MV[1].xyz,v.normal);
o.cap = capCoord * 0.5 + 0.5;

return o;
}

uniform sampler2D _MainTex;
uniform sampler2D _MatCap;

fixed4 frag (v2f i) : COLOR
{
fixed4 tex = tex2D(_MainTex, i.uv);
fixed4 mc = tex2D(_MatCap, i.cap);

return (tex + (mc*2.0)-1.0);
}


  capCoord.x = dot(UNITY_MATRIX_IT_MV[0].xyz,v.normal);

  capCoord.y = dot(UNITY_MATRIX_IT_MV[1].xyz,v.normal);

  上边2行是这里比较关键的一步,把法线转换到view空间.参看(/article/6024660.html)说明了原理.总之法线不能直接使用model-view矩阵转换到view空间.

  o.cap = capCoord * 0.5 + 0.5;

  上边是把法线值转换到纹理区间[0,1],之后在fragment shader通过这个值去贴图里查找对应的颜色值.

  这种手法似乎叫MatCap shader.这里是些卡通效果,其他地方有更真实的.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐