LoginSignup
5
2

More than 3 years have passed since last update.

3D部分の解像度を下げつつもPostProcessingStackV2を使いたい

Last updated at Posted at 2020-07-12

大元の画像はこちら。
3D描画に、PostProcessingStackV2でBloomとDoFがかかっています。
スクリーンショット 2020-07-12 21.53.41.png
白い部分が滲んでいる(Bloom)&遠景近景がぼやけている(DoF)ことが確認できます
この画像に、
【Unity】カメラ1つでUI解像度を維持し、3D解像度だけを下げる方法
を試してみた所、何やら違和感が。※解像度は半分で、低解像度を強調するためにFilterMode.Point。
スクリーンショット 2020-07-12 23.31.19.png
予定通り解像度は半分になった! ・・・けど、
あれ、PostProcessingStackV2の効果が消えてしまっている?
何故か?ということで、FrameDebuggerを確認した所、
モデルの描画については、指定したとおり、自分で用意したDisplayBufferに描画されている。
スクリーンショット 2020-07-12 22.09.47.png
モデルの描画は意図通りされている様子。
ただ、PostProcessingStackを行っている部分を確認すると…
スクリーンショット 2020-07-12 21.59.55.png
PostProcessingStackの最初の元画像を取得する部分がUnityWhiteテクスチャになってしまっている…!?
元画像が上手く取得できていないみたい。
いわゆるシェーダの

Properties
{
    _MainTex ("Texture", 2D) = "white" {}
}

の"white"を引っ張ってしまっている様子。

普段のPostProcessingStackなら、
スクリーンショット 2020-07-12 22.03.26.png
TempBuffer を _TargetPool0 にコピーしているはずなのに…。


…ということで色々確認した所、下記のことがわかってきた。
ここからは低解像度描画をするために別途用意したRenderTexture低解像度描画用RTと記載する

描画の仕方 モデルなどの描画 PostProcessの元画像取得
camera.SetTargetBuffers(低解像度描画用RT) 低解像度描画用RTに描画される UnityWhiteテクスチャを引っ張ってしまう
PostProcessingStackV2 TempBufferに描画される TempBufferを引っ張る

つまり、やりたい事を達成するためには下記のどれかを達成する必要がある

  • PPSV2を有効にした上でTempBufferのサイズを自由に変更することができれば、3Dのみ低解像度描画が達成できる
  • 低解像度描画用RTの画像をTempBufferにコピーする事ができれば、PostProcessに画像を伝える事ができる
  • PostProcessがTempBufferではなく低解像度描画用RTを拾う事ができれば、低解像度画像にPostEffectをかけることが出来る

結局色々試した所、1つのカメラではどれも達成できませんでした。


1週間近く、試しては消し、試しては消しで途方に暮れてしまった。。
ので、いっそ方針を変更して、2つカメラを用意してPostProcessingStack用にカメラを分けてみることにしました。
順番としては下記の順序となります。

  1. メイン描画用カメラ
    1. SetTargetBuffers()で低解像度描画用RTに書き込むように設定
    2. AfterEverythingタイミングでCommandBufferでSetRenderTarget(-1)で描画先をフレームバッファにする
    3. AfterEverythingタイミングで低解像度描画用RTをCameraTargetにコピーする
  2. PPSV2用のカメラ
    1. メインカメラ描画の直後に描画するようにdepthを設定
    2. 念の為、位置や姿勢など、メイン描画カメラと全く同じ表示となるようにしておく
    3. CullingはPostProcessレイヤのみ表示するようにし、ClearFlagはDon't Clearにしてメイン描画をそのまま使う
    4. PostProcessLayerを付けておいてポストプロセスをかける

という事で「メイン描画は低解像度描画用RTにモデルなどを描画し、PPSV2用はTempBufferが用意されるだろう」という目論見で試してみた結果がこれ。
スクリーンショット 2020-07-12 23.00.15.png
DoFが効いていない…??
FlameDebuggerを確認すると、カメラを切り替えたタイミングでUpdateDepthTextureが走って、深度テクスチャが無効になっていることがわかる。
スクリーンショット 2020-07-12 23.16.08.png
PPSV2用カメラはDon't Clearにしてるのに…。何で深度をクリアしてしまうのか…。
まぁそれでも、カメラを2つにすることでカラー情報をTempBufferに渡すことができた。
という事は、後は深度バッファをPostProcessにわたすことができれば目的が達成できそう…!

なので、先程の処理に深度バッファの取得&コピーを追加してみる

  1. メイン描画用カメラ
    1. SetTargetBuffers()で低解像度描画用RTに書き込むように設定
    2. CommandBufferでAfterDepthTextureのタイミングで深度バッファをキャプチャしておく
    3. AfterEverythingタイミングでCommandBufferでSetRenderTarget(-1)で描画先をフレームバッファにする
    4. AfterEverythingタイミングで低解像度描画用RTをCameraTargetにコピーする
  2. PPSV2用のカメラ
    1. メインカメラ描画の直後に描画するようにdepthを設定
    2. 念の為、位置や姿勢など、メイン描画カメラと全く同じ表示となるようにしておく
    3. CullingはPostProcessレイヤのみ表示するようにし、ClearFlagはDon't Clearにしてメイン描画をそのまま使う
    4. AfterDepthTextureタイミングで、キャプチャ済み深度バッファをBuiltinRenderTextureType.Depthにコピーする
    5. PostProcessLayerを付けておいてポストプロセスをかける

できた画像がこちら。※わかりやすくするために、3D側解像度は半分にしています。
スクリーンショット 2020-07-12 23.21.27.png
ちゃんと3D解像度は半分になりつつ、PostProcessingStackV2の効果もかかっていることが確認できます。
FrameDebuggerも確認。
スクリーンショット 2020-07-12 23.24.07.png
PPSV2用カメラのUpdateDepthTextureの後処理で深度バッファをコピーできていることが見えます。


という事で、カメラ1つで何とかしようとしすぎた事で時間がかかってしまいましたが、なんとか目的達成できました。
同じ苦労をする人が少しでも減ると良いですね。。

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2