UnityShader学习笔记(一)
标准光照模型
原理:进入的摄像机内部的光线分为四个部分
- 自发光(Emissive)
- 漫反射(Diffuse)LightTexDiffcolor
- 高光反射(Specular)Light*Pow(Dot(view,Reflect),Gloss)*SpecularColor
- 环境光(Ambient)AmbientTexDiffcolor
所以在使用标准光照模型制作shader时也是通过分别计算四种光线的效果然后叠加输出。
每种光线效果的计算方法已经给出,其中Light是指全局光直接光,Tex为漫反射贴图,Diffcolor指漫反射颜色,Pow(A,B)=A的B次方,view为视角方向=(摄像机位置-顶点位置),Reflect为反射方向,可由shader内置函数计算,Gloss为光泽度,Specular为高光颜色,Ambient可由内置语义直接获取。
例子:
Shader"review/Texture_Specular"
{
///标准光照模型 光照数据=自发光(E)+漫反射光(D)+环境光(A)+高光(S)
Properties
{
_DiffuseColor("漫反射颜色",color)=(1,1,1,1)
_SpecularColor("高光颜色",color)=(1,1,1,1)
_Gloss("光泽度",Range(8,256))=20
_MainTexture("主贴图",2D)="white"{}
}
SubShader
{
Pass
{
Tags{"LightMode"="ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
fixed4 _DiffuseColor;
fixed4 _SpecularColor;
float _Gloss;
sampler2D _MainTexture;
fixed4 _MainTexture_ST;//xyzw Tilling offset
struct a2v
{
fixed3 verts:POSITION;
fixed3 normal:NORMAL;
fixed4 uv:TEXCOORD0;
};
struct v2f
{
fixed4 verts:SV_POSITION;
fixed3 worldNoraml:TEXCOORD;
fixed2 uv:TEXCOORD1;
fixed3 worldPos:TEXCOORD2;
};
v2f vert(a2v v)
{
v2f o;
o.verts=UnityObjectToClipPos(v.verts);
o.worldNoraml=UnityObjectToWorldNormal(v.normal);
o.worldPos=mul(unity_ObjectToWorld,v.verts).xyz;
o.uv=TRANSFORM_TEX(v.uv,_MainTexture);
return o;
}
fixed4 frag (v2f i):SV_Target
{
fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz;//环境光
fixed3 worldLightDir=normalize(_WorldSpaceLightPos0.xyz) ;//世界光
fixed3 viewDir=normalize(UnityWorldSpaceViewDir(i.worldPos));//视角方向
fixed3 reflDir=normalize(reflect(worldLightDir,i.worldNoraml));//反射方向
fixed3 value=_DiffuseColor.rgb*tex2D(_MainTexture,i.uv).rgb;
fixed3 albedo=ambient*value;//环境光*贴图*漫反射光 A
fixed3 diffuse=_LightColor0.rgb*value;//直线光*贴图*漫反射光 D
fixed3 specular=_LightColor0.rgb*pow(saturate(dot(viewDir,reflDir)),_Gloss);//高光颜色 S
return fixed4(albedo+specular+diffuse,1); //A+D+S
}
ENDCG
}
}
}
tips:BRDF(Bidirectional Reflectance Distribution Function) 双向反射分布函数