見出し画像

"Distortion"で画面を歪ませよう 【Unity/URP/ShaderGraph #ポケテク】

こんにちは!ポケラボのテクニカルアーティスト礒部です。

今回のポケテクでは、シェーダーでの歪み(Distortion)効果について紹介しつつ、ShaderGraphで実装していきます。



歪み(Distortion)効果について

UnityのURPにおけるDistortionとは、一般的に不透明なオブジェクトを描画したのちに半透明を描画するタイミングで不透明オブジェクトを描画したテクスチャ(OpaqueTexture)を利用してUVをうまく歪ませることで歪み効果を得ることを指します。

シーン上で見るとこのように、ポケロボくんやカラフルなキューブの手前に、歪み用のQuadが置いています。

この効果を使うことで、例えば、

  • 高温であることを示すために陽炎のようにゆらゆらとさせる

  • ブラックホールによる空間の歪みを表現する

  • 剣を振った時のスラッシュエフェクトに軌跡を歪ませてケレン味を増す

といったことができるようになります。
非常に汎用性が高く、視覚効果も得やすいエフェクトです。ぜひShaderGraphで実装できるようになっておきましょう!


実装

まず事前準備として、Universal Render Pipeline Assetの設定から不透明テクスチャの描画を有効にする必要があります。下の画像の赤枠部分を有効にしてください。
また、その下のDownSamplingNoneにすると、不透明テクスチャの解像度を落とすことなく綺麗に表示できますが、その分メモリなどを圧迫することに注意してください。

さて今回実装するShaderGraphの全体観は以下の通りです。

GraphSettingsでは、UnlitでTransparent(半透明)にしています。
Opaque(不透明)のままだと、そのタイミングではまだ不透明テクスチャが描画されてないタイミングになるので意図しない見え方になってしまいます。

では左上のMaskグループから見ていきましょう。

こちらではQuadのUVにおける端側を歪まないようにし、Quadの境界で急に歪み始めてしまうといった違和感がないようにするためのマスクを形成しています。UVのX,Y成分にそれぞれSmoothStepをかけ、それらをそれぞれ乗算し、端が黒になるようなマスクを作ります。

マスクあり
マスクなし

次に左下のNoiseグループです。

こちらではまず、UVの1方向にスクロールするために、TIllingAndOffsetノードのOffsetにTimeから値を入れています。
Tillingは ( 1 , 8 ) と縦に押しつぶされたようにタイリングさせています。
スクロールさせたUVでGradientNoiseをサンプルし、そちらにMaskグループで作ったマスクを乗算しています。

最後に、Sample Scene Color with Distorted UVグループです。

NormalFromHeightノードのInに、Noiseグループで作ったノイズを入れています。こちらはHeightの情報からNormal(法線)を生み出してくれるノードで、ノイズなどを手軽にNormalにしてくれるので、楽したい時にはおすすめです。
次にSwizzleノードでxy成分のみにし、歪みの強さのパラメータ(DistortionIntensity)を乗算しています。このパラメータはかなり小さめのほうがよいでしょう。自分は0~0.1の範囲でSliderで調整できるようにしました。
最後にScreenPositionに加算して、それをUVとして一番右のSceneColorノードで使用しています。SceneColorノードは歪めたUVを用いて不透明テクスチャを描画してくれます。

最後にこちらのシェーダーをもとにマテリアルを作り、Quadなどのメッシュに割り当てて、歪みの強さのパラメータを調節してみてください。こちらのように歪みがアニメーションしながら強さを調整できれば完成です。

こういったシェーダーを使い、斬撃エフェクトのような活用をする場合は、ParticleSystemCustomVertexStreams機能を利用すると簡単に歪みの強さを調節できるようになります。ぜひそちらも試してみてください。


ポケラボでは3D関連職種をはじめ新規開発を一緒に推進いただける仲間を募集しています。少しでもポケラボに興味をもっていただいた方は、カジュアルなご相談からでも大歓迎なので、お気軽にご連絡ください!

株式会社ポケラボ 採用サイト

カジュアル面談をご希望の方はこちら


みんなにも読んでほしいですか?

オススメした記事はフォロワーのタイムラインに表示されます!