🌈

Unity ShaderGraph備忘録 part3-色収差

に公開

色収差

みんな大好き色収差

端的に言うと画像のRGBがズレる現象の事
英語だとChromatic Aberrationと呼びます

元々はカメラレンズの色の歪みで発生していた効果で、
その効果を模倣してイラストや映像媒体など、広く使われています

モバイルゲームだと負荷軽減の兼ね合いでぼかしの代わりの奥行き表現に使われる事もしばしば


クリスタにもVer.3.0からフィルタとして実装された

alt text
クリスタで色収差を加えた例


イラスト的用途であればクリスタやPhotoshopでいい感もありつつ
もうちょい細かく調整がしたい・アニメーションする色収差が欲しい
といった場合はUnityで色収差シェーダーを作ると、細かい制御や動的な効果を作る事ができます


VolumeのChromatic Aberration

UnityのURP環境などにはvolumeのプリセットにChromatic Aberrationがある
それを使えば手軽に色収差効果が使えます

まずシーン上のCameraのRendering>Post Processingにチェックを入れる
alt text

開いてるシーンのHierarchy上で右クリック>Volume>Global Volumeを選択

作ったGlobal volumeを選び、Inspector上でvolume profileがなければ「New」ボタンを押す
alt text

Add OverrideからPost Processing>ChromaticAberrationを追加する
alt text

追加されたChromaticAberrationの
Intensityにチェックを入れてスライダーを動かすと、色収差が出ます
4隅が引き延ばされる形で、カメラレンズの仕組みに近い処理

シーン上
alt text

ゲームビュー上
「画像」


ただVolumeの色収差だとカメラレンズ的な効果が画面全体にかかるので
sprite単体や任意の形で色収差を出したい時はShaderGraphで自作します


ShaderGraphで実装する色収差

ShaderGraphで任意の色ずれによる色収差を作れます

平行移動の例

基本的な構成は以下
alt text
①UVずらし

  • BlackBoardに登録したIntensity(float)のプロパティ分、uvを+と-方向にそれぞれずらす
    • Intensityは0~0.02ぐらいのスライダーにすると丁度良いです

②ずらしたUVをSampleTexture2Dに繋げる

  • SampleTexture2Dを3つ用意して、そのうちの2つに、①のUVをそれぞれ繋げる
  • 色収差を加えたい画像をTextureに繋げる
    (今回はSpriteにマテリアルをアタッチするのでSpriteの画像をそのまま使用)

③各SampleTexture2DのR・G・BをCombineノードで組み合わせる

  • RGBからの出力がR・G・Bそれぞれのチャンネルに対応している(③の上の方)
    • それをCombineノードに繋げる

作ったShaderGraphを選択してマテリアル化→マテリアルをSpriteにアタッチする
マテリアルのInspector上でIntensityを弄ることで色収差効果を調節できます
alt text
alt text

--追記--
クリスタのように平行移動する色収差の角度を調整したい場合は"Sine"と"Cosine"ノードを使います

alt text

  • Blackboardにfloatのプロパティを登録(angleと名付けます)、maxを360にし、0~360までの値を扱えるようにする
  • angleの値をDegrees To Radians(角度をコンピューターが扱いやすいラジアン(弧度法)に変換するノード。例えば180度は → 1π radians = 約3.14に変換される)
  • ラジアンに変換した値を"Sine"と"Cosine"ノードにつないで、それぞれVector2のx,yに繋ぐ
  • 繋いだVector2の値をIntensityにMultiplyし、元のIntensityが繋がっていたノードにOutを繋げる

これでinspector上のangleを弄ることで角度が調整できるになります
alt text

何が起きてるか
角度を方向ベクトルに変えてIntensityの方向に補正を掛けています。
元のIntensityはUVにadd/Subtractする時にVector2(1,1)に変換 = 45度の方向にスライドします
その値にこの図(Wikipedia)で計算された2つの値を掛ける事で移動方向を調整している訳です。
※例えばangleが90度の時 = π/2 = 約1.57になり、Sine,Cosine関数に入力するとそれぞれ1、0の値を返します
 元のIntensityのVector2(1,1)に先ほどのCosine(= 0),Sine(= 1)をVector2にして掛けると = Vector2(0,1)になり、y方向(縦方向)にのみ。つまり90度の方向に平行移動するようになります

詰まるところは回転行列の簡略系です


放射状の色収差の例

基本的な構成の①の部分を以下のように変えます
alt text
放射上に広げる時の原点を画面の中心に変更して、処理を加えてから原点の変更を元に戻す
という事をしています

具体的には

  • UVから0.5を引いて原点を中心に持ってくる
  • Intensityの直の値・2を掛けた値を用意する
    • 用意した値を1から引いて、それぞれUVにMultiplyする
  • UVに0.5を足して原点を元に戻す

(数式で表すとUV - 0.5 * (処理) + 0.5
 UVを-0.5~+0.5の範囲にして、0の部分を画面の真ん中に移動させています)


放射状に色収差が調節できるようになります
alt text
alt text

※Blackboardにxとyのプロパティも用意して、UVの原点を調整するVector2(0.5の所)のx,yにそれぞれ値を渡してあげると、Inspector上で原点を調節することができます
 0~1のスライダーにすると位置調節しやすいです
alt text


扇状の色収差の例

放射状と同様、①の処理にRotateノードを使います
alt text

  • RotateノードのCenterにx,yの値
    • RotationにIntensityを繋ぐ

扇状に色収差を調節できるようになります
alt text
alt text


という訳で色収差シェーダーの基本的な作り方まで書きました
一旦ここまで

続く

Discussion