高光反射計算公式(phong模型)Cspecular=(Clight*Mspecular)max(0,v*r)mgloss函數
mgloss爲材質的官澤度,也成反射度,控制高光區域亮點有多大spa
Mspecular是材質的高光反射顏色,控制材質對於高光反射的輕度和顏色orm
Clight爲光源的顏色和強度blog
v是觀察方向的單位向量ip
r是反射方向 r=2(法線單位向量n*光源方向向量)法線單位向量-光源方向向量get
高光反射計算公式(Blinn模型)Cspecular=(Clight*Mspecular)max(0,n*h)mglossit
n爲法線向量的單位向量io
h是對觀察方向和光源方向取平均後歸一化獲得的:h(注:單位向量)=(v(注:單位向量)+光源方向)/|(v(注:單位向量)+光源方向)|class
下面分別是逐頂點和逐像素兩種寫法變量
phong模型 逐頂點:
Shader "study/Chapter6/halfLambertShader" { Properties{ _Diffuse ("Diffuse", Color) = (1, 1, 1, 1) _Specular("Specular",Color)=(1,1,1,1)//控制材質高光反射顏色 _Gloss("Gloss",Range(8.0,256)) = 20 //用於控制高光區域的大小 } SubShader{ Pass{ Tags{"LightMode"="ForwardBase"} CGPROGRAM #pragma vertex vert #pragma fragment frag #include "Lighting.cginc" fixed4 _Diffuse; fixed4 _Specular; float _Gloss; struct a2v{ float4 vertex:POSITION; fixed4 normal:NORMAL; }; struct v2f{ float4 pos:SV_POSITION; fixed3 color:COLOR; }; v2f vert(a2v v){ v2f o; o.pos=UnityObjectToClipPos(v.vertex); fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz; //內置函數寫法,下面給出內置函數 //fixed3 worldNormal=normalize(UnityObjectToWorldNormal(v.normal);); fixed3 worldNormal=normalize(mul(v.normal,(float3x3)unity_WorldToObject)); fixed3 worldLightDir=normalize(_WorldSpaceLightPos0.xyz); fixed3 diffuse=_LightColor0.rgb*_Diffuse.rgb*saturate(dot(worldNormal,worldLightDir)); //反射方向get the reflect direction in world space fixed3 reflectDir=normalize(reflect(-worldLightDir,worldNormal)); //get the view direction in world space //世界空間下觀察方向 fixed3 viewDir=normalize(_WorldSpaceCameraPos.xyz-mul(unity_ObjectToWorld,v.vertex).xyz); //Computer specular term fixed3 specular = _LightColor0.rgb*_Specular.rgb*pow(saturate(dot(reflectDir,viewDir)),_Gloss); o.color=diffuse+ambient+specular; return o; } fixed4 frag(v2f i):SV_Target{ return fixed4(i.color,1.0); } ENDCG } } FallBack "Specular" }
phong模型 逐像素:
Shader "study/Chapter6/SpecularPixelLevelShader" { Properties{ _Diffuse("Diffuse",Color)=(1,1,1,1) _Specular("Specular",Color)=(1,1,1,1) _Gloss("Gloss",Range(8.0,256))=20 } SubShader{ Pass{ Tags{"LightMode"="ForwardBase"} CGPROGRAM #pragma vertex vert #pragma fragment frag #include "Lighting.cginc" fixed4 _Diffuse; fixed4 _Specular; float _Gloss; struct a2v{ fixed4 vertex:POSITION; fixed3 normal:NORMAL; }; struct v2f{ fixed4 pos:SV_POSITION; float3 worldNormal:TEXCOORD0; float3 worldPos:TEXCOORD1; }; v2f vert(a2v v){ v2f o; o.pos = UnityObjectToClipPos(v.vertex); //使用內置函數寫法 //o.worldNormal = UnityObjectToWorldNormal(v.normal); o.worldNormal=mul(v.normal,(float3x3)unity_WorldToObject); o.worldPos=mul(unity_ObjectToWorld,v.vertex).xyz; return o; } fixed4 frag(v2f i): SV_Target{ //環境光、自發光部分 fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz; //世界空間下法線單位矢量 fixed3 worldNormal=normalize(i.worldNormal); //世界空間下光源方向單位矢量 fixed3 worldLightDir=normalize(_WorldSpaceCameraPos.xyz); //漫反射部分 fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal,worldLightDir)); //世界空間下反射光矢量 fixed3 reflectDir=normalize(reflect(-worldLightDir,worldNormal)); //視野方向 fixed3 viewDir=normalize(_WorldSpaceCameraPos.xyz-i.worldPos.xyz); //高光 fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(reflectDir,viewDir)),_Gloss); //最終觀察到的光照 return fixed4(ambient+diffuse+specular,1.0); } ENDCG } } FallBack "Specular" }
Blinn模型逐像素
Shader "study/Chapter6/BlinnPhongShader" { Properties{ _Diffuse("Diffuse",Color)=(1,1,1,1) _Specular("Specular",Color)=(1,1,1,1) _Gloss("Gloss",Range(8.0,256))=20 } SubShader{ Pass{ Tags{"LightMode"="ForwardBase"} CGPROGRAM #pragma vertex vert #pragma fragment frag #include "Lighting.cginc" fixed4 _Diffuse; fixed4 _Specular; float _Gloss; struct a2v{ float4 vertex:POSITION; float3 normal:NORMAL; }; struct v2f{ float4 pos:SV_POSITION; float3 worldNormal : TEXCOORD0; float3 worldPos : TEXCOORD1; }; v2f vert(a2v v){ v2f o; o.pos=UnityObjectToClipPos(v.vertex); o.worldNormal=mul(v.normal,(float3x3)unity_WorldToObject); o.worldPos=mul(unity_ObjectToWorld,v.vertex).xyz; return o; } fixed4 frag(v2f i):SV_Target{ float3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz; fixed3 worldNormal = normalize(i.worldNormal); //內置函數寫法 //float3 worldLightDir=normalize(UnityWorldSpaceLightDir(i.worldPos)); fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz); fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0,dot(worldNormal, worldLightDir)); //內置函數寫法 //fixed3 viewDir=normalize(UnityWorldSpaceViewDir(i.worldNormal)); fixed3 viewDir=normalize(_WorldSpaceCameraPos.xyz-i.worldPos.xyz); fixed3 halfDir=normalize(worldLightDir + viewDir); fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss); return fixed4(ambient+diffuse+specular,1.0); } ENDCG } } FallBack "Specular" }
unity的內置函數
僅用於前向渲染的只有在渲染模式爲前向渲染時(「LightMode」=「ForwordBase」或者"LightMode"="ForwordAdd")
這三個函數裏的內置變量——WorldSpaceLightPos0等才能被正確賦值。
注:這一篇以及以前漫反射都是單一平行光源下計算的,查看效果時,去掉天空盒,設置方法爲window->Lighting->skybox