Unity 鏡面反射
阿新 • • 發佈:2018-11-28
一、公式
specuColor = Kd*_LightColor0*pow(max(R·V 0), _Shininess);
Kd–環境光顏色、頂點顏色、點光源的距離衰減
_LightColor0–光源顏色
R·V–反射光向量 · 觀察向量
二、逐頂點著色(古羅著色)
Shader "Custom/MySpecular_Vertex"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Bright("Bright",Float) = 2
_Shininess("Shininess" ,Float) = 10
}
SubShader
{
Tags { "RenderType" = "Opaque" }
LOD 100
Pass
{
Tags{ "LightMode" = "ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
uniform float _Shininess;
uniform float _Bright;
uniform sampler2D _MainTex;
struct appdata
{
float4 vertex:POSITION;
float2 texcoord:TEXCOORD0;
half3 normal:NORMAL;
};
struct v2f
{
float4 pos:SV_POSITION;
float2 uv:TEXCOORD0;
fixed4 difColor : COLOR0;
fixed4 specuColor : COLOR1;
};
v2f vert(in appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.texcoord;
float3 vertexWorldPos = mul(unity_ObjectToWorld, v.vertex);
float3 N = normalize (mul((float3x3)unity_ObjectToWorld, v.normal));//法線
float3 L;//入射光方向
float atten;//點光源的距離衰減係數
if (_WorldSpaceLightPos0.w == 0)//_WorldSpaceLightPos0:平行光: (world space direction, 0);
{
L = normalize(_WorldSpaceLightPos0);
atten = 1;
}
else //_WorldSpaceLightPos0: 其他光: (world space position, 1).
{
float3 light2Vertex = _WorldSpaceLightPos0 - vertexWorldPos;
L = normalize(light2Vertex);
float Length = length(light2Vertex);
atten = 1 / Length;
}
float Kd = atten*_Bright/**UNITY_LIGHTMODEL_AMBIENT*/;
//計算入射光和法線的夾角的餘弦值,並剔除小於零的值(小於0的值相當於從物體的背面向物體表面照射,沒有物理意義)
float cos = max(dot(N, L), 0);
fixed4 difColor = Kd*_LightColor0 *cos;//漫反射光的顏色
//鏡面反射
float3 R = reflect(-L, N);
float3 V= normalize(_WorldSpaceCameraPos - vertexWorldPos);
fixed4 specuColor = Kd* _LightColor0*pow(max(dot(R, V), 0), _Shininess);
o.difColor = difColor;
o.specuColor = specuColor;
return o;
}
fixed4 frag(in v2f i) :SV_Target
{
fixed4 col;
//紋理取樣
col = tex2D(_MainTex, i.uv);
col *= i.difColor;
col += i.specuColor;
return col;
}
ENDCG
}
}
}
三、逐畫素著色(馮式著色)
Shader "Custom/MySpecular_Fragment"
{
Properties
{
_MainTex("Texture", 2D) = "white" {}
_Bright("Bright",Float) = 2
_Shininess("Shininess",Float) = 10
}
SubShader
{
Tags{ "RenderType" = "Opaque" }
LOD 100
Pass
{
Tags{ "LightMode" = "ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
uniform float _Shininess;
uniform float _Bright;
uniform sampler2D _MainTex;
struct appdata
{
float4 vertex:POSITION;
float2 texcoord:TEXCOORD0;
float3 normal:NORMAL;
};
struct v2f
{
float4 pos:SV_POSITION;
float2 uv:TEXCOORD0;
float3 normalDir:TEXCOORD1;
float3 worldPos:TEXCOORD2;
};
v2f vert(in appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.texcoord;
o.normalDir = normalize(mul((float3x3)unity_ObjectToWorld, v.normal));
o.worldPos = mul((float3x3)unity_ObjectToWorld, v.vertex);
return o;
}
fixed4 frag(in v2f i) :SV_Target
{
fixed4 col;
col = tex2D(_MainTex, i.uv);
float3 N = normalize(i.normalDir);
float3 L;
float atten;
if (_WorldSpaceLightPos0.w == 0)
{
L = normalize(_WorldSpaceLightPos0);
atten = 1;
}
else
{
float3 light2Vertex = _WorldSpaceLightPos0 - i.worldPos;
L = normalize(light2Vertex);
float Length = length(light2Vertex);
atten = 1 / Length;
}
float Kd = atten*_Bright;
float4 difColor = Kd*_LightColor0*max(0, dot(N, L));
float3 R = reflect(-L, N);
float3 V = normalize(_WorldSpaceCameraPos - i.worldPos);
float4 specuColor = Kd*_LightColor0*pow(max(dot(R,V), 0), _Shininess);
col *= difColor;
col += specuColor;
return col;
}
ENDCG
}
}
}