Unity でShaderの勉強 その11 Speqular式Isの改善

サーフェイスの輝きを計算する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
        }
    }
}
```

結果:式改善後も見た目は変わっていない
<img width="352" alt="スクリーンショット 2017-02-23 21.27.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/67575/5cf1bba7-0c54-0c01-1ab5-80095c9f5554.png">
<img width="359" alt="スクリーンショット 2017-02-23 21.28.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/67575/376c783e-03c0-8fed-2490-1f47eb49469d.png">