はじめに
この記事は GRIPHONE Advent Calendar 2022 13日目の記事になります。
こんにちは、Unityエンジニアの原島です。
Unityビルトイン環境でジオラマ風な印象を与える簡易的なチルトシフトを再現してみました。
チルトシフトの概要と仕組み
チルトシフトとは、特徴的なボケ味の加工を実現する写真の撮影技法のうちの一つです。
撮影技法としてはピントの調整や歪み補正を適用することでミニチュア感のある写真を実現しています。
今回はこのチルトシフトをより簡易的な再現として、画面の上下にぼかしを入れることで再現してみます。
ぼかし
今回ぼかしの手法としてガウス関数をもちいて重みづけを行うガウシアンブラーを使用しています。
実装自体は基本的にUnityのポストプロセスでガウシアンブラーを実装するにはを参考にしています。
フラグメントシェーダ上では、重みづけ用の値自体は参考記事と同様、ガウス関数から事前計算した値を使用し、描画する色を求めています。
static const half weights[samplingCount] = { 0.036, 0.113, 0.216, 0.269, 0.216, 0.113, 0.036 };
float2 dir = _Direction * _MainTex_TexelSize.xy;
fixed4 color = 0;
for (int j = 0; j < samplingCount; j++)
{
float2 offset = dir * ((j + 1) * _TexelInterval - 1);
color.rgb += tex2D(_MainTex, i.uv + offset) * weights[j];
color.rgb += tex2D(_MainTex, i.uv - offset) * weights[j];
}
此方のガウシアンブラーを実際のカメラにアタッチすることで下画像のような画面全体にかかるぼかし感を表現できました。
ぼかしの上下への適用
作成したぼかし効果を画面の上下のみに適用します。
フラグメントシェーダ上で取得したuvのy値に、上下のぼかし制御用のfloat値のEffectAreaを掛け合わせたデータ型を用意し、先ほどの重みづけ処理の中のoffset値に掛けることで任意の位置にのみぼかしを適用させています。
※EffectAreaをプロパティ上等で調整することで、より自然に上下のぼかし幅を調整することが可能です。
half2 coord = i.uv * 2.0 - 1.0 ;
half2 angle = half2(0.0, saturate(pow(abs(coord.y * EffectArea),20)));
for (int j = 0; j < samplingCount; j++)
{
float2 offset = dir * ((j + 1) * _TexelInterval - 1);
color.rgb += tex2D(_MainTex, i.uv + offset * angle) * weights[j];
color.rgb += tex2D(_MainTex, i.uv - offset * angle) * weights[j];
}
おわりに
チルトシフトの仕組みを調べてみると比較的にシンプルな仕組みで再現できることがわかりました。
一方、この手法は画面上での位置に基づいてのみによるぼかし加工となっているため、より現実的な加工を求めるのであれば、被写界深度の調整なども必要になりそうです。