質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Q&A

1回答

1609閲覧

Unity HDRP Hole.ioのようなゲームを作りたい

john9999

総合スコア0

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

0グッド

0クリップ

投稿2022/05/28 12:12

Unity HDRP2020.3.19f1にて、Hole.ioのようなゲームを作りたいです。

現状、下記動画(URP)を参考にしていますが、
https://www.youtube.com/watch?v=5qGE2PL9wwU
動画内16:52頃か説明されているRenderer Featuresの設定(HoleやHolemaskの描画順序を入れ替えて穴を表現する)
がHDRPでできません。

いろいろググった結果、HDRPの場合、CustomPass(GameObject > Volume > Custom Pass)で実装できるかと思いましたが、HoleMaskの部分だけHoleを前面に表示することができていない状態で行き詰りました。

解決手段もしくは解決糸口を探しております。
よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

HDRPに疎いものでご参考程度ということでお願いしたいのですが、ご質問を拝見して調べてみたところ確かにCustom Pass機能を使うのが適切そうですね。

あらかじめ用意されているDraw renderers Custom Passとかいうものが、URPで言うところのRender Objectsに相当するもののように思われました。
ですが、どうやらRender Objectsと違ってステンシル設定をオーバーライドする機能はないようです。UserStencilUsageの説明を見ますに、どうやらUnityユーザーが自由に使えるステンシルビットは2つしかないんでしょうかね。
想像しますに、他のビットは複雑な描画を実現するためにHDRPの内部で使われていて、URPのように自由にオーバーライドすることを許してしまうとトラブルの原因になりやすい...みたいな事情があるのかもしれません。

代用品として下記HoleCustomPassスクリプトを用意し...

C#

