一.Specular Shader
源碼如下:
//鏡面反射Shader(specular shader )
Shader "Shader/Specular"
{
//------------------------------------【屬性值】------------------------------------
Properties
{
//主顏色
_Color("Main Color", Color) = (1, 1, 1, 1)
//鏡面反射顏色
_SpecColor("Specular Color", Color) = (1, 1, 1, 1)
//鏡面反射光澤度
_SpecShininess("Specular Shininess", Range(1.0, 100.0)) = 10.0
}
//------------------------------------【唯一的子著色器】------------------------------------
SubShader
{
//渲染類型設置:不透明
Tags{ "RenderType" = "Opaque" }
//--------------------------------唯一的通道-------------------------------
Pass
{
//光照模型ForwardBase
Tags{ "LightMode" = "ForwardBase" }
//===========開啟CG著色器語言編寫模塊===========
CGPROGRAM
//編譯指令:告知編譯器頂點和片段著色函數的名稱
#pragma vertex vert
#pragma fragment frag
//頂點著色器輸入結構
struct appdata
{
float4 vertex : POSITION;//頂點位置
float3 normal : NORMAL;//法線向量坐標
};
//頂點著色器輸出結構
struct v2f
{
float4 pos : SV_POSITION;//像素位置
float3 normal : NORMAL;//法線向量坐標
float4 posWorld : TEXCOORD0;//在世界空間中的坐標位置
};
//變量的聲明
float4 _LightColor0;
float4 _Color;
float4 _SpecColor;
float _SpecShininess;
//--------------------------------【頂點著色函數】-----------------------------
// 輸入:頂點輸入結構體
// 輸出:頂點輸出結構體
//---------------------------------------------------------------------------------
//頂點著色函數
v2f vert(appdata IN)
{
//【1】聲明一個輸出結構對象
v2f OUT;
//【2】填充此輸出結構
//輸出的頂點位置為模型視圖投影矩陣乘以頂點位置,也就是將三維空間中的坐標投影到了二維窗口
OUT.pos = mul(UNITY_MATRIX_MVP, IN.vertex);
//獲得頂點在世界空間中的位置坐標
OUT.posWorld = mul(_Object2World, IN.vertex);
//獲取頂點在世界空間中的法線向量坐標
OUT.normal = mul(float4(IN.normal, 0.0), _World2Object).xyz;
//【3】返回此輸出結構對象
return OUT;
}
//--------------------------------【片段著色函數】-----------------------------
// 輸入:頂點輸出結構體
// 輸出:float4型的像素顏色值
//---------------------------------------------------------------------------------
fixed4 frag(v2f IN) : COLOR
{
//【1】先準備好需要的參數
//獲取法線的方向
float3 normalDirection = normalize(IN.normal);
//獲取入射光線的方向
float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz);
//獲取視角方向
float3 viewDirection = normalize(_WorldSpaceCameraPos - IN.posWorld.xyz);
//【2】計算出漫反射顏色值 Diffuse=LightColor * MainColor * max(0,dot(N,L))
float3 diffuse = _LightColor0.rgb * _Color.rgb * max(0.0, dot(normalDirection, lightDirection));
//【3】計算鏡面反射顏色值
float3 specular;
//若是法線方向和入射光方向大于180度,鏡面反射值為0
if (dot(normalDirection, lightDirection) < 0.0)
{
specular = float3(0.0, 0.0, 0.0);
}
//否則,根據公式進行計算 Specular =LightColor * SpecColor *pow(max(0,dot(R,V)),Shiness),R=reflect(-L,N)
else
{
float3 reflectDirection = reflect(-lightDirection, normalDirection);
specular = _LightColor0.rgb * _SpecColor.rgb * pow(max(0.0, dot(reflectDirection, viewDirection)), _SpecShininess);
}
//【4】合并漫反射、鏡面反射、環境光的顏色值
float4 diffuseSpecularAmbient = float4(diffuse, 1.0) + float4(specular, 1.0) + UNITY_LIGHTMODEL_AMBIENT;
//【5】將漫反射-鏡面反射-環境光的顏色值返回
return diffuseSpecularAmbient;
}
//===========結束CG著色器語言編寫模塊===========
ENDCG
}
}
}
二、帶紋理載入的Specular Shader
源碼如下:
//支持紋理載入的specular shader
Shader "Shader/Specular with Shader"
{
//------------------------------------【屬性值】------------------------------------
Properties
{
//主紋理
_MainTex("Texture", 2D) = "white" {}
//主顏色
_Color("Main Color", Color) = (1, 1, 1, 1)
//鏡面反射顏色
_SpecColor("Specular Color", Color) = (1, 1, 1, 1)
//鏡面反射光澤度
_SpecShininess("Specular Shininess", Range(1.0, 100.0)) = 10.0
}
//------------------------------------【唯一的子著色器】------------------------------------
SubShader
{
//渲染類型設置:不透明
Tags{ "RenderType" = "Opaque" }
//--------------------------------唯一的通道-------------------------------
Pass
{
//光照模型ForwardBase
Tags{ "LightMode" = "ForwardBase" }
//===========開啟CG著色器語言編寫模塊===========
CGPROGRAM
//編譯指令:告知編譯器頂點和片段著色函數的名稱
#pragma vertex vert
#pragma fragment frag
//頂點著色器輸入結構
struct appdata
{
float4 vertex : POSITION;//頂點位置
float3 normal : NORMAL;//法線向量坐標
float2 texcoord : TEXCOORD0;//一級紋理坐標
};
//頂點著色器輸出結構
struct v2f
{
float4 pos : SV_POSITION;//像素位置
float3 normal : NORMAL;//法線向量坐標
float2 texcoord : TEXCOORD0;//一級紋理坐標
float4 posWorld : TEXCOORD1;//在世界空間中的坐標位置
};
//變量的聲明
float4 _LightColor0;
float4 _Color;
sampler2D _MainTex;
float4 _SpecColor;
float _SpecShininess;
//--------------------------------【頂點著色函數】-----------------------------
// 輸入:頂點輸入結構體
// 輸出:頂點輸出結構體
//---------------------------------------------------------------------------------
//頂點著色函數
v2f vert(appdata IN)
{
//【1】聲明一個輸出結構對象
v2f OUT;
//【2】填充此輸出結構
//輸出的頂點位置為模型視圖投影矩陣乘以頂點位置,也就是將三維空間中的坐標投影到了二維窗口
OUT.pos = mul(UNITY_MATRIX_MVP, IN.vertex);
//獲得頂點在世界空間中的位置坐標
OUT.posWorld = mul(_Object2World, IN.vertex);
//獲取頂點在世界空間中的法線向量坐標
OUT.normal = mul(float4(IN.normal, 0.0), _World2Object).xyz;
//輸出的紋理坐標也就是輸入的紋理坐標
OUT.texcoord = IN.texcoord;
//【3】返回此輸出結構對象
return OUT;
}
//--------------------------------【片段著色函數】-----------------------------
// 輸入:頂點輸出結構體
// 輸出:float4型的像素顏色值
//---------------------------------------------------------------------------------
fixed4 frag(v2f IN) : COLOR
{
//【1】先準備好需要的參數
//獲取紋理顏色
float4 texColor = tex2D(_MainTex, IN.texcoord);
//獲取法線的方向
float3 normalDirection = normalize(IN.normal);
//獲取入射光線的方向
float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz);
//獲取視角方向
float3 viewDirection = normalize(_WorldSpaceCameraPos - IN.posWorld.xyz);
//【2】計算出漫反射顏色值 Diffuse=LightColor * MainColor * max(0,dot(N,L))
float3 diffuse = _LightColor0.rgb * _Color.rgb * max(0.0, dot(normalDirection, lightDirection));
//【3】計算鏡面反射顏色值
float3 specular;
//若是法線方向和入射光方向大于180度,鏡面反射值為0
if (dot(normalDirection, lightDirection) < 0.0)
{
specular = float3(0.0, 0.0, 0.0);
}
//否則,根據公式進行計算 Specular =LightColor * SpecColor *pow(max(0,dot(R,V)),Shiness),R=reflect(-L,N)
else
{
float3 reflectDirection = reflect(-lightDirection, normalDirection);
specular = _LightColor0.rgb * _SpecColor.rgb * pow(max(0.0, dot(reflectDirection, viewDirection)), _SpecShininess);
}
//【4】合并漫反射、鏡面反射、環境光的顏色值
float4 diffuseSpecularAmbient = float4(diffuse, 1.0) + float4(specular, 1.0) + UNITY_LIGHTMODEL_AMBIENT;
//【5】將漫反射-鏡面反射-環境光的顏色值乘以紋理顏色值之后返回
return diffuseSpecularAmbient * texColor;
}
//===========結束CG著色器語言編寫模塊===========
ENDCG
}
}
}