<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>GPGPU on ながむしメモ</title><link>https://nagakagachi.github.io/categories/gpgpu/</link><description>Recent content in GPGPU on ながむしメモ</description><generator>Hugo</generator><language>ja-JP</language><lastBuildDate>Sat, 16 Dec 2023 16:11:44 +0900</lastBuildDate><atom:link href="https://nagakagachi.github.io/categories/gpgpu/index.xml" rel="self" type="application/rss+xml"/><item><title>【UE5】Niagara SimulationStageでNormalMapからHeightMapを復元する(Poisson方程式)</title><link>https://nagakagachi.github.io/entry/2023/12/16/161144/</link><pubDate>Sat, 16 Dec 2023 16:11:44 +0900</pubDate><guid>https://nagakagachi.github.io/entry/2023/12/16/161144/</guid><description>&lt;p&gt;&lt;span&gt;&lt;style&gt;&#10;img{&#10;display: inline-block;&#10;box-sizing: border-box;&#10;border: solid 1px #333;&#10;}&#10;&lt;/style&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/Unreal%20Engine"&gt;Unreal Engine&lt;/a&gt; Advent Calendar 2023 の16日の記事です. &lt;a href="https://qiita.com/advent-calendar/2023/ue"&gt;Unreal Engine (UE)&amp;#x306E;&amp;#x30AB;&amp;#x30EC;&amp;#x30F3;&amp;#x30C0;&amp;#x30FC; | Advent Calendar 2023 - Qiita&lt;/a&gt;&lt;/p&gt;&lt;p&gt;最近HoudiniでNormalMapからHeightMapを復元するというものを見かけ,&lt;br /&gt;&#10;Poisson方程式を解くのであればSimulationStageで実装することができるのではと考えました.&lt;blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"&gt;&lt;p lang="ja" dir="ltr"&gt;というわけで、&lt;a href="https://twitter.com/TearsOfJake?ref_src=twsrc%5Etfw"&gt;@TearsOfJake&lt;/a&gt; さんのアド&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9"&gt;バイス&lt;/a&gt;を元に、 &lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%DD%A5%A2%A5%BD%A5%F3%CA%FD%C4%F8%BC%B0"&gt;ポアソン方程式&lt;/a&gt;を用いたノーマルマップからハイトマップの復元。昨日の勾配のみの復元に比べて圧倒的に安定している。 &lt;br&gt;左：入力メッシュ &lt;br&gt;中：入力メッシュから求めたノーマルマップ&lt;br&gt;右：ノーマルマップから復元した高さ情報 &lt;a href="https://t.co/NiNyVvvrbS"&gt;pic.twitter.com/NiNyVvvrbS&lt;/a&gt;&lt;/p&gt;&amp;mdash; &lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/Akira"&gt;Akira&lt;/a&gt; Saito (@a_saito) &lt;a href="https://twitter.com/a_saito/status/1721076487150084376?ref_src=twsrc%5Etfw"&gt;2023年11月5日&lt;/a&gt;&lt;/blockquote&gt; &lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt; &lt;/p&gt;&lt;br /&gt;&#10;&lt;p&gt;この記事では「NormalMapからHeightMapを復元する」という問題をSimulationStageで実装する方法を紹介します.&lt;br /&gt;&#10;サンプルプロジェクトは以下のGoogleDriveになります (動作確認バージョン UE5.3).&lt;br /&gt;&#10;&lt;a href="https://drive.google.com/file/d/13X7s09O3bYuvWyIRp3HkDaNOcjrpnOdy/view?usp=sharing"&gt;ReconstructHeightMapFromNormal.zip - Google &amp;#x30C9;&amp;#x30E9;&amp;#x30A4;&amp;#x30D6;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/811419472fa7cff90fd29f512ec692d5e3a1ed029c96a017cf78f1c960ef9310.png" width="1200" height="657" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;/p&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3 id="Niagara-SimulationStage"&gt;&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/Niagara"&gt;Niagara&lt;/a&gt; SimulationStage&lt;/h3&gt;&#10;&lt;p&gt;&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/Niagara"&gt;Niagara&lt;/a&gt; SimulationStage はComputeShader的な&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/GPGPU"&gt;GPGPU&lt;/a&gt;処理を&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/Niagara"&gt;Niagara&lt;/a&gt;モジュールとして作成できる仕組みです.&lt;br /&gt;&#10;&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/Epic%20Games"&gt;Epic Games&lt;/a&gt;公式の&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/Niagara"&gt;Niagara&lt;/a&gt; Fluids等でも多用されています(本当にSimulationStageでほとんどの処理が作られています まじかよ).&lt;/p&gt;&lt;p&gt;SimulationStage は2D/3Dのグリッド構造に対する&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/GPGPU"&gt;GPGPU&lt;/a&gt;処理を比較的簡単に作ることができるように設計されています.&lt;br /&gt;&#10;これには数値シミュレーションで必要とされる反復実行なども含まれています.&lt;br /&gt;&#10;目的のタスクを適切な形に変形してSimulationStageで実装することで, &lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/GPU"&gt;GPU&lt;/a&gt;による高速な実行が可能になります.&lt;br /&gt;&#10;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/f98da2e455903354e0d62a7fb3506e1d0408098ff6cc774991c5c248069f90f1.png" width="1200" height="816" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3 id="NormalMapからHeightMapを復元する問題"&gt;NormalMapからHeightMapを復元する問題&lt;/h3&gt;&#10;&lt;/div&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3 id="Poisson方程式"&gt;Poisson方程式&lt;/h3&gt;&#10;&lt;p&gt;ある関数の二階の空間&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/%C8%F9%CA%AC"&gt;微分&lt;/a&gt;と別の関数との関係式をPoisson方程式といいます.&lt;br /&gt;&#10;Poisson方程式は離散化によって連立一次方程式へ変形することができ, 連立一次方程式を解く方法は様々に研究されています.&lt;br /&gt;&#10;対象の問題をPoisson方程式, ひいては連立一次方程式の形にすることができれば, Solverや解法を利用して解くことができます.&lt;/p&gt;&lt;p&gt;&lt;span class="math-inline"&gt;\(\Delta \phi =-\dfrac{\rho}{\epsilon_0}\)&lt;/span&gt;&lt;br /&gt;&#10;&lt;/p&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h4 id="Poisson方程式への変形"&gt;Poisson方程式への変形&lt;/h4&gt;&#10;&lt;p&gt;今回は NormalMapとHeightMapの関係をPoisson方程式で表現して離散化, 連立一次方程式として解くことにします.&lt;/p&gt;&#10;&lt;p&gt;NormalMapのxy成分はHeightMapの空間&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/%C8%F9%CA%AC"&gt;微分&lt;/a&gt;(勾配)から求められます.&lt;br /&gt;&#10;&lt;span class="math-inline"&gt;\(N_x(x,y)= -\dfrac { \partial H(x,y)}{\partial x}\)&lt;/span&gt;&lt;br /&gt;&#10;&lt;span class="math-inline"&gt;\(N_y(x,y)= -\dfrac { \partial H(x,y)}{\partial y}\)&lt;/span&gt;&lt;br /&gt;&#10;さらにそれぞれ x, y で&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/%CA%D0%C8%F9%CA%AC"&gt;偏微分&lt;/a&gt;します.&lt;/p&gt;&lt;p&gt;&lt;span class="math-inline"&gt;\(\dfrac {\partial N_x(x,y)}{\partial x}= -\dfrac { \partial^2 H(x,y)}{\partial x^2}\)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span class="math-inline"&gt;\(\dfrac {\partial N_y(x,y)}{\partial y}= -\dfrac { \partial^2 H(x,y)}{\partial y^2}\)&lt;/span&gt;&lt;br /&gt;&#10;ここで上の式はPoisson方程式の形になっています.&lt;/p&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h5 id="差分方程式"&gt;差分方程式&lt;/h5&gt;&#10;&lt;p&gt;このPoisson方程式を離散化すると以下のようになります.&lt;br /&gt;&#10;(&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/%C5%EC%B3%A4%C2%E7%B3%D8"&gt;東海大学&lt;/a&gt;理学部遠藤研究室さんのページ等がわかりやすいです. -&gt; &lt;a href="https://teamcoil.sp.u-tokai.ac.jp/lectures/EL1/Poisson/index.html"&gt;&amp;#x96FB;&amp;#x78C1;&amp;#x5834;(SP)&lt;/a&gt; )&lt;/p&gt;&lt;p&gt;&lt;span class="math-inline"&gt;\(\frac {N_x(x+h,y) - N_x(x-h,y)}{2h}= -\frac {H(x+h,y)+H(x-h,y) - 2H(x,y)}{h^2}\)&lt;/span&gt;&lt;br /&gt;&#10;&lt;span class="math-inline"&gt;\(\frac {N_x(x,y+h) - N_x(x,y-h)}{2h}= -\frac {H(x,y+h)+H(x,y-h) - 2H(x,y)}{h^2}\)&lt;/span&gt;&lt;br /&gt;&#10;(左辺は中心差分)&lt;/p&gt;&lt;p&gt;2つの式を足して左辺のNormalMap, 右辺にHeightMapに関わる項をまとめて整理します.&lt;br /&gt;&#10;またテクセルでの&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/%C8%F9%CA%AC"&gt;微分&lt;/a&gt;(差分)のため &lt;span class="math-inline"&gt;\(h = 1\)&lt;/span&gt; とします.&lt;br /&gt;&#10;&lt;span class="math-inline"&gt;\(- \frac {N_x(x+1,y) - N_x(x-1,y) + N_x(x,y+1) - N_x(x,y-1)}{2} \\= H(x+1,y)+H(x-1,y) + H(x,y+1)+H(x,y-1) - 4H(x,y)\)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;上の式の左辺は入力NormalMapとして与えられる既知の値, 右辺は求めたいHeightMapのいくつかの地点の値に係数をかけたものの和です.&lt;br /&gt;&#10;よってこれは左辺を定数&lt;span class="math-inline"&gt;\(b\)&lt;/span&gt;, 未知のHeightMapを&lt;span class="math-inline"&gt;\(x\)&lt;/span&gt;, 近傍HeightMap値への係数を行列&lt;span class="math-inline"&gt;\(A\)&lt;/span&gt;とした連立一次方程式ということになります.&lt;br /&gt;&#10;&lt;span class="math-inline"&gt;\(b = Ax\)&lt;/span&gt;&lt;/p&gt;&#10;&lt;p&gt;連立一次方程式を解くために更に変形していきます.&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h5 id="Jacobi法"&gt;Jacobi法&lt;/h5&gt;&#10;&lt;p&gt;見通しをよくするために左辺は記号で置き換えておきます.&lt;br /&gt;&#10;&lt;span class="math-inline"&gt;\(-N_{d} = H(x+1,y)+H(x-1,y) + H(x,y+1)+H(x,y-1) - 4H(x,y)\)&lt;/span&gt; &lt;br /&gt;&#10;(ここで &lt;span class="math-inline"&gt;\(N_{d} =\frac {N_x(x+1,y) - N_x(x-1,y) + N_x(x,y+1) - N_x(x,y-1)}{2}\)&lt;/span&gt; )&lt;/p&gt;&lt;p&gt;&lt;span class="math-inline"&gt;\(H(x,y)\)&lt;/span&gt; に関する形に変形します.&lt;/p&gt;&lt;p&gt;&lt;span class="math-inline"&gt;\(H(x,y) = \frac{(H(x+1,y)+H(x-1,y)+H(x,y+1)+H(x,y-1)) + N_{d} }{4}\)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;この式を反復的に計算することで &lt;span class="math-inline"&gt;\(H(x,y)\)&lt;/span&gt; を解に近づけていく方法をJacobi法といいます.&lt;br /&gt;&#10;プログラム的に考えると&lt;strong&gt;HeightMapの各テクセルについて上下左右の近傍値とNormalMapの値を使って更新&lt;/strong&gt;しているといえます.&lt;br /&gt;&#10;現在のHeightMapから次のHeightMapの各テクセルを並列に計算できるため&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/GPGPU"&gt;GPGPU&lt;/a&gt;とも相性が良いです.&lt;br /&gt;&#10;次はJacobi法によるHeightMapの計算を&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/Niagara"&gt;Niagara&lt;/a&gt; SimulationStageで実装します.&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;</description></item><item><title>UE5 Geometry Script を利用した頂点単位リアルタイムアニメーション</title><link>https://nagakagachi.github.io/entry/2022/10/02/194137/</link><pubDate>Sun, 02 Oct 2022 19:41:37 +0900</pubDate><guid>https://nagakagachi.github.io/entry/2022/10/02/194137/</guid><description>&lt;p&gt;Geometry Scriptの利用の一環で&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;入力メッシュの頂点インデックスをUV1に埋め込み、外部テクスチャに頂点座標をベイク&lt;/li&gt;&#10;&lt;li&gt;上記で生成したメッシュとテクスチャを利用してマテリアルで頂点単位バネアニメーション&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;というものを試してみました&lt;/p&gt;&#10;&lt;p&gt;&lt;blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"&gt;&lt;p lang="ja" dir="ltr"&gt;realtime fake secondary motion (WIP.&lt;br&gt;position, rotation, and scale operations in editor mode.&lt;br&gt;&lt;br&gt;Editorモードでの位置とスケールの操作プレビュー対応まで.&lt;br&gt;&lt;br&gt;あとプルプルしすぎていたので更に調整.&lt;a href="https://twitter.com/hashtag/UE5?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#UE5&lt;/a&gt; &lt;a href="https://t.co/xgzYPtIGpw"&gt;pic.twitter.com/xgzYPtIGpw&lt;/a&gt;&lt;/p&gt;&amp;mdash; なが (@nagakagachi) &lt;a href="https://twitter.com/nagakagachi/status/1561311962805719040?ref_src=twsrc%5Etfw"&gt;2022年8月21日&lt;/a&gt;&lt;/blockquote&gt; &lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt; &lt;/p&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3 id="サンプル"&gt;サンプル&lt;/h3&gt;&#10;&lt;p&gt;レベルに配置されている BP_ControllerInEditorTick を動かすとプルプルします.&lt;br /&gt;&#10;Playを実行すると物理で動くモデルがプルプルします.&lt;br /&gt;&#10;&lt;iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fnagakagachi%2Fue4%2Ftree%2Fmaster%2Fproject%2Fsample%2FPerVtxAnimSample" title="ue4/project/sample/PerVtxAnimSample at master · nagakagachi/ue4" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"&gt;&lt;/iframe&gt;&lt;cite class="hatena-citation"&gt;&lt;a href="https://github.com/nagakagachi/ue4/tree/master/project/sample/PerVtxAnimSample"&gt;github.com&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3 id="構成"&gt;構成&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;BP_GenerateMeshForPerVertexAnim&#10;&lt;ul&gt;&#10;&lt;li&gt;入力StaticMeshアセットから以下のようなアセットを生成する&#10;&lt;ul&gt;&#10;&lt;li&gt;UV1に頂点インデックスを埋め込んだStaticMesh&lt;/li&gt;&#10;&lt;li&gt;頂点インデックスに対応したテクセルにローカル頂点座標をベイクしたテクスチャ&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;li&gt;BP_PerVertexAnimationTest&#10;&lt;ul&gt;&#10;&lt;li&gt;上記で生成したMeshとテクスチャを利用して頂点単位バネシミュレーションをマテリアル(&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/GPU"&gt;GPU&lt;/a&gt;)で計算する&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;li&gt;BP_ControllerInEditorTick&#10;&lt;ul&gt;&#10;&lt;li&gt;Editorモードのマニピュレータ操作でバネシミュをプレビューするためのコントローラ&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/div&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3 id="導入"&gt;導入&lt;/h3&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h4 id="プロジェクトで-Geometry-Script-プラグインを有効化"&gt;プロジェクトで Geometry Script &lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%E9%A5%B0%A5%A4%A5%F3"&gt;プラグイン&lt;/a&gt;を有効化&lt;/h4&gt;&#10;&lt;p&gt;編集/&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%E9%A5%B0%A5%A4%A5%F3"&gt;プラグイン&lt;/a&gt;エディタから Geometry Script の&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C1%A5%A7%A5%C3%A5%AF%A5%DC%A5%C3%A5%AF%A5%B9"&gt;チェックボックス&lt;/a&gt;をONにする&lt;br /&gt;&#10;必要ならEditorの再起動をする&lt;br /&gt;&#10;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/6180d11068fdae02c349a7e467eed72ac958f509a59859185abd883f9cd767a9.png" width="1200" height="297" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;br /&gt;&#10;&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h4 id="PerVtxAnimWithGeometryScriptを取り込み"&gt;PerVtxAnimWithGeometryScriptを取り込み&lt;/h4&gt;&#10;&lt;p&gt;Window&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%AF%A5%B9%A5%D7%A5%ED%A1%BC%A5%E9"&gt;エクスプローラ&lt;/a&gt;上などからプロジェクトのContentフォルダにサンプルの&lt;br /&gt;&#10;PerVtxAnimWithGeometryScriptフォルダ&lt;br /&gt;&#10;をコピー&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h4 id="生成用サンプルアクター-をレベルに配置"&gt;生成用サンプルアクター をレベルに配置&lt;/h4&gt;&#10;&lt;p&gt;BP_GenerateMeshForPerVertexAnim をレベルに配置&lt;br /&gt;&#10;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/30f9d9a8b24a648be093b5061ca7a42e20b81b7b61e41ca6d7e617866b48fbdc.png" width="1200" height="843" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;br /&gt;&#10;&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h4 id="生成用サンプルアクターにアセットを設定"&gt;生成用サンプルアクターにアセットを設定&lt;/h4&gt;&#10;&lt;p&gt;BP_GenerateMeshForPerVertexAnimアクターに変換元Mesh, 出力先Mesh &amp; RenderTargetを設定&lt;br /&gt;&#10;Sm Src Mesh に変換元のStaticMeshを設定, 図は同梱しているウシモデル(Spot)を設定している様子&lt;br /&gt;&#10;&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/Tex"&gt;Tex&lt;/a&gt; Bake Position Target にベイク情報を出力するRenderTargetを設定&lt;br /&gt;&#10;Sm Bake Target に変換結果のMeshを出力するStaticMeshを設定&lt;br /&gt;&#10;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/a199ba136831e36a6a91fb45f179cc246799957a3bf072481fc714f27b8f6212.png" width="1200" height="671" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h4 id="アセット生成"&gt;アセット生成&lt;/h4&gt;&#10;&lt;p&gt;Geometry Scritpが駆動して Sm Bake Target と &lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/Tex"&gt;Tex&lt;/a&gt; Bake Position Target のアセットに生成物が保存される&lt;br /&gt;&#10;Geometry Scritpはアクターのパラメータ変更等で駆動するため, 位置の変更や Enable Regenerate Mesh のONOFF等でトリガーされる&lt;/p&gt;&lt;p&gt;Sm Bake Target にはUV1に頂点インデックスを埋め込んだStaticMeshが出力される&lt;br /&gt;&#10;&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/Tex"&gt;Tex&lt;/a&gt; Bake Position Target には頂点インデックスに対応するテクセルに頂点座標がベイクされたテクスチャが出力される&lt;br /&gt;&#10;これらのアセットを利用してリアルタイムに頂点単位アニメーションを実現する&lt;br /&gt;&#10;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/1ba5eec862176e4d55fcef6e798612f79ba89b294c3feb723d08cebe0540e1f8.png" width="448" height="326" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;br /&gt;&#10;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/438e48343ffd19bd28e794c25208bb01781560b964ac51fb8e019b669698fcc4.png" width="794" height="672" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h4 id="ランタイムサンプルアクターをレベルに配置"&gt;ランタイムサンプルアクターをレベルに配置&lt;/h4&gt;&#10;&lt;p&gt;BP_PerVertexAnimationTest は 上記アクターで生成されたメッシュとテクスチャを利用するサンプル&lt;br /&gt;&#10;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/fc8bde70344bbc575f4f192547e6b9ddd8181b2cd78f0636d8a0dc0e82c46944.png" width="1200" height="864" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;br /&gt;&#10;&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h4 id="ランタイムサンプルアクターにアセットを設定"&gt;ランタイムサンプルアクターにアセットを設定&lt;/h4&gt;&#10;&lt;p&gt;BP_PerVertexAnimationTest で生成されたメッシュとテクスチャをそれぞれ&lt;br /&gt;&#10;Mesh Vtx Attr Baked と &lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/Tex"&gt;Tex&lt;/a&gt; Vtx Attr 0 に設定&lt;br /&gt;&#10;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/740c759d4da7216bb8b008e247a4e476ea1a58c0e17efb105f46bf7273ba15ae.png" width="1200" height="663" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;</description></item><item><title>InstantNeRFで任意画像から3D再構成をするまでの流れメモ</title><link>https://nagakagachi.github.io/entry/2022/08/06/184349/</link><pubDate>Sat, 06 Aug 2022 18:43:49 +0900</pubDate><guid>https://nagakagachi.github.io/entry/2022/08/06/184349/</guid><description>&lt;p&gt;&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/NVIDIA"&gt;NVIDIA&lt;/a&gt; InstantNeRF (InstantNGP) の環境セットアップと,&lt;br /&gt;&#10;自身で用意した画像群を使った3D再構成をするフローのメモ.&lt;/p&gt;&lt;p&gt;基本的に公式&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA"&gt;リポジトリ&lt;/a&gt;のセットアップ手順そのまま.&lt;br /&gt;&#10;&lt;iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2FNVlabs%2Finstant-ngp" title="GitHub - NVlabs/instant-ngp: Instant neural graphics primitives: lightning fast NeRF and more" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"&gt;&lt;/iframe&gt;&lt;cite class="hatena-citation"&gt;&lt;a href="https://github.com/NVlabs/instant-ngp"&gt;github.com&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;&#10;&lt;ul class="table-of-contents"&gt;&#10;&lt;li&gt;&lt;a href="#セットアップ"&gt;セットアップ&lt;/a&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;a href="#実行環境"&gt;実行環境&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#Requirementsのセットアップ"&gt;Requirementsのセットアップ&lt;/a&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;a href="#CUDA"&gt;CUDA&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#CMAKE"&gt;CMAKE&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#Python"&gt;Python&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#Python-Modules"&gt;Python Modules&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#OptiX"&gt;OptiX&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#InstantNgpのビルド"&gt;InstantNgpのビルド&lt;/a&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;a href="#リポジトリの取得"&gt;リポジトリの取得&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#ビルド"&gt;ビルド&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#サンプルを実行"&gt;サンプルを実行&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#3D再構成の準備"&gt;3D再構成の準備&lt;/a&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;a href="#COLMAP"&gt;COLMAP&lt;/a&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;a href="#ダウンロード"&gt;ダウンロード&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#環境変数Pathへの追加"&gt;環境変数Pathへの追加&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#3D再構成"&gt;3D再構成&lt;/a&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;a href="#画像ファイルの準備"&gt;画像ファイルの準備&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#COLMAPによる画像群カメラ姿勢推定"&gt;COLMAPによる画像群カメラ姿勢推定&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#InstantNeRFを実行"&gt;InstantNeRFを実行&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3 id="セットアップ"&gt;セットアップ&lt;/h3&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h4 id="実行環境"&gt;実行環境&lt;/h4&gt;&#10;&lt;p&gt;WIndows10 64bit&lt;/p&gt;&#10;&lt;p&gt;RTX 3070&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h4 id="Requirementsのセットアップ"&gt;Requirementsのセットアップ&lt;/h4&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h5 id="CUDA"&gt;CUDA&lt;/h5&gt;&#10;&lt;p&gt;"v10.2 or higher"&lt;br /&gt;&#10;11.7 をインストール.&lt;br /&gt;&#10;&lt;iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fdeveloper.nvidia.com%2Fcuda-toolkit" title="CUDA Toolkit - Free Tools and Training" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"&gt;&lt;/iframe&gt;&lt;cite class="hatena-citation"&gt;&lt;a href="https://developer.nvidia.com/cuda-toolkit"&gt;developer.nvidia.com&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;</description></item><item><title> UE4マテリアルによるDistanceField生成(Jump Floodingアルゴリズム)</title><link>https://nagakagachi.github.io/entry/2021/11/07/231935/</link><pubDate>Sun, 07 Nov 2021 23:19:35 +0900</pubDate><guid>https://nagakagachi.github.io/entry/2021/11/07/231935/</guid><description>&lt;blockquote&gt;&#10;&lt;p&gt;2023/12/16更新&lt;br /&gt;&#10;SDF生成ツールをUE5向けに公開しました.&lt;blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"&gt;&lt;p lang="ja" dir="ltr"&gt;SDFテクスチャをテクスチャ2Dから生成するUE5上のツール. &lt;br&gt;別の作業のために生えてきた. Jump Floodingを&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/GPU"&gt;GPU&lt;/a&gt;(マテリアル)で実行.&lt;br&gt;&lt;br&gt;入力テクスチャは黒かそうでないかで外部/内部扱いしたSDF計算. 出力は RチャンネルにUV距離, Gチャンネルに内部フラグ. MIT License &lt;a href="https://twitter.com/hashtag/UE5?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#UE5&lt;/a&gt; &lt;a href="https://t.co/6GdbEja9o3"&gt;https://t.co/6GdbEja9o3&lt;/a&gt; &lt;a href="https://t.co/ogWdxzP5Xm"&gt;pic.twitter.com/ogWdxzP5Xm&lt;/a&gt;&lt;/p&gt;&amp;mdash; なが (@nagakagachi) &lt;a href="https://twitter.com/nagakagachi/status/1730982828358390040?ref_src=twsrc%5Etfw"&gt;2023年12月2日&lt;/a&gt;&lt;/blockquote&gt; &lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt; &lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;p&gt;サンプルプロジェクト有 (&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/UE4"&gt;UE4&lt;/a&gt;.27).&lt;/p&gt;&lt;p&gt;Jump Flooding &lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A2%A5%EB%A5%B4%A5%EA%A5%BA%A5%E0"&gt;アルゴリズム&lt;/a&gt;によるDistanceField生成をUEマテリアルで実装したメモ.&lt;br /&gt;&#10;ついでに Editor Utility &lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/Widget"&gt;Widget&lt;/a&gt; でSeedテクスチャの生成とDistanceFieldの生成をトリガーするテスト.&lt;/p&gt;&lt;p&gt;Jump Flooding Algorithm (&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/JFA"&gt;JFA&lt;/a&gt;)の詳細については各種資料参照.&lt;br /&gt;&#10;&lt;a href="https://www.comp.nus.edu.sg/~tants/jfa/i3d06.pdf"&gt;https://www.comp.nus.edu.sg/~tants/jfa/i3d06.pdf&lt;/a&gt;&lt;br /&gt;&#10;&lt;a href="https://en.wikipedia.org/wiki/Jump_flooding_algorithm"&gt;Jump flooding algorithm - Wikipedia&lt;/a&gt;&lt;br /&gt;&#10;&lt;a href="https://observablehq.com/@rreusser/gpu-voronoi-diagrams-using-the-jump-flooding-algorithm"&gt;GPU Voronoi Diagrams using the Jump Flooding Algorithm / Ricky Reusser | Observable&lt;/a&gt;&lt;/p&gt;&#10;&lt;ul class="table-of-contents"&gt;&#10;&lt;li&gt;&lt;a href="#サンプルプロジェクト"&gt;サンプルプロジェクト&lt;/a&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;a href="#DistanceFieldテクスチャ生成手順"&gt;DistanceFieldテクスチャ生成手順&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#アセット説明"&gt;アセット説明&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#Jump-Flooding-ステップ"&gt;Jump Flooding ステップ&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#その他"&gt;その他&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3 id="サンプルプロジェクト"&gt;サンプルプロジェクト&lt;/h3&gt;&#10;&lt;p&gt;&lt;a href="https://drive.google.com/file/d/1FEnmbDwYRBIwaszz5AE0AYxZszL3f-ga/view?usp=sharing"&gt;DistanceFIeldByJFA00.zip - Google &amp;#x30C9;&amp;#x30E9;&amp;#x30A4;&amp;#x30D6;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&#10;&lt;p&gt;プロジェクトの[ThirdPersonBP/DF]に関連BPやマテリアル等がある.&lt;/p&gt;&#10;&lt;figure class="figure-image figure-image-fotolife" title="関連コンテンツフォルダ"&gt;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/01ee4bded480ce2abd6147c04de23b1413901b2a887326cf8354440d16665e4b.png" width="1200" height="683" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;figcaption&gt;関連コンテンツフォルダ&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h4 id="DistanceFieldテクスチャ生成手順"&gt;DistanceFieldテクスチャ生成手順&lt;/h4&gt;&#10;&lt;p&gt;&lt;strong&gt;EUW_JfaTestアセット&lt;/strong&gt; を右クリック-&gt;Run Editor Utility &lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/Widget"&gt;Widget&lt;/a&gt; で&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/Widget"&gt;Widget&lt;/a&gt;を表示する.&lt;br /&gt;&#10;&lt;strong&gt;Generate Seed Texture ボタン&lt;/strong&gt; を押すとマテリアルによってSeedテクスチャが更新される.&lt;/p&gt;&#10;&lt;figure class="figure-image figure-image-fotolife" title="Generate SeedTexture"&gt;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/82eb92868758e2a8f2520e7a7580d5e0ee3378cbcf69ee53fcd3a5849db86ecc.png" width="1015" height="627" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;figcaption&gt;Generate SeedTexture&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;strong&gt;Run &lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/JFA"&gt;JFA&lt;/a&gt; ボタン&lt;/strong&gt; を押すとSeedテクスチャを元にDistanceFieldテクスチャが生成される.&lt;/p&gt;&#10;&lt;figure class="figure-image figure-image-fotolife" title="DistanceField生成"&gt;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/754ad1b9f0b4e013903449f9f98036a615c7b432b20a868ef78f5bbfd07613fa.png" width="932" height="615" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;figcaption&gt;Generate DistanceField&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h4 id="アセット説明"&gt;アセット説明&lt;/h4&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;RT_Seed&#10;&lt;ul&gt;&#10;&lt;li&gt;DistanceFieldの元になるSeedテクスチャ. 黒テクセルは無効で, それ以外の色のテクセルがSeedとして評価される.&lt;/li&gt;&#10;&lt;li&gt;どんなテクスチャでもよいが,今回はマテリアルM_DistanceSeedでその場で生成している.&lt;/li&gt;&#10;&lt;li&gt;サイズはデフォルト512x512だが変更可能. ただし動作確認しているのは2の冪のみ.&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;li&gt;RT_Jfa0&#10;&lt;ul&gt;&#10;&lt;li&gt;DistanceFieldの出力先テクスチャ.&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;li&gt;M_DistanceSeed&#10;&lt;ul&gt;&#10;&lt;li&gt;Seedテクスチャの生成用マテリアル. 適当な計算で適当な位置に黒(0,0,0)ではないSeedを書き込む.&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;li&gt;MF_JumpFlood&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/JFA"&gt;JFA&lt;/a&gt;のメイン処理をCustomNodeで記述したMaterialFunction. M_JumpFlood_SetupとM_JumpFlood_Itrはこれを呼び出す.&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;li&gt;M_JumpFlood_Setup&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/JFA"&gt;JFA&lt;/a&gt;の初回パス用マテリアル. Seedテクスチャを元に黒(0,0,0)ではないテクセルをSeedとして&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/JFA"&gt;JFA&lt;/a&gt;の初回パスを実行する.&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;li&gt;M_JumpFlood_Itr&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/JFA"&gt;JFA&lt;/a&gt;の反復パス用マテリアル. 基本的には初回パスと同じだが,&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/JFA"&gt;JFA&lt;/a&gt;入力が前回の&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/JFA"&gt;JFA&lt;/a&gt;パスの結果テクスチャになる.&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;li&gt;M_JumpFlood_Copy&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/JFA"&gt;JFA&lt;/a&gt;結果テクスチャを元に出力先テクスチャRT_Jfa0 へ出力するマテリアル.&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;li&gt;EUW_JfaTest&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/JFA"&gt;JFA&lt;/a&gt;処理のMaterialDrawなどをする&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/Widget"&gt;Widget&lt;/a&gt;. 今回の&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/JFA"&gt;JFA&lt;/a&gt;関連の処理はほぼここに書いてある.&lt;/li&gt;&#10;&lt;li&gt;&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/JFA"&gt;JFA&lt;/a&gt;のワークテクスチャ(PingPong用に2枚)を内部で生成して利用する.&lt;/li&gt;&#10;&lt;li&gt;&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/JFA"&gt;JFA&lt;/a&gt;自体はテクスチャサイズXに対して (log2(X)-1)回のマテリアルDrawで完了する.&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;</description></item><item><title> InstancedStaticMeshとCustomDataとTextureで大量オブジェクト (UE4 Advent Calendar 2020)</title><link>https://nagakagachi.github.io/entry/UE4_AdventCalendar2020_a/</link><pubDate>Tue, 15 Dec 2020 00:05:00 +0900</pubDate><guid>https://nagakagachi.github.io/entry/UE4_AdventCalendar2020_a/</guid><description>&lt;p&gt;&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/UE4"&gt;UE4&lt;/a&gt; AdventCalendar2020 15日目の記事となります&lt;br /&gt;&#10;&lt;a href="https://qiita.com/advent-calendar/2020/ue4"&gt;Unreal Engine 4 (UE4) Advent Calendar 2020 - Qiita&lt;/a&gt;&lt;/p&gt;&lt;p&gt;サンプルプロジェクトは以下(&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/UE4"&gt;UE4&lt;/a&gt;.26)&lt;br /&gt;&#10;&lt;iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fnagakagachi%2Fue4%2Ftree%2Fmaster%2Fproject%2Fsample%2FStatefulInstancedMesh" title="ue4/project/sample/StatefulInstancedMesh at master · nagakagachi/ue4" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"&gt;&lt;/iframe&gt;&lt;cite class="hatena-citation"&gt;&lt;a href="https://github.com/nagakagachi/ue4/tree/master/project/sample/StatefulInstancedMesh"&gt;github.com&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;&#10;&lt;ul class="table-of-contents"&gt;&#10;&lt;li&gt;&lt;a href="#やりたいこと"&gt;やりたいこと&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#仕組みの概要"&gt;仕組みの概要&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#事前情報"&gt;事前情報&lt;/a&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;a href="#CustomData"&gt;CustomData&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#CanvasObject"&gt;CanvasObject&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#TextureRenderTarget2Dの準備"&gt;TextureRenderTarget2Dの準備&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#InstancedStaticMeshComponentの設定"&gt;InstancedStaticMeshComponentの設定&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#Instance番号をCustomDataに設定"&gt;Instance番号をCustomDataに設定&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#Instanceの基準位置をテクスチャに書き込み"&gt;Instanceの基準位置をテクスチャに書き込み&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#変位テクスチャによってメッシュを動かすマテリアル"&gt;変位テクスチャによってメッシュを動かすマテリアル&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#変位テクスチャ更新マテリアル"&gt;変位テクスチャ更新マテリアル&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#速度テクスチャ更新マテリアル"&gt;速度テクスチャ更新マテリアル&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#まとめ"&gt;まとめ&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3 id="やりたいこと"&gt;やりたいこと&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;大量の&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9"&gt;インスタンス&lt;/a&gt;メッシュについて個別のパラメータをBPからマテリアルへ渡す&lt;/li&gt;&#10;&lt;li&gt;大量の&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9"&gt;インスタンス&lt;/a&gt;メッシュのパラメータ更新を&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/GPGPU"&gt;GPGPU&lt;/a&gt;(マテリアル)で高速に実行する&lt;/li&gt;&#10;&lt;li&gt;BPのみでつくる (&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/C%2B%2B"&gt;C++&lt;/a&gt;つかわない)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;このような要素を含んだデモとして以下のようなサンプルを作成しました。&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;基準位置とバネで接続された物体のシミュレーション&#10;&lt;ul&gt;&#10;&lt;li&gt;バネによる速度の変化&lt;/li&gt;&#10;&lt;li&gt;速度による位置の変化&lt;/li&gt;&#10;&lt;li&gt;プレイヤーとのインタ&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E9%A5%AF"&gt;ラク&lt;/a&gt;ション&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&lt;p&gt;&lt;iframe width="560" height="315" src="https://www.youtube.com/embed/2CmtMvd89KA?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;&lt;cite class="hatena-citation"&gt;&lt;a href="https://youtu.be/2CmtMvd89KA"&gt;youtu.be&lt;/a&gt;&lt;/cite&gt; &lt;br /&gt;&#10;&lt;iframe width="560" height="315" src="https://www.youtube.com/embed/2dWGmIMSwSg?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;&lt;cite class="hatena-citation"&gt;&lt;a href="https://youtu.be/2dWGmIMSwSg"&gt;youtu.be&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&#10;以降の説明は基本的にこのデモをベースにしていきます。&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;今回紹介する方法は大まかに以下のような流れになります。&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;InstancedStaticMeshのCustomDataにInstance番号を設定する&lt;/li&gt;&#10;&lt;li&gt;テクスチャを配列データに見立ててInstanceパラメータを格納する&lt;/li&gt;&#10;&lt;li&gt;Instanceパラメータテクスチャをマテリアルで更新する&lt;/li&gt;&#10;&lt;li&gt;マテリアルでInstance番号に対応したパラメータをテクスチャから取得して使う&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/div&gt;</description></item><item><title>UE4 ComputeShader Write, Material Read (GPGPU)</title><link>https://nagakagachi.github.io/entry/2020/03/20/060000/</link><pubDate>Fri, 20 Mar 2020 06:00:00 +0900</pubDate><guid>https://nagakagachi.github.io/entry/2020/03/20/060000/</guid><description>&lt;p&gt;エンジンバージョン:4.24 (4.25がリリースされたら対応予定)&lt;/p&gt;&#10;&lt;ul class="table-of-contents"&gt;&#10;&lt;li&gt;&lt;a href="#はじめに"&gt;はじめに&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#サンプルコード"&gt;サンプルコード&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#説明"&gt;説明&lt;/a&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;a href="#RWテクスチャ定義"&gt;RWテクスチャ定義&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#RWテクスチャのUAV生成"&gt;RWテクスチャのUAV生成&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#ComputeShaderによるRWテクスチャへの書き込み"&gt;ComputeShaderによるRWテクスチャへの書き込み&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#RWテクスチャのマテリアルでの利用"&gt;RWテクスチャのマテリアルでの利用&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#サンプルコードの概要"&gt;サンプルコードの概要&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&lt;p&gt;ComputeShaderで計算した結果を、RWテクスチャを利用してダイレクトにマテリアルで利用する。↓はサンプルコードの実行の様子。&lt;blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"&gt;&lt;p lang="ja" dir="ltr"&gt;ﾜｻﾜｻﾜｻ&lt;br&gt;&lt;br&gt;記事用のサンプルはもうこれでいいか（妥協&lt;a href="https://twitter.com/hashtag/UE4Study?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#UE4Study&lt;/a&gt; &lt;a href="https://t.co/qCDI2oPJHr"&gt;pic.twitter.com/qCDI2oPJHr&lt;/a&gt;&lt;/p&gt;&amp;mdash; なが (@nagakagachi) &lt;a href="https://twitter.com/nagakagachi/status/1240520264221224960?ref_src=twsrc%5Etfw"&gt;2020年3月19日&lt;/a&gt;&lt;/blockquote&gt; &lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt; &lt;/p&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3 id="はじめに"&gt;はじめに&lt;/h3&gt;&#10;&lt;p&gt;&lt;a href="https://nagakagachi.hatenablog.com/entry/2019/09/22/222604"&gt;&amp;#x524D;&amp;#x56DE;&amp;#x306E;&amp;#x8A18;&amp;#x4E8B;&lt;/a&gt;ではComputeShaderでメッシュ情報を直接生成する方法を紹介した。前回記事の手法では頂点カラー等を利用することでComputeShaderからマテリアルへ追加情報を渡すことができる。しかし頂点データの一部を間借りすることから渡せる情報に制限がある。&lt;br /&gt;&#10;当記事ではComputeShaderが書き込みをしたRWテクスチャをそのままマテリアルで利用することで頂点データ利用に比べてより自由に情報を受け渡す方法を検証してうまくいったので公開。そもそもこんな面倒なことしなくても可能な方法があるかもしれないので注意。&lt;br /&gt;&#10;(GlobalShader利用, エンジン改造無し)&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;uprojectファイルを右クリック→Generate &lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/Visual%20Studio"&gt;Visual Studio&lt;/a&gt; project files でプロジェクトコード生成.&lt;br /&gt;&#10;&lt;iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fnagakagachi%2Fue4%2Fblob%2Fmaster%2Fproject%2Fsample%2FUavTextureSample.zip" title="nagakagachi/ue4" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"&gt;&lt;/iframe&gt;&lt;cite class="hatena-citation"&gt;&lt;a href="https://github.com/nagakagachi/ue4/blob/master/project/sample/UavTextureSample.zip"&gt;github.com&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3 id="説明"&gt;説明&lt;/h3&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h4 id="RWテクスチャ定義"&gt;RWテクスチャ定義&lt;/h4&gt;&#10;&lt;p&gt;マテリアルで利用可能且つComputeShaderで書き込みが可能なUAVリソースとしてのテクスチャが必要であるため、UTextureRenderTarget2Dを継承したRWテクスチャを定義する。&lt;br /&gt;&#10;bCanCreateUAVにtrueを指定することでリソース自体がUAV利用可能な設定で作成される。ただしこの設定だけではUAVが作成されないため(メンバ変数uav_)、RWテクスチャとして利用するComputeShader処理側で必要なときに生成する(後述)。&lt;br /&gt;&#10;また、UAVの破棄はRenderThreadで処理する必要があるのでデスト&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E9%A5%AF"&gt;ラク&lt;/a&gt;タでRenderThreadのコマンドとして発行している。&lt;/p&gt;&#10;&lt;pre class="code lang-cpp" data-lang="cpp" data-unlink&gt;&lt;span class="synComment"&gt;// UavTextureSampleComponent.h&lt;/span&gt;&#10;UCLASS(BlueprintType)&#10;&lt;span class="synType"&gt;class&lt;/span&gt; UNglRWTextureRenderTarget2D : &lt;span class="synStatement"&gt;public&lt;/span&gt; UTextureRenderTarget2D&#10;{&#10;&#9;GENERATED_UCLASS_BODY()&#10;&lt;p&gt;&lt;span class="synStatement"&gt;public&lt;/span&gt;:&#10;&lt;span class="synType"&gt;virtual&lt;/span&gt; ~UNglRWTextureRenderTarget2D();&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;FUnorderedAccessViewRHIRef uav_;&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;};&#10;&lt;/pre&gt;&lt;pre class="code lang-cpp" data-lang="cpp" data-unlink&gt;&lt;span class="synComment"&gt;// UavTextureSampleComponent.cpp&lt;/span&gt;&#10;UNglRWTextureRenderTarget2D::UNglRWTextureRenderTarget2D(&lt;span class="synType"&gt;const&lt;/span&gt; FObjectInitializer&amp;amp; ObjectInitializer)&#10;: Super(ObjectInitializer)&#10;{&#10;bNeedsTwoCopies = &lt;span class="synConstant"&gt;false&lt;/span&gt;;&#10;&lt;span class="synComment"&gt;// リソース生成時にUAV利用可能な設定で作成することを指示&lt;/span&gt;&#10;bCanCreateUAV = &lt;span class="synConstant"&gt;true&lt;/span&gt;;&#10;}&lt;/p&gt;&#10;&lt;p&gt;UNglRWTextureRenderTarget2D::~UNglRWTextureRenderTarget2D()&#10;{&#10;&lt;span class="synStatement"&gt;if&lt;/span&gt; (uav_.IsValid())&#10;{&#10;&lt;span class="synComment"&gt;// UAVの破棄&lt;/span&gt;&#10;&lt;span class="synComment"&gt;// 破棄は描画スレッドで実行する必要があるのでコマンドをキューに積む.&lt;/span&gt;&#10;&lt;span class="synType"&gt;auto&lt;/span&gt; rhi_resource = uav_;&#10;ENQUEUE_RENDER_COMMAND(UpdateResourceImmediate)(&#10;[rhi_resource](FRHICommandListImmediate&amp;amp; RHICmdList)&#10;{&#10;rhi_resource-&amp;gt;Release();&#10;}&#10;);&#10;}&#10;}&#10;&lt;/pre&gt;&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h4 id="RWテクスチャのUAV生成"&gt;RWテクスチャのUAV生成&lt;/h4&gt;&#10;&lt;p&gt;本来ならUTextureRenderTarget2Dの初期化フローの中で生成するのが理想だが、今回はUAV利用する側が生成することにした。&lt;/p&gt;&#10;&lt;pre class="code lang-cpp" data-lang="cpp" data-unlink&gt;&lt;span class="synComment"&gt;// UavTextureSampleComponent.cpp 252行目&lt;/span&gt;&#10;&lt;span class="synStatement"&gt;if&lt;/span&gt; (!rw_tex-&amp;gt;uav_.IsValid())&#10;{&#10;&#9;rw_tex-&amp;gt;uav_ = RHICreateUnorderedAccessView(rw_tex-&amp;gt;Resource-&amp;gt;TextureRHI);&#10;}&#10;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h4 id="ComputeShaderによるRWテクスチャへの書き込み"&gt;ComputeShaderによるRWテクスチャへの書き込み&lt;/h4&gt;&#10;&lt;p&gt;生成したUAVはComputeShaderパラメータに設定することで利用可能。&lt;/p&gt;&#10;&lt;pre class="code lang-cpp" data-lang="cpp" data-unlink&gt;&lt;span class="synComment"&gt;// UavTextureSampleComponent.cpp 271行目&lt;/span&gt;&#10;SetUAVParameter(RHICmdList, rhi_cs, cs-&amp;gt;rw_tex, rw_tex-&amp;gt;uav_);&#10;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h4 id="RWテクスチャのマテリアルでの利用"&gt;RWテクスチャのマテリアルでの利用&lt;/h4&gt;&#10;&lt;p&gt;UNglRWTextureRenderTarget2Dは通常のUTextureオブジェクトと同様にマテリアルパラメータに設定可能。これでComputeShaderで書き込みをしたRWテクスチャをそのままマテリアルで利用できる。&lt;br /&gt;&#10;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/5c8a60351bcfe3ae030428d71a6de4334197e4b9e769ba08a822cd496fd85d1e.png" alt="f:id:nagakagachi:20200319232634p:plain" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;br /&gt;&#10;&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;</description></item><item><title>UE4 ComputeShaderでMeshの頂点バッファをリアルタイム書き換えする (GPGPU)</title><link>https://nagakagachi.github.io/entry/2019/09/22/222604/</link><pubDate>Sun, 22 Sep 2019 22:26:04 +0900</pubDate><guid>https://nagakagachi.github.io/entry/2019/09/22/222604/</guid><description>&lt;p&gt;エンジンバージョン:4.22, 4.23&lt;/p&gt;&#10;&lt;p&gt;諸事情によりサンプルプロジェクト無し&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/UE4"&gt;UE4&lt;/a&gt;のProceduralMeshのようなことをComputeShaderでできたら、大量の頂点をリアルタイムに操作できて面白いのではないかという思い付き。&lt;br /&gt;&#10;今回はたくさんの草をリアルタイムに生成する目的で実装してある程度うまくいったのでメモ。&lt;br /&gt;&#10;この方法を応用すれば頂点カラーとかに&lt;b&gt;InstanceID的なものやそのほか特殊な情報を埋め込んでおいてマテリアルBPで利用&lt;/b&gt;するといったこともできる。&lt;/p&gt;&lt;p&gt;この記事は&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/C%2B%2B"&gt;C++&lt;/a&gt;とGlobalShaderを利用したもので、且つエンジン改造はしない。&lt;br /&gt;&#10;また、自前で用意した頂点バッファをComputeShaderで書き換えて&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/UE4"&gt;UE4&lt;/a&gt;のメッシュ描画に流す方法がメインであるため、実装したComputeShader自体については深く説明しない。&lt;/p&gt;&lt;p&gt;&lt;iframe width="560" height="315" src="https://www.youtube.com/embed/vYK3n3544V4?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;&lt;cite class="hatena-citation"&gt;&lt;a href="https://www.youtube.com/watch?v=vYK3n3544V4"&gt;www.youtube.com&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&#10;↑プレイヤーからの影響を草一本一本が受ける例。&lt;br /&gt;&#10;草の位置や基準方向などを構造化バッファで保持しているのでそれらをComputeShaderで更新すればこのようなことも可能。&lt;br /&gt;&#10;&lt;iframe width="560" height="315" src="https://www.youtube.com/embed/KTw7eWUym6k?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;&lt;cite class="hatena-citation"&gt;&lt;a href="https://www.youtube.com/watch?v=KTw7eWUym6k"&gt;www.youtube.com&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&#10;↑さらにマテリアルBP側で頂点オフセットによる風揺れをつけた例。&lt;br /&gt;&#10;描画自体は&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/UE4"&gt;UE4&lt;/a&gt;のメッシュ描画に乗っかっているのでStaticMesh等と同じようにマテリアルが使えるのが強みの一つ。&lt;/p&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3 id="基本の考え"&gt;基本の考え&lt;/h3&gt;&#10;&lt;p&gt;自分で作成した頂点バッファやインデックスバッファを&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/UE4"&gt;UE4&lt;/a&gt;のメッシュ描画に流し込む方法は意外と簡単で、FPrimitiveSceneProxy派生クラスでGetDynamicMeshElements()関数をoverrideして適切にバッファ情報を渡せば可能になる。&lt;br /&gt;&#10;そこでこれらのバッファをUnorderedAccess可能な設定で作成しておき、毎フレームComputeShaderで書き換えるようにすることで、形状をリアルタイムに変更しつつマテリアル等を含めた描画部分は&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/UE4"&gt;UE4&lt;/a&gt;の仕組みをそのまま利用できると考えた。&lt;figure class="figure-image figure-image-fotolife" title="フローのイメージ"&gt;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/a7e0ed1dbb7467ca02ad9f19db3cd9c2f5042317917e76eeb0a6fe5fa284007d.png" alt="f:id:nagakagachi:20190922201851p:plain" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;figcaption&gt;フローのイメージ&lt;/figcaption&gt;&lt;/figure&gt;&lt;/p&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h4 id="必要な要素の概要"&gt;必要な要素の概要&lt;/h4&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;自作ComputeShader用GlobalShader&#10;&lt;ul&gt;&#10;&lt;li&gt;自作MeshProxyが生成した頂点バッファUAVやインデックスバッファUAVへ読み書きして草メッシュを作る&lt;/li&gt;&#10;&lt;li&gt;草メッシュの位置や向きは別途StructuredBufferで与える&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;li&gt;自作MeshComponentクラス&#10;&lt;ul&gt;&#10;&lt;li&gt;対になる自作MeshProxyを生成してシステムに登録し、ゲーム側からの情報を通知する役割&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;li&gt;自作MeshProxyクラス&#10;&lt;ul&gt;&#10;&lt;li&gt;自作MeshComponentの描画スレッド側における分身のような存在&lt;/li&gt;&#10;&lt;li&gt;UnorderedAccess可能な各種頂点バッファとインデックスバッファおよびそれらのUAVを作成する&lt;/li&gt;&#10;&lt;li&gt;&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/UE4"&gt;UE4&lt;/a&gt;メッシュ描画システムのメッシュ情報収集に適切に頂点バッファなどを設定する&lt;/li&gt;&#10;&lt;li&gt;ComputeShaderのDispatchコマンド発行もする&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3 id="自作computeshader用globalshader"&gt;自作ComputeShader用GlobalShader&lt;/h3&gt;&#10;&lt;p&gt;自作MeshProxyの各バッファのUAVを設定して書き換えるComputeShaderのGlobalShader。&lt;br /&gt;&#10;GlobalShader自体については公式のドキュメントを参考。&lt;br /&gt;&#10;&lt;a href="https://docs.unrealengine.com/ja/Programming/Rendering/ShaderInPlugin/QuickStart/index.html"&gt;https://docs.unrealengine.com/ja/Programming/Rendering/ShaderInPlugin/QuickStart/index.html&lt;/a&gt;&lt;br /&gt;&#10;ComputeShaderをGlobalShaderとして作成してUAV他パラメータを設定する流れについては以下のブログが参考になる。&lt;br /&gt;&#10;&lt;a href="http://www.sciement.com/tech-blog/c/structured_buffer_compute_shader_ue4_part2/"&gt;[UE4][ComputeShader][HLSL][C++]Unreal Engine 4&amp;#x3067;(RW)StructuredBuffer&amp;#x3092;&amp;#x7528;&amp;#x3044;&amp;#x305F;ComputeShader&amp;#x3092;&amp;#x5229;&amp;#x7528;&amp;#x3059;&amp;#x308B;&amp;#xFF08;&amp;#x305D;&amp;#x306E;&amp;#xFF12;&amp;#xFF1A;C++&amp;#x5074;&amp;#x30B7;&amp;#x30A7;&amp;#x30FC;&amp;#x30C0;&amp;#x30AF;&amp;#x30E9;&amp;#x30B9;&amp;#xFF09; &amp;ndash; &amp;#x30B5;&amp;#x30A4;&amp;#x30A2;&amp;#x30E1;&amp;#x30F3;&amp;#x30C8;&amp;#x6280;&amp;#x8853;&amp;#x30E1;&amp;#x30E2;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;今回はComputeShaderのスレッド一つが草一本を担当することとし、スレッドIDと草一つに割り当てられた頂点数からスレッドが書き込む頂点バッファ内の位置を決めている。あまり特殊なことはしていないが、接線法線頂点バッファ等がPackedフォーマットになっている場合はUAVから読み取った値をUnpackしたり書き戻す際に再度Packしたりといった処理が必要な点に注意。&lt;figure class="figure-image figure-image-fotolife" title="ComputeShaderの処理イメージ"&gt;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/fc508a3445d4aa4c0034f49351815345ab6d54a45970a5e6adf04e1739dbab1b.png" alt="f:id:nagakagachi:20190922220711p:plain" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;figcaption&gt;ComputeShaderの処理イメージ&lt;/figcaption&gt;&lt;/figure&gt;&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3 id="自作meshcomponentクラス"&gt;自作MeshComponentクラス&lt;/h3&gt;&#10;&lt;p&gt;UPrimitiveComponentを継承&lt;br /&gt;&#10;&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%DD%A1%BC%A5%CD%A5%F3%A5%C8"&gt;コンポーネント&lt;/a&gt;としてゲームスレッド側の情報を管理する。UProceduralMeshComponentを参考にした。&lt;br /&gt;&#10;&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%DD%A1%BC%A5%CD%A5%F3%A5%C8"&gt;コンポーネント&lt;/a&gt;の描画スレッド側の情報を管理するカスタムMeshProxyクラスを生成して保持し、適切に情報を渡したりするのが主な役目。&lt;br /&gt;&#10;適切なタイミングで自作MeshProxyへComputeShaderのDispatchコマンド生成をリク&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9"&gt;エス&lt;/a&gt;トをする。&lt;/p&gt;&#10;&lt;pre class="code lang-cpp" data-lang="cpp" data-unlink&gt;&lt;span class="synType"&gt;virtual&lt;/span&gt; &lt;span class="synType"&gt;void&lt;/span&gt; UComputeMeshComponent::TickComponent(&lt;span class="synType"&gt;float&lt;/span&gt; DeltaTime, &lt;span class="synType"&gt;enum&lt;/span&gt; ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) &lt;span class="synType"&gt;override&lt;/span&gt;&#10;{&#10; &lt;span class="synComment"&gt;// SendRenderDynamicData_Concurrent の呼び出しをリクエスト&lt;/span&gt;&#10; MarkRenderDynamicDataDirty();&#10;}&#10;&lt;span class="synType"&gt;virtual&lt;/span&gt; &lt;span class="synType"&gt;void&lt;/span&gt; UComputeMeshComponent::SendRenderDynamicData_Concurrent() &lt;span class="synType"&gt;override&lt;/span&gt;&#10;{&#10; &lt;span class="synComment"&gt;// カスタムMeshProxyにComputeShaderのDispatchコマンド生成を要求&lt;/span&gt;&#10; カスタムMeshProxy-&amp;gt;EnqueueDispatchComputeShader();&#10;}&#10;&lt;/pre&gt;&#10;&lt;/div&gt;</description></item></channel></rss>