UnityのLWRPで_CameraOpaqueTextureを利用してGrabPassのようなことをする

はじめに

Unityの従来のレンダーパイプラインではGrabPassという特殊なパスを利用して それまでにレンダリングした絵をテクスチャとして利用できました。 LWRPを含むSRPではGrabPassが使えなくなります。 LWRPではGrabPassの代替として_CameraOpaqueTextureというものが用意されています。 このテクスチャをShader Graphから利用してみます。

  • Unity:2018.3.0b8
  • LWRP:4.1.0-preview

_CameraOpaqueTexture

SRPではGrabpassがなくなっています。 次のページの制限事項の項目にサラッと書かれています。

すべてのスクリプタブルレンダーパイプライン(SRP)に言えることですが、ライトのレンズフレアなど、以前 Overlay レイヤーでレンダーされたものにはすべて非対応です。Grabpass はなくなっています。

それではGrabpassの代わりになる表現はないのかと調べたところ、 _CameraOpaqueTextureというものがあるそうです。

Shader Graphから扱っているツイートがありました。

_CameraOpaqueTextureを使う

さきほどのツイートでほとんど説明されていますが、 微妙足りていない部分があるので補足します。

_CameraOpaqueTextureを使うには LWRPの設定で「Opaque Texture」を有効にする必要があります。

後はさきほどのツイートの動画のとおりに進めればOKです。

プロパティを作成し「Reference」に「_CameraOpaqueTexture」と入力します。

「Exposed」は必要ないのでオフにしました。

適当にPBR Masterにつなげてみます。

RenderQueueは「Transparent」に設定します。

これで次のようになります。

これで生成されるコードは次のようになります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
TEXTURE2D(_CameraOpaqueTexture); SAMPLER(sampler_CameraOpaqueTexture); float4 _CameraOpaqueTexture_TexelSize;

...

SurfaceDescription PopulateSurfaceData(SurfaceDescriptionInputs IN)
{
SurfaceDescription surface = (SurfaceDescription)0;
float4 _ScreenPosition_4567259E_Out = float4(IN.ScreenPosition.xy / IN.ScreenPosition.w, 0, 0);
float4 _SampleTexture2D_DC5F7424_RGBA = SAMPLE_TEXTURE2D(_CameraOpaqueTexture, sampler_CameraOpaqueTexture, (_ScreenPosition_4567259E_Out.xy));
float _SampleTexture2D_DC5F7424_R = _SampleTexture2D_DC5F7424_RGBA.r;
float _SampleTexture2D_DC5F7424_G = _SampleTexture2D_DC5F7424_RGBA.g;
float _SampleTexture2D_DC5F7424_B = _SampleTexture2D_DC5F7424_RGBA.b;
float _SampleTexture2D_DC5F7424_A = _SampleTexture2D_DC5F7424_RGBA.a;
surface.Albedo = (_SampleTexture2D_DC5F7424_RGBA.xyz);
surface.Normal = IN.TangentSpaceNormal;
surface.Emission = IsGammaSpace() ? float3(0, 0, 0) : SRGBToLinear(float3(0, 0, 0));
surface.Metallic = 0;
surface.Smoothness = 0.5;
surface.Occlusion = 1;
surface.Alpha = 1;
surface.AlphaClipThreshold = 0;
return surface;
}

...

適当にUVをずらしてReflection Probeと合成してみました。

おわりに

LWRPでGrabpass的なことをしてみました。 従来のレンダーパイプラインといろいろと勝手が違ってわからないことばかりで大変です。