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