Ride into the Standard Shader: A Guide to Custom Lighting Models
このエントリは GREE Advent Calendar 2015 11日目の記事です。
こんにちは、Art グループ / Technical Artist チームの酒井 駿介です。グリーでの今までのお仕事は、東京ゲームショウ2015 に出展した VR ゲーム サラと毒蛇の王冠 や、先月リリースされた モバイル VR ゲーム シドニーとあやつり王の墓 の開発などです。シドニーは iOS / Android で遊ぶことができます。ぜひプレイしてみてください。また、弊社の VR に対する技術的取り組みについては、5日目 の Robin のエントリをご覧ください。
本エントリの「グリーをささえる技術」のテーマは Unity の Standard Shader です。技術者だけではなく、ゲーム・映像問わず多くの3Dアーティストの参考になれば幸いです。(ちなみに、わたしはエンジニアではなくART 部所属のクリエイターです)
Standard Shader おさらい
そもそも Shader って? という方は、わたしが 2015 年 11 月の GREE Creators’ Meetup #3 で発表した アーティストのためのプログラマブルシェーダ講座 をご覧ください。
ご存知の通り、Standard Shader は Unity 5 から搭載された PBR 機能をもつ高機能な Shader タイプです。Standard Shader のレンダリングには、Shader Model 3.0 相当 に対応したハードウェアが必要なので、モバイルコンテンツに全面的に取り入れるにはまだ難しいかもしれませんが、デスクトップ PC がプラットフォームである VR コンテンツ制作に取り組んでいる弊社では、この Standard Shader を積極的に活用しています。
Standard Shader のマテリアルを使って、適切なライティング設定が行われたシーンからは、Unity の Global Illumination ( GI )機能とも相まって、非常に高品質なレンダリング結果を得ることができます。
そんな Standard Shader を、さらにクリエイターがカスタムしていくことで、これまでにない新たな表現を作り出すことができます。そのポイントの1つが、Lighting Model です。
Lighting Model
Lighting Model とは、マテリアルがもっているプロパティ ( Color, Texture Color, Specular Value, etc. ) と、ライトの情報 ( Light Color, Direction, Attenuation ) を使用して、物体が光に照らされた状態を表現するための計算モデルです。3D用語でいうところの、 Lambert や、Blinn がこの Lighting Model にあたります。
Lighting Model に手を加えると、例えばアニメのような toon 調マテリアルなど、様々な表現を作ることができます。
Unity で Lighting Model を扱う場合、Surface Shader 内で関数のような形式で記述することになります。( Vertex & Fragment Shader 方式でも Lighting Model は扱えますが、かなり複雑になってしまいます)
Legacy Shader の Lighting Model
Unity 公式サイトから Built in Shader をダウンロードし、ファイルを覗いてみると、Lighting.cginc というファイルに Lighting Model が定義されているのを確認できます。これは、見ての通り Lambert の Lighting Model です。
1 2 3 4 5 |
inline fixed4 LightingLambert (SurfaceOutput s, UnityGI gi) { ... } |
Standard Shader の Lighting Model
一方、Standard Shader では Legacy Shader と異なり、UnityPBSLighting.cginc というファイルに Lighting Model が定義されています。このファイルでは、 Standard と StandardSpecular という2つの Lighting Model が確認できます。
1 2 3 4 5 |
inline half4 LightingStandard (SurfaceOutputStandard s, half3 viewDir, UnityGI gi) { ... } |
1 2 3 4 5 |
inline half4 LightingStandardSpecular (SurfaceOutputStandardSpecular s, half3 viewDir, UnityGI gi) { ... } |
今回は、この LightingStandard をベースに、Lighting Model を独自に定義してみようと思います。
カスタム Standard Shader の Lighting Model を変更する
まず Unity Editor の Project Window から Create > Shader > Standard Surface Shader と進み、カスタム Shader を作成します。この状態ではまだ Lighting Model として Standard を使うようになっているので、今回は StandardCustom が Lighting Model 名として扱われるよう、 directive を変更します。
1 2 |
#pragma surface surf StandardCustom |
次に、Shader と Lighting Model のやりとりするに使われるプロパティの構造体 SurfaceOutput を用意します。名前を StandardCustom に合わせ、内容は UnityPBSLighting.cginc ファイルからコピーします。
1 2 3 4 5 6 7 8 9 10 11 |
struct SurfaceOutputStandardCustom { fixed3 Albedo; // base (diffuse or specular) color fixed3 Normal; // tangent space normal, if written half3 Emission; half Metallic; // 0=non-metal, 1=metal half Smoothness; // 0=rough, 1=smooth half Occlusion; // occlusion (default 1) fixed Alpha; // alpha for transparencies }; |
そして、Shader 内に StandardCustom という Lighting Model を定義します。とりあえず、中身は .cginc と全く同じです。
1 2 3 4 5 |
inline half4 LightingStandardCustom (SurfaceOutputStandardCustom s, half3 viewDir, UnityGI gi) { ... } |
また、GI 関連の計算を行う関数も、同じく中身は変えずに名前だけ変更して記述します。
1 2 3 4 5 6 7 8 |
inline void LightingStandardCustom_GI ( SurfaceOutputStandardCustom s, UnityGIInput data, inout UnityGI gi) { UNITY_GI(gi, s, data); } |
最後に、Lighting Model で使われている関数を利用するため、UnityPBSLighting.cginc をインクルードしておきます。
1 2 |
#include "UnityPBSLighting.cginc" |
Legacy Shader で Lighting Model を定義する場合よりも複雑になってしまいましたが、これでカスタム Standard Shader に Lighting Model を定義することができました。あとは、この Lighting Model 内で自由に Shader プログラムを書いていきましょう。次からは、具体的なプログラムをいくつかご紹介します。
カスタム Standard Shader 応用編
スクリーントーンシェーダ
スクリーンスペースで展開したドットパターンのテクスチャを、モデルの陰の部分だけにマスクして表示しています。LightingStandard をベースにているので、バッチリ PBR が効いています。フォトリアルとノンフォトリアルが同時に存在している、不思議な表現です。
陰部分のマスクは、法線ベクトルとライトの方向ベクトルを dot 関数にかけることで実現しています。ライトの方向ベクトルは、以下のように取得できます。
1 2 |
half3 lightDir = gi.light.dir; |
Advanced Rim Lighting
Rim Lighting で計算した Emission を、ライトの方向と法線ベクトルを元にマスクすることで、通常の Rim Lighting よりも自然なイメージを表現することができます。デフォルメされたキャラクターに使ってもいいですし、リアルな皮膚の質感表現とも相性がよいかもしれません。
みなさんも、ぜひ Standard Shader で面白い絵作りに挑戦して見てください。明日は橋本さんによる S3 の記事です。お楽しみに!