1using UnityEngine; 2using UnityEngine.Rendering; 3using UnityEngine.Rendering.HighDefinition; 4using UnityEngine.Rendering.RendererUtils; 5 6public class HoleCustomPass : CustomPass 7{ 8 private static ShaderTagId[] forwardShaderTags; 9 10 // 描画対象とするオブジェクトのレンダーキュー 11 public RenderQueueType queue = RenderQueueType.All; 12 13 // マスク用パスの場合ShaderHoleMaskレイヤーを、穴用パスの場合ShaderHoleレイヤーを選択 14 public LayerMask layerMask = 1; 15 16 // オブジェクトの奥行き方向のレンダリング順序の設定 17 public SortingCriteria sorting = SortingCriteria.CommonOpaque; 18 19 // マスク用パスの場合、ここにチェックを入れておきます 20 public bool mask = false; 21 22 // マスクを書き込むビットを選択 23 // たぶんUserBit0でいいかと思うのですが、もし他のシェーダーがUserBit0を 24 // 使用している場合は、競合して描画不具合を起こすかもしれません 25 // その場合はUserBit1を試してみてください 26 public UserStencilUsage stencilBit = UserStencilUsage.UserBit0; 27 28 protected override void Setup(ScriptableRenderContext renderContext, CommandBuffer cmd) 29 { 30 forwardShaderTags = new[] 31 { 32 HDShaderPassNames.s_ForwardName, 33 HDShaderPassNames.s_ForwardOnlyName, 34 HDShaderPassNames.s_SRPDefaultUnlitName 35 }; 36 } 37 38 // 地面の端より外から地面の下を見ると、地面の下に穴の内壁が伸びているのが 39 // 見えてしまう現象を回避するため、URocks!さんのチュートリアルでは 40 // パイプライン設定のFiltering→Opaque Layer Maskからレイヤーを除外して 41 // いるようですが、HDRPだとどの設定があれに該当するのか分かりませんでした... 42 // そこで、代わりにメインカメラのCulling Maskからマスク用・穴用レイヤーを 43 // 除外しておき、ここでレイヤーマスクを追加してやることにしました 44 // シーンビューだと相変わらず穴が地下に伸びてしまうでしょうが、メインカメラの 45 // 映像ではマスク外に穴の内壁は描かれなくなるだろうと思います 46 protected override void AggregateCullingParameters(ref ScriptableCullingParameters cullingParameters, HDCamera hdCamera) 47 { 48 cullingParameters.cullingMask |= (uint)(int)this.layerMask; 49 } 50 51 protected override void Execute(CustomPassContext ctx) 52 { 53 // ステンシル設定をオーバーライド、さらに穴用パスならデプス設定もオーバーライド 54 var stateBlock = new RenderStateBlock(RenderStateMask.Stencil | (this.mask ? 0 : RenderStateMask.Depth)) 55 { 56 // URocks!さんのチュートリアルではリファレンス値を1にしていますが、 57 // 代わりに全ビット1として... 58 stencilReference = ~0 59 }; 60 61 // ステンシル値を読み取る・書き込むビットをstencilBitだけに制限しました 62 var stencilState = new StencilState(readMask: (byte)this.stencilBit, writeMask: (byte)this.stencilBit); 63 64 // マスク用・穴用についてそれぞれステンシル設定・デプス設定を編集し... 65 if (this.mask) 66 { 67 stencilState.SetPassOperation(StencilOp.Replace); 68 } 69 else 70 { 71 stencilState.SetCompareFunction(CompareFunction.Equal); 72 stateBlock.depthState = new DepthState(compareFunction: CompareFunction.Always); 73 } 74 stateBlock.stencilState = stencilState; 75 76 // レンダリングを実行 77 var renderConfig = ctx.hdCamera.frameSettings.IsEnabled(FrameSettingsField.Shadowmask) 78 ? HDUtils.GetBakedLightingWithShadowMaskRenderConfig() 79 : HDUtils.GetBakedLightingRenderConfig(); 80 var result = new RendererListDesc(forwardShaderTags, ctx.cullingResults, ctx.hdCamera.camera) 81 { 82 rendererConfiguration = renderConfig, 83 renderQueueRange = this.GetRenderQueueRange(this.queue), 84 sortingCriteria = this.sorting, 85 excludeObjectMotionVectors = false, 86 stateBlock = stateBlock, 87 layerMask = this.layerMask 88 }; 89 var renderCtx = ctx.renderContext; 90 CoreUtils.DrawRendererList(ctx.renderContext, ctx.cmd, renderCtx.CreateRendererList(result)); 91 } 92}

それをグローバルなCustom Pass Volumeにセットして穴マスクおよび穴の描画を担当させました。また、Obstaclesの追加描画にはDraw renderers Custom Passを使用しました。

図1

すみませんが、コード中のコメントでも申し上げたようにURPのFiltering→Opaque Layer Maskに相当するものを見つけられず、代わりにメインカメラのCulling Maskから穴レイヤーを除外しています。
ついでに穴マスクもメインのレンダリングパスで描画する必要はなさそうに思いまして、併せて除外しました。

図2

これらの処置を加えたところ、穴の見た目は下図のようになりました。

図3

引き続きチュートリアルを続行し、最終的に下図のような穴になりました。

図4

投稿2022/06/10 18:57

編集2022/06/10 18:59
Bongo

総合スコア10807

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

john9999

2022/06/10 22:44

丁寧なご回答ありがとうございます。 早速試してみましたが、いくつか分からなかったのでご教授ください。 ①HoleCustomPassのコードをそのまま流用しましたが、4行目の  using UnityEngine.Rendering.RendererUtils;  にて、「型または名前空間の名前 'RendererUtils' が名前空間 'UnityEngine.Rendering' に存在しません」のエラーになってしまいました。  名前空間についてあまり理解できておらず…、どのようにすれば解決できそうでしょうか? ②HoleCustomPass作成後の、「それをグローバルなCustom Pass Volumeにセット」が具体的にどのような操作でしょうか?
Bongo

2022/06/11 04:21 編集

①について すみませんでした。ご指摘を受けて確認してみましたら、ご質問者さんがお使いの2020.3.19f1の時点ではまだ正式導入されていない機能を使ってしまっていたようです。 まずコード冒頭の using UnityEngine.Rendering.RendererUtils; を using UnityEngine.Experimental.Rendering; に変更し、さらにExecuteメソッド末尾の var renderCtx = ctx.renderContext; CoreUtils.DrawRendererList(ctx.renderContext, ctx.cmd, renderCtx.CreateRendererList(result)); を CoreUtils.DrawRendererList(ctx.renderContext, ctx.cmd, RendererList.Create(result)); に変更してもう一度お試しいただけますでしょうか。 ②について あれは、まずご質問者さんがおっしゃった通りにメニューの「GameObject」→「Volume」→「Custom Pass」でカスタムパスボリュームをつくったのち、そのCustomPassVolumeコンポーネントの「Mode」を「Global」に設定することを意図しておりました。 「Local」の場合ですと、さらにオブジェクトにコライダーを付けることでコライダー内にカメラが侵入した場合だけカスタムパスが効果を発揮するように作ることもできるみたいですね。ですが、今回のケースは常時カスタムパスを実行してほしいので「Global」を選びました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問