Unityでシェーダを書く場合、とりあえず開発者が必要そうな変数やら関数はUnity側で用意されていることが多いので
"UnityCG.cginc"
、"AutoLight.cginc"
、"Lighting.cginc"
この辺りのファイルたちを眺めると良い感じです。
このようなライト方向とカラーを適用したいわゆるランバートシェーダを書いてみます。
※前提としてディレクショナルライト1個の世界
ライトベクトルは_WorldSpaceLightPos0
と記述すればUnityが勝手に値を突っ込んでくれます(とっても便利)。
ライトのカラーはfixed4 _lightColor0
と定義すれば、先取同様Unityが勝手に値を突っ込んでくれます。
ただし、Lighting.cgincをインクルードしているとコンフリクトしてコンパイルエラーになるので注意です。
それらのデータを使って処理を書いていくわけですが、こんなに至れり尽くせりなのですが、 _WorldSpaceLightPos0
は頂点シェーダで使うことが出来ず、フラグメントシェーダ内でしか使えません。エラーは出ませんが、おそらく値が(0,0,0,0)になっています。
上のサンプルはピクセルライティング(ピクセル単位でライト処理を実行している)なのですが、頂点ライティングもやってみます。
ということで頂点ライティングは以下のような実装になります。
- C#側からシェーダへ
ライトベクトル
を渡す - 頂点シェーダで頂点単位で拡散反射輝度を計算する
- フラグメントシェーダで頂点ごとの輝度を描画する
シェーダとC#のサンプルコードです。
これらを描画するメッシュ、GameObjectにアタッチする想定です。
※注意 : もっと簡単な方法を後述しています
と、ここまで書いててあれですが、WorldSpaceLightDir
というヘルパー関数があります。
この関数を使えば頂点シェーダ内で、ライトベクトルが取得できることがわかりました。
※C#のコードは不要となりますorz
最終このシェーダだけで頂点ライティングが出来るようになりました。
まとめ
- 頂点シェーダ内でディレクショナルライトベクトルを受け取る方法は、
WorldSpaceLightDir(オブジェクト空間頂点座標)
というヘルパー関数を使用する
です。
環境
- Unity2018.2.12f1