加上Ambient後,沒有光源的地方就不會是全黑了。最後,只剩下Specular了!
之後可針對物體粗糙程度,設置粗糙變數n,若物體越粗糙,反射程度會指數遞減(高光會不明顯)。
Shader "Unlit/Phong"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Color("Color", Color) = (0.25, 0.5, 0.5, 1)
_Diffuse("Diffuse", float) = 1
_Gloss("Gloss", float) = 1
_Specular("Specular", float) = 1
}
SubShader
{
Tags { "RenderType"="Opaque" }
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal : NORMAL;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
float4 worldPos : TEXCOORD1;
float3 normal : NORMAL;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float4 _Color;
float _Gloss;
float _Diffuse;
float _Specular;
v2f vert (appdata v)
{
v2f o;
// 將物件座標轉為螢幕座標
o.vertex = UnityObjectToClipPos(v.vertex);
// 取得texture的UV,之後要貼貼圖在像素上
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
// 計算Diffuse需要頂點世界座標,所以拿世界座標轉換矩陣跟頂點座標相乘
o.worldPos = mul(unity_ObjectToWorld, v.vertex);
// 獲得頂點法向量
o.normal = v.normal;
return o;
}
fixed4 frag(v2f i) : SV_Target
{
/* Ambient */
fixed4 ambient = UNITY_LIGHTMODEL_AMBIENT;
/* Diffuse */
// 獲得點的法向量 (normalize)
fixed3 worldNormalDir = normalize(i.normal);
// 獲得點對光源的向量 (normalize)
fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
// 取光向量與表面法向量夾角,並算出強度
fixed4 diffuse = saturate(dot(worldNormalDir, worldLightDir)) * _Diffuse;
/* Specular */
// 計算光對表面的反射向量
// (worldLightDir是負的,因為是從光為起點到表面的向量)
fixed3 reflectDir = normalize(reflect(-worldLightDir, worldNormalDir));
// 算出視角與表面的向量
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos);
// dot算出specular
fixed4 specular = pow(saturate(dot(reflectDir, viewDir)), _Gloss) * _Specular;
// 取得貼圖在該UV下的顏色
fixed4 textureColor = tex2D(_MainTex, i.uv) * _Color;
return textureColor * (diffuse);
//return textureColor * (diffuse + ambient);
//return textureColor * (diffuse + ambient + specular);
}
ENDCG
}
}
}
(圖片參考:https://blog.csdn.net/arag2009/article/details/78083065)