UnityのHDRPでのGrabPassの代替表現
はじめに
Unityの従来のレンダーパイプラインではGrabPassという特殊なパスが存在しました。
このパスを利用することで、それまでにレンダリングした絵をテクスチャとして利用できました。
このパスを利用することで屈折表現やその他特殊な表現を実装することもありました。
このパスは便利だったのですが、
LWRPやHDRPなどのSRPではGrabPassが廃止されてしまいました。
今回はHDRPでのGrabPassの代替表現について軽く調べたのでまとめます。
- Unity : 2019.2.0b1
- HDRP : 6.7.1-preview
屈折及び歪みの表現
SRPではGrabpassがなくなっています。 次のページの制限事項の項目にサラッと書かれています。
すべてのスクリプタブルレンダーパイプライン(SRP)に言えることですが、ライトのレンズフレアなど、以前 Overlay レイヤーでレンダーされたものにはすべて非対応です。Grabpass はなくなっています。
HDRPではこの廃止されたGrabPassの機能のうち屈折などの表現の代わりとなる機能が
LitシェーダおよびUnlitシェーダに実装されているようです。
Litシェーダ
まずはLitシェーダから見ていきます。 Litシェーダのマテリアルを作成して「Surface Type」を「Transparent」に変更します。
「Base Color」を透明にします。
「Transparency Inputs」の「Refraction Model」を「None」から変更します。
「Smoothness」の値によってぼかしのかかったような透明の表現になります。
「Smoothness」を1に、「Index Of Refraction」を1.04にすると次のようになりました。
スクリーンスペースで屈折を表現しているためなのか、IORの値などによっては 屈折が欠けることもあるようです。
「Transparency Inputs」ではIORなどを設定する前述の方法の他に もう1つ屈折のような表現を行う方法が用意されています。 「Distortion」のチェックボックスをオンにします。
Distortion Vector Mapというのが登録できるようになっています。 このマップはRとGにxy方向へのズレを、bにブラー成分を入れたものとなっています。
試しにこのようなテクスチャを入れてみました。
Quadにこのマテリアルを貼り付けてみると次のようになりました。
Unlitシェーダ
Unlitシェーダには「Distortion」があります。
透明のオブジェクトにライティング効果がかかるとガラスのようになります。 単純に空間を歪ませたい場合にはUnlitが使えそうです。
エフェクトの周囲の空間を歪ませるのに使ってみました。
HDRPのTransparentなUnlitのDistortionを使ってみた例 pic.twitter.com/lNeb3nf0nv
— 折登 いつき (@MatchaChoco010) 2019年5月22日
Shader Graph
Shader Graphでもこれらの表現は使えます。 次の例はHDRP用のUnlitシェーダグラフでDistortionを使っています。 歯車アイコンから「Distortion」をオンにすることでMasterノードにDistortionの項目が生えます。
ノイズをRG成分に割り当ててみました。
これで次のようになりました。
Shader GraphでDistortionをスクロールするTransparentなUnlitのマテリアルを作ってSphereに割り当ててみた。 pic.twitter.com/i4gy3rWmsN
— 折登 いつき (@MatchaChoco010) 2019年5月22日
その他の表現
屈折のような表現はできましたがもう少し自由な表現を行おうとすると 画面をテクスチャとして直接いじりたくなります。
HDRPでは内部で_ColorPyramidTextureというテクスチャに描画内容を書き出しています。
ShaderVariables.hlsl内部に_ColorPyramidTextureから色をサンプルしてくる
SampleCameraColorという関数が用意されています。
この関数をTransparent以降の描画タイミングで利用すると従来のGrabPassのようなことが
行えます。
試しにShaderGraphからSampleCameraColorを利用してみます。
HDRPのUnlitなShaderGraqphを用意します。
「Surface Type」を「Transparent」に変更します。
Screen Positionノードを作成します。
Custom Functionノードを生成して、SampleCameraColor(uv)とします。
uv.y = 1 - uv.y;
Out = SampleCameraColor(uv);
Out.rgb *= 0.2;uvのy座標を反転し、色を取得してからそれを0.2倍にして暗くしています。
Custom FunctionノードでSampleCameraColorが存在しないとのことで警告されています。
しかし、生成されるコードではShaderVariables.hlslが読み込まれており問題なく動きます。
HDRPでGrabPass的なことをやる方法がだいたいわかった。 pic.twitter.com/Ivi3g22lQy
— 折登 いつき (@MatchaChoco010) 2019年5月25日
この_ColorPyramidTextureはHDRとなっているようです。
そのため色調をいじろうとしても思ったような色にならないこともありそうですが、
おおよそGrabPassと同じ感覚で使えるようになったのではないでしょうか。
2019/09/21追記
こんなややこしいことをしなくてもHD Scene Colorという レンダリングした絵をとってくるノードがズバリ存在しました。
おわりに
HDRPでのGrabPassの代替手段をまとめました。
歪ませたい場合はHDRPのLitおよびUnlitシェーダに用意されている機能で十分そうです。
さらに特殊なことをしたい場合にはSampleCameraColorを利用すると良さそうです。