LoginSignup
2
5

More than 5 years have passed since last update.

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

Posted at

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

結果:式改善後も見た目は変わっていない
スクリーンショット 2017-02-23 21.27.53.png
スクリーンショット 2017-02-23 21.28.45.png

2
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
5