Unityシェーダーチュートリアル ポストプロセスを使わずにトーンマッピングをする
シェーダー
建物のライティングをしているとだいたいこのような事になります。
特に壁が白とかベージュとか明るい系の色だと
照明付近がものすごく白飛びするのでとても下品です。
PC用コンテンツであればポストプロセスでトーンマッピングすれば良いのですが、
モバイル用コンテンツの場合、パフォーマンスの関係で使いたくなかったり、
うまく使えなかったりします。
かといってこのまま画として仕上げるわけにもいかないので、
AOを強めにかけてみたり、ライトの直接強度・間接強度をごにょごにょしてみたり。。。
などとやっていると、どんどん画が破綻していくわけです。。。
何か楽にいい感じになる方法はないものかとあれこれ考えていたら、
先日がっつり作業していたHDRPの事を思い出しました。
HDRPのシェーダーグラフでは、Override Baked GI という項目があり、
ベイク済みのライトマップをシェーダー内で直接編集することができます。
Standardシェーダーにはそのような項目はありませんが、
ビルトインシェーダーのファイルにちょっと追記すればできそうなのでやってみます。
Standard ライティングモデルのコードを改造する
デフォルトのシェーダーファイルを持ってくる
ビルトインのシェーダーコードは,Unity のインストールフォルダの中に入っています。
[インストールフォルダ → Editor → Data → CGIncludes] を開いてください。
数十個のシェーダーファイルの中に、UnityPBSLighting.cginc というファイルがあります。
このファイルをプロジェクトにインポートします。
同フォルダにシェーダーを新規作成すれば自動的に
インストールフォルダではなくこちらの UnitiyPBSLighting.cginc を読みにいきます。
UnityPBSLighting.cginc を探る
UnityPBSLighting.cginc の中に以下のようなコードが含まれています。
※ 記述を省略しています
inline half4 LightingStandard (・・・) {・・・}
inline half4 LightingStandard_Deferred (・・・) {・・・}
これが、Standard シェーダーのライティングコードです。
上が Forward レンダリング用、
下が Deferred レンダリング用 です。
この2つのコードの中に、下記のような記述があります。
UNITY_BRDF_PBS (s.Albedo, specColor, oneMinusReflectivity, s.Smoothness, s.Normal, viewDir, gi.light, gi.indirect);
最後の引数の、 gi.indirect にライトマップの情報が入っており、
gi.indirect.diffuse で取得することができます。
これを UNITY_BRDF_PSB に渡す前に編集してしまおうというわけです。
ライトマップにトーンマップをかける
以下の記事を参考に、ACES Filmic Tonemapping をやってみます。
gi.indirect.diffuse = saturate(
(gi.indirect.diffuse * (gi.indirect.diffuse * 2.51 + 0.03)) /
(gi.indirect.diffuse * (gi.indirect.diffuse * 2.43 + 0.59) + 0.14)
);
UNITY_BRDF_PBS (s.Albedo, specColor, oneMinusReflectivity, s.Smoothness, s.Normal, viewDir, gi.light, gi.indirect);
結果こうなりました。美しい。
トーンマップの式を変えてみたり、かける前と後でブレンドしてみたり、いろいろできそうですね。
[…] ポストプロセスを使わずにトーンマッピングをする | Tsumiki Tech Times […]