Help us understand the problem. What is going on with this article?

Unity でShaderの勉強 その9 ADSシェーディング

More than 3 years have passed since last update.

ADSシェーディングとは

Ambient LightingのA
Diffuse LightingのD
Speqular LightingのS
を合わせてADSシェーディングというらしい。
環境光とディフューズ反射、スペキュラ反射を組み合わせてライティングを行うので簡単にリッチな表現ができるらしい。

計算式はこうなる
I(Intensity:強度) = Ia + Id + Is
Ia = La * Ka
Id = Ld * Kd * max((s・n),0)
Is = Ls * Ks * pow((r・n),f)

Lは光の強さを表す
Kは光の反射率を表す
Laの場合、aはambientを表すからLaはambientのLightの強さ=環境光の強さを表すことになる。

Id(ディフューズの強度)は前回?くらいにやったので省略

Is(スペキュラの強度)について

スペキュラ成分はサーフェイスの輝き具合を表す。
1. 入射光s
2. sの反射光r
3. サーフェイスのノーマルn
4. サーフェイスから視点へのベクトルv
5. vとrの距離に応じてどれくらいスペキュラを小さくするか f

が使われる。

入射光sから反射光rを求めるには以下の式を使う

r = -s + 2(s・n)n

反射光rによってもたらされる反射の強さは、視点までのベクトルvと全く同じ時に最大となり、rとvがずれると大幅に減衰する。
rとvの内積結果を累乗することでθ分離れた時に急速に値を小さくすることができる。何乗するかはfで表す。
これにスペキュラライトの強度Lsとスペキュラ反射率Ksを組み合わせることでIsの式はいかになる。

Is = Ls * Ks * Pow((r・v),f)

r・vの結果が0未満になると2乗した時に整数になるからスペキュラがおかしくなるのかな?
ひょっとしたらPow(max(r・v),0),f)の方が良いかもしれない。

コード

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);
                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 19.36.07.png
ライトの向きを変えてみる
スクリーンショット 2017-02-23 19.37.19.png
Materialの設定
スクリーンショット 2017-02-23 19.37.38.png

注意点

NORMALセマンティクスがNormalとなっていたためUnityObjectToWorldNormal関数が正常に動作せずdiffuseが0になってSphereが真っ暗になっていた。注意。

正しい
v2f vert(float4 pos : POSITION,float3 normal : NORMAL) {
間違い
v2f vert(float4 pos : POSITION,float3 normal : Normal) {
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした