サーフェイスの輝きを計算するSpeqularの式は以下になります。
入射光sに対する反射 r = -s + 2(s・n)n
Speqular式Is = Ls * Ks * pow(max(r・v,0),f)
反射rの算出には内積を使っていたりと計算量が多いため、これを改善します。
vとsが同ベクトルになるとnはvとsの中間になる性質を利用して
rの近似値となる中間ベクトルhを代わりに使ってSpeqular式を再作成します。
中間ベクトルh = (v + h).normalize
Speqular式Is = Ls * Ks * pow(max(h・n),f)
rの算出がなくなった分いくらか処理負荷が減ったと思います。
コード
Shader "Custom/TestShader" {
Properties {
_MainColor("MainColor",Color) = (1,1,1,1)
_Ka("Ambient反射",Range(0,1)) = 0.5
_Kd("Diffse反射",Range(0,1)) = 0.5
_Ks("Speqular反射",Range(0,1)) = 0.5
_f("Speqular減衰率",Int) = 5
[Toggle] _useAmbient("Use Ambient",Float) = 1
[Toggle] _useDiffuse("Use Diffuse",Float) = 1
[Toggle] _useSpeqular("Use Speqular",Float) = 1
}
SubShader {
Tags { "Queue" = "Geometry" "RenderType" = "Opaque" "LightMode" = "ForwardBase"}
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
uniform float4 _LightColor0;
uniform float4 _MainColor;
uniform float _Ka;
uniform float _Kd;
uniform float _Ks;
uniform int _f;
uniform float _useAmbient;
uniform float _useDiffuse;
uniform float _useSpeqular;
struct v2f {
float4 wPos : SV_POSITION;
float4 ambientColor : Color0;
float4 diffuseColor : Color1;
float4 speqularColor : Color2;
};
v2f vert(float4 pos : POSITION,float3 normal : NORMAL) {
v2f output;
output.wPos = mul(UNITY_MATRIX_MVP,pos);
float3 wNormal = UnityObjectToWorldNormal(normal);
//calculate ia
output.ambientColor = unity_AmbientSky * _Ka;
//calculate id
output.diffuseColor = _LightColor0 * _Kd * max(dot(_WorldSpaceLightPos0 ,wNormal),0);
//calculate is
//float3 r = -_WorldSpaceLightPos0 + 2 * dot(_WorldSpaceLightPos0,wNormal)* wNormal;
//output.speqularColor = _LightColor0 * _Ks * pow(max(dot(r,_WorldSpaceCameraPos),0),_f);
float3 h = normalize(_WorldSpaceLightPos0 + _WorldSpaceCameraPos);
output.speqularColor = _LightColor0 * _Ks * pow(max(dot(h,wNormal),0),_f);
return output;
}
float4 frag(v2f input) : SV_TARGET {
float4 adsColor = (0,0,0,0);
if(_useAmbient) {
adsColor += input.ambientColor;
}
if(_useDiffuse) {
_MainColor += input.diffuseColor;
}
if(_useSpeqular) {
adsColor += input.speqularColor;
}
return _MainColor * adsColor;
}
ENDCG
}
}
}