各向异性有两种类型,先截个图看看效果
一种是 径向各向异性:
一种是 线性各向异性:
这个shader就类似金属拉丝或者头发上的高光。(线性各向异性)
它能基于法线贴图的蓝色通道混合各向异性与粗糙程度。
支持漫反射(diffuse)、法线(normal)、反射(specular)、光泽贴图(gloss)和透明(transparency)着色器
光泽与反射值也应用于各向异性高光。
高光能增大或减小表面的各向异性高光的偏移值(Offset)。
各向异性高光表面的方向是被一个像下面的方向贴图定义的。
和切线空间的法线贴图效果相同,在表面定义高光。然而他们不应该在unity中转换法线贴图。
也就是这些图不用再转化成法线贴图了(我是这么理解的)。
成员:
各向异性的方向:就是表面高光的方向,和法线贴图的切线空间方向相同。
反射:反射强度是贴图的红色通道定义的。控制了反射高光的亮度。
光泽:光泽强度是贴图的绿色通道定义的。绿色越多反射高光越细越锐利,绿色越少反射高光越宽越模糊。最好把这个值设为一个非零值。
各向异性遮罩:贴图的蓝色通道定义各向异性与blinn高光的混合,蓝色越多各向异性比重越大,蓝色越少blinn比重越大。
各向异性的偏移:能使各向异性离中心点远或近
以下是本次shader需要的贴图:
径向各向异性效果:
线性各向异性效果:
建立一个shader:
先浏览一下变量:
_SpecularColor 高光颜色
_SpecPower 高光强度
_Specular 高光各向异性的数目
_AnisoDir 各向异性方向贴图
_AnisoOffset 各向异性的偏移
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_MainTint ("Diffuse Tint", Color) = (1,1,1,1)
_SpecularColor ("Specular Color", Color) = (1,1,1,1)//高光颜色
_SpecPower ("Specular Power", Range(0,30)) = 2//高光强度
_Specular ("Specular Amount", Range(0, 1)) = 0.5
_AnisoDir ("Anisotropic Direction", 2D) = ""{}//各向异性方向法线贴图
_AnisoOffset("Anisotropic Offset", Range(-1,1)) = -0.2//_AnisoOffset的作用偏移
}
让着色器加载我们定义的新的函数不是以前的Lambert
#pragma surface surf Anisotropic
告诉使用shader model3.0的渲染模式
#pragma target 3.0
建立一个新的结构体SurfaceAnisoOutput 传值用
Albedo 对光源的反射率
Normal 法线方向
Emission 自发光
AnisoDirection 各向异性方向
Specular 高光反射中的指数部分的系数
Gloss 高光反射中的强度系数
Alpha 透明度
struct SurfaceAnisoOutput
{
fixed3 Albedo;//对光源的反射率
fixed3 Normal;//法线方向
fixed3 Emission;//自发光
fixed3 AnisoDirection;//各向异性方向
half Specular;//高光反射中的指数部分的系数
fixed Gloss;//高光反射中的强度系数
fixed Alpha;//透明度
};
重要的执行函数 LightingAnisotropic
先求出半角向量halfVector
再求法线方向与光照方向的点积NdotL
半角向量与各向异性方向点积HdotA
求出各向异性:
sin((半角向量与各向异性方向点积+偏移值)的弧度值 * 180)
再根据各向异性求出反光强度spec
最后与光照颜色等进行整合
inline fixed4 LightingAnisotropic (SurfaceAnisoOutput s, fixed3 lightDir, half3 viewDir, fixed atten)
{
fixed3 halfVector = normalize(normalize(lightDir) + normalize(viewDir));//normalize()函数把向量转化成单位向量
float NdotL = saturate(dot(s.Normal, lightDir));
fixed HdotA = dot(normalize(s.Normal + s.AnisoDirection), halfVector);
float aniso = max(0, sin(radians((HdotA + _AnisoOffset) * 180f)));//radians()函数将角度值转换为弧度值
float spec = saturate(pow(aniso, s.Gloss * 128) * s.Specular);//saturate(x)函数 如果x小于0返回 0;如果x大于1返回1;否则返回x;把x限制在0-1
fixed4 c;
c.rgb = ((s.Albedo * _LightColor0.rgb * NdotL) + (_LightColor0.rgb * _SpecularColor.rgb * spec)) * (atten * 2);
c.a = 1.0;
return c;
}
在surf函数中接受各向异性法线贴图
转化为输出的各向异性方向
然后就ok了
<span style="font-size:14px;"> void surf (Input IN, inout SurfaceAnisoOutput o) {
half4 c = tex2D (_MainTex, IN.uv_MainTex) * _MainTint;
float3 anisoTex = UnpackNormal(tex2D(_AnisoDir, IN.uv_AnisoDir));
o.AnisoDirection = anisoTex;
o.Specular = _Specular;
o.Gloss = _SpecPower;
o.Albedo = c.rgb;
o.Alpha = c.a;
}</span>
这是径向的效果:
这是线性的效果:
全部代码如下:
Shader "Custom/textShader" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_MainTint ("Diffuse Tint", Color) = (1,1,1,1)
_SpecularColor ("Specular Color", Color) = (1,1,1,1)//高光颜色
_SpecPower ("Specular Power", Range(0,30)) = 2//高光强度
_Specular ("Specular Amount", Range(0, 1)) = 0.5
_AnisoDir ("Anisotropic Direction", 2D) = ""{}//各向异性方向法线贴图
_AnisoOffset("Anisotropic Offset", Range(-1,1)) = -0.2//_AnisoOffset的作用偏移
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf Anisotropic
#pragma target 3.0
sampler2D _MainTex;
sampler2D _AnisoDir;//各向异性的
float4 _MainTint;
float4 _SpecularColor;
float _AnisoOffset;
float _Specular;
float _SpecPower;
struct SurfaceAnisoOutput
{
fixed3 Albedo;//对光源的反射率
fixed3 Normal;//法线方向
fixed3 Emission;//自发光
fixed3 AnisoDirection;//各向异性方向
half Specular;//高光反射中的指数部分的系数
fixed Gloss;//高光反射中的强度系数
fixed Alpha;//透明度
};
inline fixed4 LightingAnisotropic (SurfaceAnisoOutput s, fixed3 lightDir, half3 viewDir, fixed atten)
{
fixed3 halfVector = normalize(normalize(lightDir) + normalize(viewDir));//normalize()函数把向量转化成单位向量
float NdotL = saturate(dot(s.Normal, lightDir));
fixed HdotA = dot(normalize(s.Normal + s.AnisoDirection), halfVector);
float aniso = max(0, sin(radians((HdotA + _AnisoOffset) * 180f)));//radians()函数将角度值转换为弧度值
float spec = saturate(pow(aniso, s.Gloss * 128) * s.Specular);//saturate(x)函数 如果x小于0返回 0;如果x大于1返回1;否则返回x;把x限制在0-1
fixed4 c;
c.rgb = ((s.Albedo * _LightColor0.rgb * NdotL) + (_LightColor0.rgb * _SpecularColor.rgb * spec)) * (atten * 2);
c.a = 1.0;
return c;
}
struct Input {
float2 uv_MainTex;
float2 uv_AnisoDir;
};
void surf (Input IN, inout SurfaceAnisoOutput o) {
half4 c = tex2D (_MainTex, IN.uv_MainTex) * _MainTint;
float3 anisoTex = UnpackNormal(tex2D(_AnisoDir, IN.uv_AnisoDir));
o.AnisoDirection = anisoTex;
o.Specular = _Specular;
o.Gloss = _SpecPower;
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
--------- by wolf96