<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Mesh on ながむしメモ</title><link>https://nagakagachi.github.io/categories/mesh/</link><description>Recent content in Mesh on ながむしメモ</description><generator>Hugo</generator><language>ja-JP</language><lastBuildDate>Sat, 31 Dec 2022 08:00:00 +0900</lastBuildDate><atom:link href="https://nagakagachi.github.io/categories/mesh/index.xml" rel="self" type="application/rss+xml"/><item><title>DepthPrepass有効時のCoplanar PolygonによるGPU負荷増大 [UE][Rendering]</title><link>https://nagakagachi.github.io/entry/2022/12/31/080000/</link><pubDate>Sat, 31 Dec 2022 08:00:00 +0900</pubDate><guid>https://nagakagachi.github.io/entry/2022/12/31/080000/</guid><description>&lt;p&gt;DepthPrepass&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%EC%A5%F3%A5%C0%A5%EA%A5%F3%A5%B0"&gt;レンダリング&lt;/a&gt;に関連して, &lt;br /&gt;モデルやレベルの作りによって&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/GPU"&gt;GPU&lt;/a&gt;負荷が増大してしまう特殊な状況について説明します.&lt;/p&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3 id="問題"&gt;問題&lt;/h3&gt;&#10;&lt;p&gt;同一平面で重なり合うポリゴン(&lt;em&gt;Coplanar Polygon&lt;/em&gt;)は, 重なりの数だけBasePass PixelShaderが実行される可能性があります.&lt;br /&gt;&lt;u&gt;これにより本来DepthPrepass環境で除去される不要なBasePass負荷が追加で発生します.&lt;/u&gt;&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;&lt;span style="font-size: 50%;"&gt;同一平面で重なり合うポリゴン を &lt;u&gt;Coplanar Polygon&lt;/u&gt; と呼んでいます.&lt;br /&gt;Lamina Faces や Z-Fighting状態のポリゴン というような表現もあると思います.&lt;br /&gt;もっと良い呼び名があれば教えてください!&lt;/span&gt;&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;p&gt;&lt;br /&gt;以下のサンプルシーンは&lt;u&gt;Opaque&lt;/u&gt;で適当ワールドノイズマテリアルのCubeをいくつか配置した状態です.&lt;br /&gt;よくOverDraw負荷が問題となる半透明が無いシーンなので安心と思いきや, 表示モードを「シェーダ複雑度」へ切り替えてみると.&lt;/p&gt;&#10;&lt;figure class="figure-image figure-image-fotolife" title="サンプルシーン"&gt;&lt;img src="images/c272dc256ecc74375b4877e418f9aece697a71c86bd6127d341d415a59f7952a.png" width="1200" height="819" loading="lazy" title="" class="hatena-fotolife" style="width: 250px;" itemprop="image" /&gt; &lt;img src="images/a677d850b9bfe572bc8a5c7266cf9e69dddd2dcab9c69a6e33f03b69da90597a.png" width="1200" height="814" loading="lazy" title="" class="hatena-fotolife" style="width: 250px;" itemprop="image" /&gt;&#10;&lt;figcaption&gt;サンプルシーン&lt;/figcaption&gt;&#10;&lt;/figure&gt;&#10;&lt;p&gt;&lt;u&gt;何故か高負荷を示す真っ白な部分があります&lt;/u&gt;.&lt;/p&gt;&#10;&lt;p&gt;RenderDocでキャプチャして 「&lt;u&gt;Quad Over Draw (Pass)&lt;/u&gt;」でOverDrawを確認します.&lt;/p&gt;&#10;&lt;figure class="figure-image figure-image-fotolife" title="RenderDoc Quad Over Draw (Pass)"&gt;&lt;img src="images/5581b84e591e4b8ad0c9549404a169faf37c5f1d03c470168dc9ee1e23b48d5a.png" width="1020" height="666" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /&gt;&#10;&lt;figcaption&gt;RenderDoc Quad Over Draw (Pass)&lt;/figcaption&gt;&#10;&lt;/figure&gt;&#10;&lt;p&gt;RenderDoc上でも確かに右側の配置でBasePassのOverDrawが発生しているようです.&lt;/p&gt;&#10;&lt;p&gt;BasePassではDeferredの場合はGBuffer書き込み, Forwardであれば複雑なLighting計算が実行されるため,本来実行されないはずのOpaqueでのBasePass OverDrawは&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/GPU"&gt;GPU&lt;/a&gt;負荷に大きな影響を与えます.&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3 id="原因"&gt;原因&lt;/h3&gt;&#10;&lt;p&gt;この問題の原因は深度が完全に一致するポリゴンが複数重なっている点と, DepthPrepass有りBasePassの仕組みの関係によるものです.&lt;/p&gt;&#10;&lt;p&gt;まずシーンの配置ですが, 左側の配置と同じ3つのCubeをポリゴンが重なるように配置しています &lt;a href="#f-9dd25646" id="fn-9dd25646" name="fn-9dd25646" title="1モデル内のポリゴン同士でも, レベルに配置した別モデルのポリゴン同士でも関係なくこの問題は発生します."&gt;*1&lt;/a&gt;.&lt;br /&gt;&lt;img src="images/86f7777de4998b3ffd7e612339bc77651597f293595d2c33f3f21683589a12c9.png" width="1200" height="817" loading="lazy" title="" class="hatena-fotolife" style="width: 250px;" itemprop="image" /&gt; &lt;img src="images/c48411fd5c3bc351c2e59974c39d4469d52a31f9e23dbb2a29b1f67fa3b605fb.png" width="1200" height="813" loading="lazy" title="" class="hatena-fotolife" style="width: 250px;" itemprop="image" /&gt;&lt;/p&gt;&#10;&lt;p&gt;このような状況では, DepthPrepass有効時のBasePassは重なり合ったポリゴンそれぞれについて全て実行されてしまい, 高負荷なBasePassが何度も実行されることにより&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/GPU"&gt;GPU&lt;/a&gt;負荷を増大させます.&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3 id="BasePassが複数回実行される理由"&gt;BasePassが複数回実行される理由&lt;/h3&gt;&#10;&lt;p&gt;本来のDepthPrepass手法は, DepthPreapssで先に生成したDepthBufferを頼りに, 各Meshの可視&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%D4%A5%AF%A5%BB%A5%EB"&gt;ピクセル&lt;/a&gt;のマテリアルBasePass PixelShaderだけを最小限実行することで高速化するためのものです.&lt;br /&gt;例として背景, 円柱, 板で構成されたシーンのDepthPrepass有りBasePassの挙動を以下に示します.&lt;br /&gt;右側図の緑色部分がDepthTestを通過してBasePassのPixelShaderが実行された&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%D4%A5%AF%A5%BB%A5%EB"&gt;ピクセル&lt;/a&gt;になります.&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;DepthPrepassでDepthBufferが完成&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;img src="images/59936b850442a7a395812d241e30d7fbdf9a56980124ad6698d1b70727d32ba8.png" width="1070" height="714" loading="lazy" title="" class="hatena-fotolife" style="width: 250px;" itemprop="image" /&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;円柱モデルBasePass描画&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;img src="images/0a300dab9c592601ce13587e02a2a295ec8497277f6896b50f330d7bd3997ca2.png" width="1068" height="711" loading="lazy" title="" class="hatena-fotolife" style="width: 250px;" itemprop="image" /&gt; &lt;img src="images/a43c6b573e3814646727af503df327c0499aa2723e377fab7ca90b0df466c219.png" width="1069" height="713" loading="lazy" title="" class="hatena-fotolife" style="width: 250px;" itemprop="image" /&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;背景モデルBasePass描画&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;img src="images/a51f5fb7597a3719fb354d1e0cada8730dccd901c7346a72f6e4c0744198105a.png" width="1070" height="714" loading="lazy" title="" class="hatena-fotolife" style="width: 250px;" itemprop="image" /&gt; &lt;img src="images/803ab8d758963f5b703032bfb6984ce851646438c5a167151baefa3f2d22dc78.png" width="1069" height="712" loading="lazy" title="" class="hatena-fotolife" style="width: 250px;" itemprop="image" /&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;板モデルBasePass描画&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;img src="images/536d0d26f787eb50b831f285ab440bd31a185067995c2c3b24adf697416e7c76.png" width="1071" height="712" loading="lazy" title="" class="hatena-fotolife" style="width: 250px;" itemprop="image" /&gt; &lt;img src="images/3269379750a785f5ea7673a9ba4273e00a4526ccb8514482654abfa5c4fce4ff.png" width="1070" height="712" loading="lazy" title="" class="hatena-fotolife" style="width: 250px;" itemprop="image" /&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;各モデルのBasePassが, 最終的に画面に見えている部分でだけ働いているのがわかると思います.&lt;br&gt;&#10;このようにBasePassが無駄に実行されないようにして高速化するというのがDepthPrepassの目的となります.&lt;/p&gt;&#10;&lt;p&gt;これを実現するためにBasePassは&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;DepthWrite=OFF 且つ DepthTest=GreaterEqual&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;p&gt;という設定をされます &lt;a href="#f-9b586fdf" id="fn-9b586fdf" name="fn-9b586fdf" title="GreaterEqualなのはReverseZ環境でのことで, StandardZの場合はLessEqualです."&gt;*2&lt;/a&gt;.&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;&lt;span style="font-size: 80%;"&gt;指摘がありましたので追記-&amp;gt; Maskedを含めたマテリアルをDepthPrePassを利用してEarlyZ有効で効率的に描画するために Equal なDepthTestで描画する場合があります. 本件のシーンではOpaqueを対象とし且つRenderDocキャプチャ等も確認したところGreaterEqualであったためこのように記述しています(UE5.3).&lt;/span&gt;&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;p&gt;この設定によって, 各モデルのBasePass描画では&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;DepthPrepassで確定した深度値に対して&lt;br /&gt;&lt;u&gt;&lt;strong&gt;同じか&lt;/strong&gt;&lt;/u&gt;それより近い場合にのみ描画する&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;p&gt;という挙動をすることになります.&lt;/p&gt;&#10;&lt;p&gt;この &lt;u&gt;&lt;strong&gt;同じかそれより近い&lt;/strong&gt;&lt;/u&gt; という点と, 深度が完全に一致してしまう Coplanar Polygon の関係によって今回のような問題が起きています.&lt;/p&gt;&#10;&lt;/div&gt;</description></item><item><title>Voxel Mesh化手法についてメモ( Voxel Meshing )</title><link>https://nagakagachi.github.io/entry/2020/08/22/180515/</link><pubDate>Sat, 22 Aug 2020 18:05:15 +0900</pubDate><guid>https://nagakagachi.github.io/entry/2020/08/22/180515/</guid><description>&lt;p&gt;SDFなどのVoxelからMeshを生成する手法のメモ。&lt;/p&gt;&#10;&lt;p&gt;もとのSDFのセルと、Mesh化で管理されるVoxelは一致しないので注意。&lt;/p&gt;&#10;&lt;p&gt;もとのSDFのセル中心を頂点とするようなVoxel上でMesh化が実行される。&lt;/p&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3 id="marching--cubes"&gt;Marching Cubes&lt;/h3&gt;&#10;&lt;p&gt;&lt;a href="http://paulbourke.net/geometry/polygonise/"&gt;Polygonising a scalar field (Marching Cubes)&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;Voxelの頂点のパターンからそのVoxelのポリゴンパターンをLookupしてMesh化する。&lt;/p&gt;&#10;&lt;p&gt;シャープな形状が作りにくいらしい。&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3 id="dual-contour"&gt;Dual Contour&lt;/h3&gt;&#10;&lt;p&gt;&lt;a href="https://people.eecs.berkeley.edu/~jrs/meshpapers/SchaeferWarren2.pdf"&gt;https://people.eecs.berkeley.edu/~jrs/meshpapers/SchaeferWarren2.pdf&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;あるVoxelを構成する辺について、SDFをの符号が異なる両端を持つ辺に注目し、辺を横切るような等値面の交差位置と法線をSDFの勾配等から計算する。&lt;/p&gt;&#10;&lt;p&gt;一つのVoxelについて境界面は複数存在する可能性があり、すべての境界面からの距離の自乗和が最小になるような一点をそのVoxel内の頂点として最小二乗法で推定する。&lt;/p&gt;&#10;&lt;p&gt;すべてのVoxelについて上記の点を計算し、隣接Cellで点同士をつなげてMeshを構成する。&lt;/p&gt;&#10;&lt;p&gt;シャープな形状を作ることができるらしい。&lt;/p&gt;&#10;&lt;p&gt;Voxel毎に最小二乗法を解く必要があるためコストが高い可能性。&lt;/p&gt;&#10;&lt;p&gt;また自己交差メッシュができてしまう可能性もある。&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3 id="surfacenets"&gt;SurfaceNets&lt;/h3&gt;&#10;&lt;p&gt;&lt;a href="https://www.merl.com/publications/docs/TR99-24.pdf"&gt;https://www.merl.com/publications/docs/TR99-24.pdf&lt;/a&gt;&lt;br /&gt;&#10;&lt;a href="https://medium.com/@bonsairobo/smooth-voxel-mapping-a-technical-deep-dive-on-real-time-surface-nets-and-texturing-ef06d0f8ca14"&gt;Smooth Voxel Mapping: a Technical Deep Dive on Real-time Surface Nets and Texturing | by DreamCat Games | Aug, 2020 | Medium&lt;/a&gt;&lt;br /&gt;&#10;&lt;a href="https://github.com/TomaszFoster/NaiveSurfaceNets/blob/master/NaiveSurfaceNets.cs"&gt;NaiveSurfaceNets/NaiveSurfaceNets.cs at master &amp;middot; TomaszFoster/NaiveSurfaceNets &amp;middot; GitHub&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&#10;&lt;p&gt;Meshを構成するVoxel内の頂点を推定することはDual Contourと同様だが、複数ある辺と等値面の交差位置を平均した地点を頂点位置とするところが異なる。&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;hr&gt;&#10;&lt;p&gt;&lt;a href="https://nagakagachi.hatenablog.com/entry/2020/08/22/180515"&gt;元のはてなブログ記事&lt;/a&gt;&lt;/p&gt;</description></item></channel></rss>