今週はテッド チャンの「息吹」を読むのに熱心です。
前回に引き続き、です。今回は10章から12章までPhongの反射モデルの実装に踏み込んでいきます。(短め。)
学んだことのメモ(章ごと)
第10章:Phong モデル
「Phongの反射モデル」の実装パートです。このモデルはこれまで扱ってきた拡散反射光(と環境光)に加えて、ここまで踏み込んでこなかった鏡面反射光を計算に含めるものです。鏡面反射光(=ハイライト)は肉眼で金属などの物体を見るときに観察できる鋭い反射光のことです。求め方としては視線ベクトルと(光の)反射ベクトルの差(なす角)をそのまま利用します。
// 視線ベクトル view = カメラの(ワールド)座標 - 頂点の(ワールド)座標 float3 view = normalize(_WorldSpaceCameraPos - i.vertexW); // 反射ベクトル = 入射光(便宜的にマイナス)と頂点の法線方向から計算(以下と同義) float3 rflt = normalize(reflect(-light, normal)); // 視線ベクトルと反射ベクトルの差(角度)は内積で求める = saturate(dot(view, rflt)) float specular = pow(saturate(dot(view, rflt)), _Shiness);
_Shinessは鏡面反射のしやすさ(ある意味では範囲と言って良いかもしれない)に影響するもので、大きければ鋭い反射(狭い範囲)で、小さければ鈍い反射(広い範囲)で表面の反射が変わります。
10章、スペキュラ―ライトの指数による影響。 pic.twitter.com/zbeqMAcwpi
— ayato (@dn0t_) October 4, 2020
視線ベクトルを求めるには、実はUnityWorldSpaceViewDirというのがUnityCG.cgincに用意されていました。
inline float3 UnityWorldSpaceViewDir( in float3 worldPos ) { return _WorldSpaceCameraPos.xyz - worldPos; }
「おー、まんまやな」と言う感じです。黙ってこれ使いましょう。
ところでこの章の最後に「Phongの反射モデル」と「Phongシェーディング」は意味違うからね!との注意がありました。実際Wikiの「Phongの反射モデル」にも
併せてこの論文中には、多角形面モデルからラスタライズされた個々のピクセルに対して、補間計算を行う方法も論述されていた。 この補間技術は後述するようにPhongシェーディングとして知られている。
と書いてありました。ひー、誤用して叩かれないように覚えておこう。
第11章:Blinn-Phong モデル
少し読んだだけでわからなくなりそうだったので、ググってみたところこちらのサイトなどが参考になりました。自分のノートの画像を貼っておきます。 ところで「ハーフベクトル」という概念がここで出てきましたが、正しい数学用語(?)ではなくCG界隈で便宜的に使われるものなのでしょうか。それ系のサイトばかり出てきました。
第12章:フレネル反射
「フレネル」という言葉は以前Blenderでセルルックな表現に挑戦した際にキャラのリムライトに代替させる方法として出てきた言葉として覚えていました。このおかげもあって理解はしやすかったです。ざっくりと言えばオブジェクトに光を当てると輪郭がぼわーんと明るく見えるあれの実装ですね。(あるいはプールを水平に見るか垂直に見るか、みたいな例も?)
ここではわざとフレネルの影響部分だけを表示させてみました。
12章、フレネル反射係数による影響。 pic.twitter.com/2Ma1fxeUOa
— ayato (@dn0t_) October 5, 2020
おそらく次でVol.03の読書録は終わると思います。