参考连接:http://liweizhaolili.blog.163.com/blog/static/162307442012726111843408/app
效果图:3d
1.首先,导入unity自带的模型,以下图,它使用的是StandardSpecular这个shader,具体的实现能够从unity官网中下载看看。它的实现比较复杂,这里咱们把它替换为咱们本身写的shader,方便咱们去控制。对于法线贴图,注意要设置Texture Type为Normal map。code
下面这个shader是漫反射+高光+法线贴图:orm
Shader "Custom/Light" { Properties { _MainColor ("主颜色", Color) = (0.5, 0.5, 0.5, 1) _NormalTex ("法线贴图", 2D) = "white" {} _Specular ("高光颜色", Color) = (1, 1, 1, 1) _Gloss ("高光系数", Range(8, 256)) = 20 } SubShader { Tags { "LightMode" = "ForwardBase" } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" #include "Lighting.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; float3 normal : NORMAL; float4 tangent : TANGENT; }; struct v2f { float4 vertex : SV_POSITION; float2 uv : TEXCOORD0; float3 lightDir : TEXCOORD1; float3 viewDir : TEXCOORD2; }; fixed4 _MainColor; sampler2D _NormalTex; fixed4 _Specular; float _Gloss; v2f vert (appdata v) { v2f o; o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); o.uv = v.uv; TANGENT_SPACE_ROTATION; //rotation是使模型空间转为切线空间的矩阵 o.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex)).xyz; o.viewDir = mul(rotation, ObjSpaceViewDir(v.vertex)).xyz; return o; } fixed4 frag (v2f i) : SV_Target { fixed3 tangentLightDir = normalize(i.lightDir); fixed3 tangentViewDir = normalize(i.viewDir); fixed4 packedNormal = tex2D(_NormalTex, i.uv); fixed3 tangentNormal = UnpackNormal(packedNormal); //漫反射 fixed3 diffuse = _LightColor0.rgb * _MainColor.rgb * saturate(dot(tangentNormal, tangentViewDir)); //Blinn-Phong高光光照模型,相对于普通的Phong高光模型,会更加光 fixed3 halfDir = normalize(tangentLightDir + tangentViewDir); fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(tangentNormal, halfDir)), _Gloss); return fixed4(diffuse + specular, 1); } ENDCG } } }
2.从效果图中,咱们能够发现有边缘光的效果,所以先加上。blog
Shader "Custom/Light" { Properties { _MainColor ("主颜色", Color) = (0.5, 0.5, 0.5, 1) _NormalTex ("法线贴图", 2D) = "white" {} _Specular ("高光颜色", Color) = (1, 1, 1, 1) _Gloss ("高光系数", Range(8, 256)) = 20 _RimColor ("边缘颜色", Color) = (1, 0, 0, 1) _RimPower ("边缘颜色强度", Range(0.1, 1)) = 1 } SubShader { Tags { "LightMode" = "ForwardBase" } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" #include "Lighting.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; float3 normal : NORMAL; float4 tangent : TANGENT; }; struct v2f { float4 vertex : SV_POSITION; float2 uv : TEXCOORD0; float3 lightDir : TEXCOORD1; float3 viewDir : TEXCOORD2; }; fixed4 _MainColor; sampler2D _NormalTex; fixed4 _Specular; float _Gloss; fixed4 _RimColor; half _RimPower; v2f vert (appdata v) { v2f o; o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); o.uv = v.uv; TANGENT_SPACE_ROTATION; //rotation是使模型空间转为切线空间的矩阵 o.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex)).xyz; o.viewDir = mul(rotation, ObjSpaceViewDir(v.vertex)).xyz; return o; } fixed4 frag (v2f i) : SV_Target { fixed3 tangentLightDir = normalize(i.lightDir); fixed3 tangentViewDir = normalize(i.viewDir); fixed4 packedNormal = tex2D(_NormalTex, i.uv); fixed3 tangentNormal = UnpackNormal(packedNormal); //漫反射 fixed3 diffuse = _LightColor0.rgb * _MainColor.rgb * saturate(dot(tangentNormal, tangentViewDir)); //Blinn-Phong高光光照模型,相对于普通的Phong高光模型,会更加光 fixed3 halfDir = normalize(tangentLightDir + tangentViewDir); fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(tangentNormal, halfDir)), _Gloss); //边缘颜色,对于法线和观察方向,只要在同一坐标系下便可 fixed dotProduct = 1 - saturate(dot(tangentNormal, tangentViewDir)); fixed3 rim = _RimColor.rgb * pow(dotProduct, 1 / _RimPower); return fixed4(diffuse + specular + rim, 1); } ENDCG } } }
3.接着就须要用到遮罩效果,这里我用到了下面这张遮罩图。分析一下咱们的效果图,它的边缘光是流动的,对于某一个位置的边缘光,随着时间的变化,它是在有光与无光这两个状态不断变化的,而看一下咱们的遮罩图,以y轴方向来讲,它也是黑白两种状态的切换,经过对遮罩图的取样,就能对边缘光进行控制了。再说一点,若是咱们把遮罩图改成全白的,那么就是咱们上方那种效果了,不会发生流动。get
Shader "Custom/Light" { Properties { _MainColor ("主颜色", Color) = (0.5, 0.5, 0.5, 1) _NormalTex ("法线贴图", 2D) = "white" {} _Specular ("高光颜色", Color) = (1, 1, 1, 1) _Gloss ("高光系数", Range(8, 256)) = 20 _RimColor ("边缘颜色", Color) = (1, 0, 0, 1) _RimPower ("边缘颜色强度", Range(0.1, 1)) = 1 _MaskTex ("光遮罩图", 2D) = "white" {} _MoveDir ("边缘光移动方向", Range(-1, 1)) = 1 } SubShader { Tags { "LightMode" = "ForwardBase" } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" #include "Lighting.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; float3 normal : NORMAL; float4 tangent : TANGENT; }; struct v2f { float4 vertex : SV_POSITION; float2 uv : TEXCOORD0; float3 lightDir : TEXCOORD1; float3 viewDir : TEXCOORD2; }; fixed4 _MainColor; sampler2D _NormalTex; fixed4 _Specular; float _Gloss; fixed4 _RimColor; half _RimPower; sampler2D _MaskTex; fixed _MoveDir; v2f vert (appdata v) { v2f o; o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); o.uv = v.uv; TANGENT_SPACE_ROTATION; //rotation是使模型空间转为切线空间的矩阵 o.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex)).xyz; o.viewDir = mul(rotation, ObjSpaceViewDir(v.vertex)).xyz; return o; } fixed4 frag (v2f i) : SV_Target { fixed3 tangentLightDir = normalize(i.lightDir); fixed3 tangentViewDir = normalize(i.viewDir); fixed4 packedNormal = tex2D(_NormalTex, i.uv); fixed3 tangentNormal = UnpackNormal(packedNormal); //漫反射 fixed3 diffuse = _LightColor0.rgb * _MainColor.rgb * saturate(dot(tangentNormal, tangentViewDir)); //Blinn-Phong高光光照模型,相对于普通的Phong高光模型,会更加光 fixed3 halfDir = normalize(tangentLightDir + tangentViewDir); fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(tangentNormal, halfDir)), _Gloss); //边缘颜色,对于法线和观察方向,只要在同一坐标系下便可 fixed dotProduct = 1 - saturate(dot(tangentNormal, tangentViewDir)); fixed3 rim = _RimColor.rgb * pow(dotProduct, 1 / _RimPower); fixed4 maskCol = tex2D(_MaskTex, i.uv + float2(0, _Time.y * _MoveDir)); return fixed4(diffuse + specular + rim * maskCol.rgb, 1); } ENDCG } } }
http://pan.baidu.com/s/1mh9T1l2
it