标签:dir ali unity cross mat return unit tag dba
目标:赋予材质法线贴图,并能响应光照的变化,体现出凹凸感。Shader "Custom/TestBumpShader" {
Properties {
_NormalMap("Bump", 2D)=""{} //1.
}
SubShader {
pass{
Tags{"LightMode"="ForwardBase"} //2.
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "unitycg.cginc"
#include "lighting.cginc"
sampler2D _NormalMap;
struct v2f{ //3.
float4 pos:POSITION;
float2 uv:TEXCOORD0;
float3 lightdir:TEXCOORD1;
float3 wpos:TEXCOORD2;
};
v2f vert(appdata_tan v)
{
v2f o;
o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
o.wpos=mul(unity_ObjectToWorld, v.vertex).xyz;
o.uv=v.texcoord.xy;
//4.
TANGENT_SPACE_ROTATION;
float3 objLight=ObjSpaceLightDir(v.vertex);
o.lightdir=mul(rotation,objLight);
return o;
}
fixed4 frag(v2f IN):COLOR
{
float3 N =normalize(UnpackNormal(tex2D(_NormalMap,IN.uv))); //5.
float3 L = normalize(IN.lightdir);
float ndotl=saturate(dot(N,L));
fixed4 col = _LightColor0*ndotl;
col+=UNITY_LIGHTMODEL_AMBIENT;
return col;
}
ENDCG
}
}
}
按照代码里的注释位置
_NormalMap("Bump", 2D)=""{} //1.
定义一个贴图,当然,下面的CG程序中要声明一下
法线贴图就必然涉及到光照,还是用forwardbase吧
struct v2f{ //3.
float4 pos:POSITION;
float2 uv:TEXCOORD0;
float3 lightdir:TEXCOORD1;
float3 wpos:TEXCOORD2;
};
结构体中定义一个uv对应纹理,一个lightdir是光照方向,一个wpos是世界坐标
世界坐标的计算和uv值的获取就不说了,以前有,代码里也有
为了使法线贴图产生作用,要在切线空间中进行计算,这里要把光照向量L转到切线空间
TANGENT_SPACE_ROTATION;
float3 objLight=ObjSpaceLightDir(v.vertex);
o.lightdir=mul(rotation,objLight);
这里的TANGENT_SPACE_ROTATION定义在unitycg.cginc中
// Declares 3x3 matrix ‘rotation‘, filled with tangent space basis
#define TANGENT_SPACE_ROTATION float3 binormal = cross( normalize(v.normal), normalize(v.tangent.xyz) ) * v.tangent.w; float3x3 rotation = float3x3( v.tangent.xyz, binormal, v.normal )
所以前面忘说的一点就是vert函数的参数不用appdata_base了,而改用appdata_tan,因为TANGENT_SPACE_ROTATION中用到了v.tangent,这个在appdata_base中是没有的。
然后用这里的这个rotation去变换模型坐标空间中的光照方向,将其变换到切线空间中,得到我们要用的光照向量
float3 N =normalize(UnpackNormal(tex2D(_NormalMap,IN.uv))); //5.
这里对法线贴图采样要用unpacknormal函数,也是定义在unitycg.cginc中
看到网上有人的解释:
//将材质贴图对应的法线 绘制在一张贴图上
//将贴图对应点的单位法线向量信息float3(x,y,z) 储存在图对应的颜色里color(r,g,b)里
//其中x,y,z分别对应r,g,b
//单位法线向量 float3(x,y,z),x,y,z的取值范围是 [-1,1]
//在法线贴图中被压缩在颜色的范围[0,1]中,所以需要转换
原因我也不太明,还在学习中,反正先当固定用法记吧
再用这个处理后的法线向量和光向量进行漫反射计算就得出最终颜色。
我们看下效果:
可以看到明暗变化显出凹凸,而不是平面了,其实模型还是平面,这就是视觉欺骗吧。
ShaderLab学习小结(十五)法线贴图的简单Shader
标签:dir ali unity cross mat return unit tag dba
原文地址:http://blog.51cto.com/shuxiayeshou/2069514