<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>C++ on ながむしメモ</title><link>https://nagakagachi.github.io/categories/c++/</link><description>Recent content in C++ on ながむしメモ</description><generator>Hugo</generator><language>ja-JP</language><lastBuildDate>Sat, 10 Jun 2023 22:17:12 +0900</lastBuildDate><atom:link href="https://nagakagachi.github.io/categories/c++/index.xml" rel="self" type="application/rss+xml"/><item><title>UE5.2でC++プロジェクトのビルド時間が増加した問題の対処 [UE][UE5.2]</title><link>https://nagakagachi.github.io/entry/2023/06/10/221712/</link><pubDate>Sat, 10 Jun 2023 22:17:12 +0900</pubDate><guid>https://nagakagachi.github.io/entry/2023/06/10/221712/</guid><description>&lt;p&gt;UE5.1からUE5.2へアップデートしてから, &lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/C%2B%2B"&gt;C++&lt;/a&gt;プロジェクトのビルド時間が5倍以上に増えて困った.&lt;/p&gt;&lt;p&gt;&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9"&gt;ソースコード&lt;/a&gt;を色々書き換えて調べたところ,&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;GlobalShader派生クラスへの&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/SRV"&gt;SRV&lt;/a&gt;, UAV設定関数をフラットに記述する数が大きく影響&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;p&gt;というところまでわかったのでメモ.&lt;/p&gt;&#10;&lt;p&gt;私と同じ沼にハマったひとの役にたてば幸い.&lt;/p&gt;&#10;&lt;p&gt;具体的には以下のUtil関数が該当&lt;/p&gt;&#10;&lt;pre class="code c++" data-lang="c++" data-unlink&gt;RenderCore/Public/ShaderParameterUtils.h&#10;SetSRVParameter()&#10;SetUAVParameter()&lt;/pre&gt;&lt;p&gt;&lt;br /&gt;&#10;&lt;p&gt;これらを一つの関数内で直接大量に(フラットに)記述するとビルド時間が大きく増加する模様.&lt;br /&gt;&#10;対策としては &lt;strong&gt;Shader単位等で関数化してそれを呼び出すような記述&lt;/strong&gt; とするとUE5.1以前と同じくらいのビルド時間だった.&lt;/p&gt;&lt;/p&gt;&#10;&lt;pre class="code c++" data-lang="c++" data-unlink&gt;// ビルド時間が増えるパターン 100個くらい並んでました.&#10;void MainFunc()&#10;{&#10; // 全てのShaderに対するSetSRV/SetUAVをフラットに記述.&#10; SetSRVParameter(ShaderA, SRV);&#10; SetSRVParameter(ShaderA, SRV);&#10; SetUAVParameter(ShaderA, UAV);&#10; SetUAVParameter(ShaderA, UAV);&#10; ...&#10; SetSRVParameter(ShaderZ, SRV);&#10; SetSRVParameter(ShaderZ, SRV);&#10; SetUAVParameter(ShaderZ, UAV);&#10; SetUAVParameter(ShaderZ, UAV);&#10;}&lt;/pre&gt;&lt;p&gt;&lt;br /&gt;&#10;&lt;p&gt;エンジン側の&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9"&gt;ソースコード&lt;/a&gt;を見るとシェーダ毎等で関数に分けていたため,&lt;br /&gt;&#10;そのように書き直したところビルド時間が以前と同じくらいになった.&lt;br /&gt;&#10;&lt;br /&gt;&lt;/p&gt;&#10;&lt;/p&gt;&#10;&lt;pre class="code c++" data-lang="c++" data-unlink&gt;// ビルド時間が増えないパターン.&#10;void SetParamShaderA()&#10;{&#10; SetSRVParameter(ShaderA, SRV);&#10; SetSRVParameter(ShaderA, SRV);&#10; SetUAVParameter(ShaderA, UAV);&#10; SetUAVParameter(ShaderA, UAV);&#10; ...&#10;}&#10;...&#10;void SetParamShaderZ()&#10;{&#10; SetSRVParameter(ShaderZ, SRV);&#10; SetSRVParameter(ShaderZ, SRV);&#10; SetUAVParameter(ShaderZ, UAV);&#10; SetUAVParameter(ShaderZ, UAV);&#10; ...&#10;}&#10;void MainFunc()&#10;{&#10; // Shader毎のSRV/UAV設定メソッドを記述.&#10; SetParamShaderA(...);&#10; ...&#10; SetParamShaderZ(...);&#10;}&lt;/pre&gt;&#10;&lt;p&gt;私のプロジェクトでは前者の場合 8分前後 かかっていたものが, 後者に修正したところ 1分前後 に短縮された.&lt;/p&gt;</description></item><item><title>TextureArrayに対して実行可能なDrawMaterialToRenderTargetプラグイン[UE][Plugin]</title><link>https://nagakagachi.github.io/entry/2023/01/16/080000/</link><pubDate>Mon, 16 Jan 2023 08:00:00 +0900</pubDate><guid>https://nagakagachi.github.io/entry/2023/01/16/080000/</guid><description>&lt;p&gt;&lt;strong&gt;TextureRenderTarget2DArray&lt;/strong&gt; のSlice(配列の要素)を指定して &lt;strong&gt;DrawMaterialToRenderTarget&lt;/strong&gt; ができるUE&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%D7%A5%E9%A5%B0%A5%A4%A5%F3"&gt;プラグイン&lt;/a&gt;の公開.&lt;br /&gt;&#10;&lt;br /&gt;&#10;&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;ul&gt;&#10;&lt;li&gt;&lt;a href="#リポジトリの-NglTextureRt2dArrayUtil-をコピー"&gt;リポジトリの NglTextureRt2dArrayUtil をコピー&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="#サンプル"&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;p&gt;テクスチャ配列アセットの要素に対してマテリアル描画を実行できる&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%D7%A5%E9%A5%B0%A5%A4%A5%F3"&gt;プラグイン&lt;/a&gt;.&lt;br /&gt;&#10;UE標準のDrawMaterialToRenderTargetノードとほぼ同じで, TextureRenderTarget2DArrayとその何番目にDrawするかを指定できる.&lt;/p&gt;&#10;&lt;figure class="figure-image figure-image-fotolife" title="NglDrawMaterialToRenderTargetArraySliceノード"&gt;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/861d07799c56448bb066d90ed87790effc1e299a781ac42624bdfe1dd3f81712.png" width="635" height="420" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;figcaption&gt;NglDrawMaterialToRenderTargetArraySliceノード&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p&gt;内部で一時テクスチャの生成やコピーをする必要があったため, ゲーム中にリアルタイム利用するような用途向きではない点に注意.&lt;/p&gt;&#10;&lt;p&gt;エンジン改造無しで実装するためにこうなったが今後修正できるかもしれない(未定),&lt;/p&gt;&#10;&lt;p&gt;動作確認 UE5.1 &lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/Win64"&gt;Win64&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;div class="section"&gt;&#10;&lt;h4 id="リポジトリの-NglTextureRt2dArrayUtil-をコピー"&gt;&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA"&gt;リポジトリ&lt;/a&gt;の NglTextureRt2dArrayUtil をコピー&lt;/h4&gt;&#10;&lt;p&gt;&lt;a href="https://github.com/nagakagachi/ue_plugin/tree/main/distribution/NglTextureRt2dArrayUtil"&gt;ue_plugin/distribution/NglTextureRt2dArrayUtil at main &amp;middot; nagakagachi/ue_plugin &amp;middot; GitHub&lt;/a&gt;&lt;/p&gt;&lt;p&gt;自身のプロジェクトに Plugins &lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8"&gt;ディレクト&lt;/a&gt;リを作成し, その中に上記&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/Github"&gt;Github&lt;/a&gt;の NglTextureRt2dArrayUtil &lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8"&gt;ディレクト&lt;/a&gt;リをコピーペーストする.&lt;br /&gt;&#10;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/f2424a228885ead7b7aa13c3f7b15aff3414d42250c07db4f65015972a02007c.png" width="284" height="182" 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/aca77d72e4d09e756c968b2805d1fc316bf69650a72292833f697b2076ba3d37.png" width="441" height="139" 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;a class="keyword" href="https://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="https://d.hatena.ne.jp/keyword/%A5%D7%A5%E9%A5%B0%A5%A4%A5%F3"&gt;プラグイン&lt;/a&gt; のウィンドウを開き, NglTextureRt2dArrayUtil&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%D7%A5%E9%A5%B0%A5%A4%A5%F3"&gt;プラグイン&lt;/a&gt;が有効になっていればOK.&lt;br /&gt;&#10;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/ba9a6d5dba272364ffaae21e9df37cab1595109385dec3a3c3cadd94fcc95860.png" width="882" height="460" 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&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3 id="サンプル"&gt;サンプル&lt;/h3&gt;&#10;&lt;p&gt;&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%D7%A5%E9%A5%B0%A5%A4%A5%F3"&gt;プラグイン&lt;/a&gt;コンテンツのEditorUtilityWidget &lt;strong&gt;EUW_DrawToRenderTargetArraySample&lt;/strong&gt; を右クリック-&gt;エディターユーティリティウィジットを実行 で簡易サンプルが起動する&lt;br /&gt;&#10;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/94f3c62a9e079ff9cbfadb7f2c79695b165aa870b0900170b20f7224f224d621.png" width="993" height="434" 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/238bdee6dd0bf8828805c6c141ecc387c6ae3dff2355047f6878dd6bbbabdf64.png" width="1001" height="474" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;br /&gt;&#10;&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;ウィンドウ左側にマテリアルと描画先Array要素番号(Slice Index)を指定.&lt;/li&gt;&#10;&lt;li&gt;ウィンドウ右側に書き込み先のTextureRTArrayアセットを指定。&lt;/li&gt;&#10;&lt;li&gt;Runボタン を押すとArray指定要素にマテリアル描画が実行される.&lt;/li&gt;&#10;&lt;/ol&gt;&lt;p&gt;下図は&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/Widget"&gt;Widget&lt;/a&gt;でSlice 0番に対して実行して, エディタでTextureRTArrayの Slice 0 を表示して結果を確認している様子.&lt;br /&gt;&#10;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/aaba9895685d049e9eb1dd70e574973e2883642033bf736247f8afe0a99a26ea.png" width="1200" height="646" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&#10;&lt;p&gt;出来上がったTextureRtArrayをテクスチャ配列アセットに変換するなどご自由に.&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;a class="keyword" href="https://d.hatena.ne.jp/keyword/Github"&gt;Github&lt;/a&gt;のStarや使ったよというメッセージを貰えると嬉しいです!&lt;/p&gt;&#10;&lt;p&gt;そもそも作った理由はエディタでマテリアルを使って自由に色々なテクスチャ配列を作りたかったため.&lt;/p&gt;&#10;&lt;p&gt;面白い使い方やもっと良い機能案があればご連絡ください.&lt;/p&gt;&#10;&lt;br /&gt;&#10;&lt;p&gt;以上&amp;hellip;&lt;/p&gt;</description></item><item><title>3要素ソートのメモ (3element pattern sort)</title><link>https://nagakagachi.github.io/entry/2022/05/23/212804/</link><pubDate>Mon, 23 May 2022 21:28:04 +0900</pubDate><guid>https://nagakagachi.github.io/entry/2022/05/23/212804/</guid><description>&lt;p&gt;3要素をパターンでソート.&lt;/p&gt;&#10;&lt;p&gt;安定ソートではないことに注意.&lt;/p&gt;&#10;&lt;p&gt;&lt;span style="font-size: 80%"&gt;久しぶりの記事がこれですよ&lt;/span&gt;&lt;br /&gt;&#10;&lt;/p&gt;&#10;&lt;pre class="code lang-cpp" data-lang="cpp" data-unlink&gt;&lt;span class="synComment"&gt;// パターン.&lt;/span&gt;&#10;&lt;span class="synType"&gt;constexpr&lt;/span&gt; &lt;span class="synType"&gt;int&lt;/span&gt; k_sort_pattern_3[&lt;span class="synConstant"&gt;8&lt;/span&gt;][&lt;span class="synConstant"&gt;3&lt;/span&gt;]&#10;{&#10; {&lt;span class="synConstant"&gt;2&lt;/span&gt;, &lt;span class="synConstant"&gt;1&lt;/span&gt;, &lt;span class="synConstant"&gt;0&lt;/span&gt;}, &lt;span class="synComment"&gt;// 000-&amp;gt; 0&lt;/span&gt;&#10; {&lt;span class="synConstant"&gt;0&lt;/span&gt;, &lt;span class="synConstant"&gt;2&lt;/span&gt;, &lt;span class="synConstant"&gt;1&lt;/span&gt;}, &lt;span class="synComment"&gt;// 001-&amp;gt; 1&lt;/span&gt;&#10; {&lt;span class="synConstant"&gt;1&lt;/span&gt;, &lt;span class="synConstant"&gt;0&lt;/span&gt;, &lt;span class="synConstant"&gt;2&lt;/span&gt;}, &lt;span class="synComment"&gt;// 010-&amp;gt; 2&lt;/span&gt;&#10; {&lt;span class="synConstant"&gt;0&lt;/span&gt; ,&lt;span class="synConstant"&gt;1&lt;/span&gt;, &lt;span class="synConstant"&gt;2&lt;/span&gt;}, &lt;span class="synComment"&gt;// 011-&amp;gt; 3&lt;/span&gt;&#10; {&lt;span class="synConstant"&gt;2&lt;/span&gt;, &lt;span class="synConstant"&gt;1&lt;/span&gt;, &lt;span class="synConstant"&gt;0&lt;/span&gt;}, &lt;span class="synComment"&gt;// 100-&amp;gt; 4&lt;/span&gt;&#10; {&lt;span class="synConstant"&gt;2&lt;/span&gt;, &lt;span class="synConstant"&gt;0&lt;/span&gt;, &lt;span class="synConstant"&gt;1&lt;/span&gt;}, &lt;span class="synComment"&gt;// 101-&amp;gt; 5&lt;/span&gt;&#10; {&lt;span class="synConstant"&gt;1&lt;/span&gt;, &lt;span class="synConstant"&gt;2&lt;/span&gt;, &lt;span class="synConstant"&gt;0&lt;/span&gt;}, &lt;span class="synComment"&gt;// 110-&amp;gt; 6&lt;/span&gt;&#10; {&lt;span class="synConstant"&gt;0&lt;/span&gt; ,&lt;span class="synConstant"&gt;1&lt;/span&gt;, &lt;span class="synConstant"&gt;2&lt;/span&gt;}, &lt;span class="synComment"&gt;// 111-&amp;gt; 7&lt;/span&gt;&#10;};&#10;&lt;span class="synComment"&gt;// 3要素からパターンID計算.&lt;/span&gt;&#10;&lt;span class="synType"&gt;constexpr&lt;/span&gt; &lt;span class="synType"&gt;auto&lt;/span&gt; get_sort_pattern_3 = [](&lt;span class="synType"&gt;const&lt;/span&gt; &lt;span class="synType"&gt;float&lt;/span&gt; (&amp;amp;ar)[&lt;span class="synConstant"&gt;3&lt;/span&gt;])&#10;{&#10; &lt;span class="synStatement"&gt;return&lt;/span&gt; ((ar[&lt;span class="synConstant"&gt;0&lt;/span&gt;] &amp;lt;= ar[&lt;span class="synConstant"&gt;1&lt;/span&gt;]) ? &lt;span class="synConstant"&gt;1&lt;/span&gt; : &lt;span class="synConstant"&gt;0&lt;/span&gt;) + ((ar[&lt;span class="synConstant"&gt;1&lt;/span&gt;] &amp;lt;= ar[&lt;span class="synConstant"&gt;2&lt;/span&gt;]) ? &lt;span class="synConstant"&gt;2&lt;/span&gt; : &lt;span class="synConstant"&gt;0&lt;/span&gt;) + ((ar[&lt;span class="synConstant"&gt;2&lt;/span&gt;] &amp;lt;= ar[&lt;span class="synConstant"&gt;0&lt;/span&gt;]) ? &lt;span class="synConstant"&gt;4&lt;/span&gt; : &lt;span class="synConstant"&gt;0&lt;/span&gt;);&#10;};&#10;&lt;p&gt;&lt;span class="synComment"&gt;// ソート対象の3要素配列.&lt;/span&gt;&#10;&lt;span class="synType"&gt;constexpr&lt;/span&gt; &lt;span class="synType"&gt;float&lt;/span&gt; src[&lt;span class="synConstant"&gt;3&lt;/span&gt;] = { -&lt;span class="synConstant"&gt;3.0f&lt;/span&gt;,&lt;span class="synConstant"&gt;3.0f&lt;/span&gt;,-&lt;span class="synConstant"&gt;2.3f&lt;/span&gt; };&#10;&lt;span class="synComment"&gt;// パターンID取得.&lt;/span&gt;&#10;&lt;span class="synType"&gt;constexpr&lt;/span&gt; &lt;span class="synType"&gt;int&lt;/span&gt; sort_pattern = &lt;span class="synIdentifier"&gt;get_sort_pattern_3&lt;/span&gt;(src);&lt;/p&gt;&#10;&lt;p&gt;&lt;span class="synComment"&gt;// パターンでソート順に取り出し.&lt;/span&gt;&#10;&lt;span class="synType"&gt;constexpr&lt;/span&gt; &lt;span class="synType"&gt;float&lt;/span&gt; sort_v0 = src[k_sort_pattern_3[sort_pattern][&lt;span class="synConstant"&gt;0&lt;/span&gt;]];&#10;&lt;span class="synType"&gt;constexpr&lt;/span&gt; &lt;span class="synType"&gt;float&lt;/span&gt; sort_v1 = src[k_sort_pattern_3[sort_pattern][&lt;span class="synConstant"&gt;1&lt;/span&gt;]];&#10;&lt;span class="synType"&gt;constexpr&lt;/span&gt; &lt;span class="synType"&gt;float&lt;/span&gt; sort_v2 = src[k_sort_pattern_3[sort_pattern][&lt;span class="synConstant"&gt;2&lt;/span&gt;]];&lt;/p&gt;&#10;&lt;p&gt;&lt;span class="synComment"&gt;// チェック.&lt;/span&gt;&#10;&lt;span class="synStatement"&gt;static_assert&lt;/span&gt;(sort_v0 &amp;lt;= sort_v1 &amp;amp;&amp;amp; sort_v1 &amp;lt;= sort_v2);&#10;&lt;/pre&gt;&lt;/p&gt;</description></item><item><title>縮小バッファによる半透明パーティクル描画についてのメモ</title><link>https://nagakagachi.github.io/entry/2021/12/12/193138/</link><pubDate>Sun, 12 Dec 2021 19:31:38 +0900</pubDate><guid>https://nagakagachi.github.io/entry/2021/12/12/193138/</guid><description>&lt;p&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="#Lost-Planet"&gt;Lost Planet&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#METAL-GEAR-SOLID-4"&gt;METAL GEAR SOLID 4&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#Tales-of-ARISE"&gt;Tales of ARISE&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 class="keyword" href="https://d.hatena.ne.jp/keyword/METAL%20GEAR%20SOLID%204"&gt;METAL GEAR SOLID 4&lt;/a&gt;の記事などで紹介されている方法の確認をあらためて&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;半透明用バッファを(0,0,0,1)でクリア&lt;/li&gt;&#10;&lt;li&gt;半透明描画&#10;&lt;ul&gt;&#10;&lt;li&gt;アルファブレンドの場合&#10;&lt;ul&gt;&#10;&lt;li&gt;RGB : Dst*(1-SrcAlpha) + Src*SrcAlpha&lt;/li&gt;&#10;&lt;li&gt;Alpha: DstAlpha * (1 - SrcAlpha)&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;li&gt;加算ブレンドの場合&#10;&lt;ul&gt;&#10;&lt;li&gt;RGB : Dst + Src*SrcAlpha&lt;/li&gt;&#10;&lt;li&gt;Alpha: DstAlpha&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;li&gt;半透明バッファを最終合成&#10;&lt;ul&gt;&#10;&lt;li&gt;RGB : Dst * SrcAlpha + Src&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;3回の半透明描画の例で計算確認&lt;/p&gt;&#10;&lt;p&gt;c[i]はアルファ乗算済みRGB&lt;/p&gt;&#10;&lt;p&gt;a[i]は対応する出力アルファ値{ 半透明アルファ値 : アルファブレンド, 0.0 : 加算合成 }&lt;/p&gt;&#10;&lt;p&gt;としてアルファブレンドと加算合成が任意に混在するものとする&lt;/p&gt;&#10;&lt;pre class="code lang-cpp" data-lang="cpp" data-unlink&gt;&lt;span class="synComment"&gt;// c0に直接3回の合成(c1, c2, c3 の順)&lt;/span&gt;&#10;cd=c3+(c2+(c1+&lt;span class="synIdentifier"&gt;c0&lt;/span&gt;(&lt;span class="synConstant"&gt;1&lt;/span&gt;-a1))(&lt;span class="synConstant"&gt;1&lt;/span&gt;-a2))(&lt;span class="synConstant"&gt;1&lt;/span&gt;-a3)&#10;ad=(&lt;span class="synConstant"&gt;1&lt;/span&gt;-a0)(&lt;span class="synConstant"&gt;1&lt;/span&gt;-a1)(&lt;span class="synConstant"&gt;1&lt;/span&gt;-a2)(&lt;span class="synConstant"&gt;1&lt;/span&gt;-a3)&#10;&#10;&#10;&lt;span class="synComment"&gt;// ---------------------------------------------&lt;/span&gt;&#10;&#10;&lt;span class="synComment"&gt;// cs_, as_へ3回の半透明を合成してから最後にc0と合成&lt;/span&gt;&#10;&lt;span class="synComment"&gt;// 疑似コードの通り初期値として c0=0, a0=1 とすると c1,c2,c3 の合成は&lt;/span&gt;&#10;c_temp=c3+(c2+&lt;span class="synIdentifier"&gt;c1&lt;/span&gt;(&lt;span class="synConstant"&gt;1&lt;/span&gt;-a2))(&lt;span class="synConstant"&gt;1&lt;/span&gt;-a3)&#10;a_temp=(&lt;span class="synConstant"&gt;1&lt;/span&gt;-a1)(&lt;span class="synConstant"&gt;1&lt;/span&gt;-a2)(&lt;span class="synConstant"&gt;1&lt;/span&gt;-a3)&#10;&#10;&lt;span class="synComment"&gt;// c_tempをc0へ合成&lt;/span&gt;&#10;cd=c0*a_temp+c_temp&#10;=&lt;span class="synIdentifier"&gt;c0&lt;/span&gt;(&lt;span class="synConstant"&gt;1&lt;/span&gt;-a1)(&lt;span class="synConstant"&gt;1&lt;/span&gt;-a2)(&lt;span class="synConstant"&gt;1&lt;/span&gt;-a3)+( c3+(c2+&lt;span class="synIdentifier"&gt;c1&lt;/span&gt;(&lt;span class="synConstant"&gt;1&lt;/span&gt;-a2))(&lt;span class="synConstant"&gt;1&lt;/span&gt;-a3) )&#10;=c3+(c2+(c1+&lt;span class="synIdentifier"&gt;c0&lt;/span&gt;(&lt;span class="synConstant"&gt;1&lt;/span&gt;-a1))(&lt;span class="synConstant"&gt;1&lt;/span&gt;-a2))(&lt;span class="synConstant"&gt;1&lt;/span&gt;-a3)&#10;&lt;/pre&gt;&#10;&lt;p&gt;c0直接合成とc_tmpを介した合成で式が一致した&lt;/p&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;cs=c3+(c2+(c1+c0(1-a1))(1-a2))(1-a3)&lt;br&gt;as=(1-a0)(1-a1)(1-a2)(1-a3)&lt;br&gt;&lt;br&gt;c0=0, a0=1とすると&lt;br&gt;cs_=c3+(c2+c1(1-a2))(1-a3)&lt;br&gt;as_=(1-a1)(1-a2)(1-a3)&lt;br&gt;&lt;br&gt;cdへの合成&lt;br&gt;c=cd*as_+cs_&lt;br&gt;=cd(1-a1)(1-a2)(1-a3)+( c3+(c2+c1(1-a2))(1-a3) )&lt;br&gt;=c3+(c2+(c1+cd(1-a1))(1-a2))(1-a3)&lt;br&gt;&lt;br&gt;で最初の式でc0=cdとした場合と一致&lt;/p&gt;&amp;mdash; なが (@nagakagachi) &lt;a href="https://twitter.com/nagakagachi/status/1468969836424609795?ref_src=twsrc%5Etfw"&gt;2021年12月9日&lt;/a&gt;&lt;/blockquote&gt; &lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt; &lt;br /&gt;&#10;&lt;br /&gt;&#10;&lt;br /&gt;&#10;&lt;/p&gt;&#10;&lt;/div&gt;</description></item><item><title> MainViewのViewportSizeとカメラ位置,カメラ姿勢の取得</title><link>https://nagakagachi.github.io/entry/2021/11/06/201354/</link><pubDate>Sat, 06 Nov 2021 20:13:54 +0900</pubDate><guid>https://nagakagachi.github.io/entry/2021/11/06/201354/</guid><description>&lt;p&gt;&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/UE4"&gt;UE4&lt;/a&gt;.27で確認&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-C++" data-lang="C++"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8b949e;font-style:italic"&gt;// Get Current View Info (EditorMode, PlayMode).&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff7b72"&gt;auto&lt;/span&gt; GetCurrentViewportInfo &lt;span style="color:#ff7b72;font-weight:bold"&gt;=&lt;/span&gt; [](&lt;span style="color:#ff7b72"&gt;const&lt;/span&gt; UWorld&lt;span style="color:#ff7b72;font-weight:bold"&gt;*&lt;/span&gt; world, FVector2D&lt;span style="color:#ff7b72;font-weight:bold"&gt;&amp;amp;&lt;/span&gt; out_viewport_size, FVector&lt;span style="color:#ff7b72;font-weight:bold"&gt;&amp;amp;&lt;/span&gt; out_view_location, FQuat&lt;span style="color:#ff7b72;font-weight:bold"&gt;&amp;amp;&lt;/span&gt; out_view_quat)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff7b72"&gt;if&lt;/span&gt; (&lt;span style="color:#ff7b72;font-weight:bold"&gt;!&lt;/span&gt;world)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff7b72"&gt;return&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8b949e;font-weight:bold;font-style:italic"&gt;#if WITH_EDITOR&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff7b72"&gt;if&lt;/span&gt; (world&lt;span style="color:#ff7b72;font-weight:bold"&gt;-&amp;gt;&lt;/span&gt;WorldType &lt;span style="color:#ff7b72;font-weight:bold"&gt;==&lt;/span&gt; EWorldType&lt;span style="color:#ff7b72;font-weight:bold"&gt;::&lt;/span&gt;Editor &lt;span style="color:#ff7b72;font-weight:bold"&gt;||&lt;/span&gt; world&lt;span style="color:#ff7b72;font-weight:bold"&gt;-&amp;gt;&lt;/span&gt;WorldType &lt;span style="color:#ff7b72;font-weight:bold"&gt;==&lt;/span&gt; EWorldType&lt;span style="color:#ff7b72;font-weight:bold"&gt;::&lt;/span&gt;EditorPreview)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#8b949e;font-style:italic"&gt;// EditorMode.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#8b949e;font-style:italic"&gt;// Use First Editor Viewport.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff7b72"&gt;for&lt;/span&gt; (FLevelEditorViewportClient&lt;span style="color:#ff7b72;font-weight:bold"&gt;*&lt;/span&gt; &lt;span style="color:#79c0ff;font-weight:bold"&gt;level_viewport_clients&lt;/span&gt; : GEditor&lt;span style="color:#ff7b72;font-weight:bold"&gt;-&amp;gt;&lt;/span&gt;GetLevelViewportClients())&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff7b72"&gt;if&lt;/span&gt; (level_viewport_clients &lt;span style="color:#ff7b72;font-weight:bold"&gt;&amp;amp;&amp;amp;&lt;/span&gt; level_viewport_clients&lt;span style="color:#ff7b72;font-weight:bold"&gt;-&amp;gt;&lt;/span&gt;IsPerspective())&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; out_viewport_size &lt;span style="color:#ff7b72;font-weight:bold"&gt;=&lt;/span&gt; level_viewport_clients&lt;span style="color:#ff7b72;font-weight:bold"&gt;-&amp;gt;&lt;/span&gt;Viewport&lt;span style="color:#ff7b72;font-weight:bold"&gt;-&amp;gt;&lt;/span&gt;GetSizeXY();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; out_view_location &lt;span style="color:#ff7b72;font-weight:bold"&gt;=&lt;/span&gt; level_viewport_clients&lt;span style="color:#ff7b72;font-weight:bold"&gt;-&amp;gt;&lt;/span&gt;GetViewLocation();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; out_view_quat &lt;span style="color:#ff7b72;font-weight:bold"&gt;=&lt;/span&gt; level_viewport_clients&lt;span style="color:#ff7b72;font-weight:bold"&gt;-&amp;gt;&lt;/span&gt;GetViewRotation().Quaternion();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff7b72"&gt;break&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff7b72"&gt;else&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8b949e;font-weight:bold;font-style:italic"&gt;#endif&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#8b949e;font-style:italic"&gt;// Non EditorMode.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#8b949e;font-style:italic"&gt;// Use First PlayerCamera.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff7b72"&gt;if&lt;/span&gt; (&lt;span style="color:#ff7b72"&gt;auto&lt;/span&gt;&lt;span style="color:#ff7b72;font-weight:bold"&gt;*&lt;/span&gt; camera_manager &lt;span style="color:#ff7b72;font-weight:bold"&gt;=&lt;/span&gt; UGameplayStatics&lt;span style="color:#ff7b72;font-weight:bold"&gt;::&lt;/span&gt;GetPlayerCameraManager(world, &lt;span style="color:#a5d6ff"&gt;0&lt;/span&gt;))&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; GEngine&lt;span style="color:#ff7b72;font-weight:bold"&gt;-&amp;gt;&lt;/span&gt;GameViewport&lt;span style="color:#ff7b72;font-weight:bold"&gt;-&amp;gt;&lt;/span&gt;GetViewportSize(out_viewport_size);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; out_view_location &lt;span style="color:#ff7b72;font-weight:bold"&gt;=&lt;/span&gt; camera_manager&lt;span style="color:#ff7b72;font-weight:bold"&gt;-&amp;gt;&lt;/span&gt;GetCameraLocation();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; out_view_quat &lt;span style="color:#ff7b72;font-weight:bold"&gt;=&lt;/span&gt; camera_manager&lt;span style="color:#ff7b72;font-weight:bold"&gt;-&amp;gt;&lt;/span&gt;GetCameraRotation().Quaternion();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ff7b72"&gt;return&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;};&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff7b72"&gt;const&lt;/span&gt; UWorld&lt;span style="color:#ff7b72;font-weight:bold"&gt;*&lt;/span&gt; world &lt;span style="color:#ff7b72;font-weight:bold"&gt;=&lt;/span&gt; [&lt;span style="color:#f85149"&gt;ワールド&lt;/span&gt;];&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;FVector2D out_viewport_size;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;FVector out_view_location;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;FQuat out_view_quat;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8b949e;font-style:italic"&gt;// Get Info.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;GetCurrentViewportInfo(world, out_viewport_size, out_view_location, out_view_quat);&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;&#10;&lt;p&gt;&lt;a href="https://nagakagachi.hatenablog.com/entry/2021/11/06/201354"&gt;元のはてなブログ記事&lt;/a&gt;&lt;/p&gt;</description></item><item><title>ProjectRoot直下のShadersディレクトリをShaderIncludePathに追加するだけのPlugin [UE4]</title><link>https://nagakagachi.github.io/entry/2021/08/18/083000/</link><pubDate>Wed, 18 Aug 2021 08:30:00 +0900</pubDate><guid>https://nagakagachi.github.io/entry/2021/08/18/083000/</guid><description>&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;/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;p&gt;プロジェクトルート/Shaders をUEのShaderIncludePathに自動追加する&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;br /&gt;&#10;&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/UE4"&gt;UE4&lt;/a&gt;.25辺りからマテリアルのCustomノードで Include File Paths を指定して外部シェーダファイルをインクルードして利用できるようになったが,インクルードパスの設定が面倒だったので勉強ついでに自分用自動化&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;/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;iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fnagakagachi%2Fue4%2Ftree%2Fmaster%2FPlugin%2FNglShaderIncludePlugin" title="ue4/Plugin/NglShaderIncludePlugin 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/Plugin/NglShaderIncludePlugin"&gt;github.com&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;1. &lt;b&gt;zipを解凍してできたNglShaderIncludePluginを ProjectRoot/Plugins にコピー.&lt;/b&gt;&lt;br /&gt;&#10;2. &lt;b&gt;ProjectRoot/Shaders &lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8"&gt;ディレクト&lt;/a&gt;リにCustomノードで使いたい ush を配置.&lt;/b&gt;&lt;/p&gt;&#10;&lt;pre class="code c++" data-lang="c++" data-unlink&gt;// テストで用意した IncludeTest.ush というファイル&#10;#pragma once&#10;float3 Func00()&#10;{&#10; return float3(1.0, 0.0, 0.0);&#10;}&lt;/pre&gt;&lt;p&gt;3. &lt;b&gt;マテリアルのCustomノードの Include File Paths に "/Project/filename.ush" を入力.&lt;/b&gt;&lt;/p&gt;&#10;&lt;figure class="figure-image figure-image-fotolife" title="Customノード例"&gt;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/6f671447c4dd4e8b946a6de2ed046a4bd43542906b659231433e4b9ef528501e.png" alt="f:id:nagakagachi:20210818012316p:plain" width="1039" height="876" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;figcaption&gt;Customノード例&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;4. &lt;b&gt;Customノードでインクルードしたushの関数などが利用できるようになる. &lt;/b&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;UEプロジェクト起動時に Shaders &lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8"&gt;ディレクト&lt;/a&gt;リが存在しないと以下のような警告がログに出力されるので&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8"&gt;ディレクト&lt;/a&gt;リを作成するように.&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;LogTemp: Warning: [FNglShaderIncludePluginModule] directory [ProjectRoot/Shaders] does not exist.&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;p&gt;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/39be8a695b54791eb55ea1e611245b63bc991cc35fac0710945f927fd9ece0dc.png" alt="f:id:nagakagachi:20210818003947p:plain" width="1080" height="429" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;/p&gt;&#10;&lt;/div&gt;</description></item><item><title>行優先と列優先のはなし(row-major, column-major)</title><link>https://nagakagachi.github.io/entry/2021/07/02/213944/</link><pubDate>Fri, 02 Jul 2021 21:39:44 +0900</pubDate><guid>https://nagakagachi.github.io/entry/2021/07/02/213944/</guid><description>&lt;p&gt;今ひとつ完全理解に至っていなかったので自分の言葉で残しておく&lt;br /&gt;&#10;間違ってたら&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/%CD%C5%C0%BA%A4%B5%A4%F3"&gt;妖精さん&lt;/a&gt;が直してくれる&lt;/p&gt;&lt;p&gt;(WEB上にたくさんある有用な記事を読んでわかる方は当記事をこれ以上読む必要は無い)&lt;br /&gt;&#10;&lt;a href="https://docs.microsoft.com/ja-jp/windows/win32/direct3dhlsl/dx-graphics-hlsl-per-component-math"&gt;Per-Component &amp;#x7B97;&amp;#x8853;&amp;#x6F14;&amp;#x7B97; - Win32 apps | Microsoft Learn&lt;/a&gt;&lt;/p&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3 id="行列の要素と演算"&gt;行列の要素と演算&lt;/h3&gt;&#10;&lt;p&gt;行列の行と列の意味や行列要素の位置はrow-majorでもcolumn-majorでも変わることはない&lt;/p&gt;&#10;&lt;p&gt;行とは行列の横方向のラインであるし、列は縦方向のラインである&lt;/p&gt;&#10;&lt;p&gt;mat._11は1行目1列目の要素であり、mat._42は4行目2列目の要素である&lt;/p&gt;&#10;&lt;p&gt;行列とベクトルの乗算のルールもrow-majorでもcolumn-majorで変わることはない&lt;/p&gt;&#10;&lt;p&gt;(ただしHLSL等ではベクトルは演算の位置によって適宜列ベクトルや行ベクトルに読み替えられる)&lt;/p&gt;&#10;&lt;pre class="code c++" data-lang="c++" data-unlink&gt;V1 = M * V0; // Matrix4x4とVec4&lt;/pre&gt;&#10;&lt;p&gt;は&lt;/p&gt;&#10;&lt;pre class="code c++" data-lang="c++" data-unlink&gt;V1.x = M._11 * V0.x + M._12 * V0.y + M._13 * V0.y + M._14 * V0.w&#10;V1.y = M._21 * V0.x + M._22 * V0.y + M._23 * V0.y + M._24 * V0.w&#10;V1.z = M._31 * V0.x + M._32 * V0.y + M._33 * V0.y + M._34 * V0.w&#10;V1.w = M._41 * V0.x + M._42 * V0.y + M._43 * V0.y + M._44 * V0.w&lt;/pre&gt;&#10;&lt;p&gt;であり、&lt;/p&gt;&#10;&lt;pre class="code c++" data-lang="c++" data-unlink&gt;V1 = V0 * M; // Matrix4x4とVec4&lt;/pre&gt;&#10;&lt;p&gt;は&lt;/p&gt;&#10;&lt;pre class="code c++" data-lang="c++" data-unlink&gt;V1.x = M._11 * V0.x + M._21 * V0.y + M._31 * V0.y + M._41 * V0.w&#10;V1.y = M._12 * V0.x + M._22 * V0.y + M._32 * V0.y + M._42 * V0.w&#10;V1.z = M._13 * V0.x + M._23 * V0.y + M._33 * V0.y + M._43 * V0.w&#10;V1.w = M._14 * V0.x + M._24 * V0.y + M._34 * V0.y + M._44 * V0.w&lt;/pre&gt;&#10;&lt;p&gt;である&lt;/p&gt;&#10;&lt;/div&gt;</description></item><item><title>Houdini HDK ビルドメモ (18.0.460)</title><link>https://nagakagachi.github.io/entry/2020/05/24/190639/</link><pubDate>Sun, 24 May 2020 19:06:39 +0900</pubDate><guid>https://nagakagachi.github.io/entry/2020/05/24/190639/</guid><description>&lt;p&gt;HDK(&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/C%2B%2B"&gt;C++&lt;/a&gt;)のサンプルについてcmakeでVisualStudioプロジェクトを作成してビルドする機会があったのでメモ.&lt;br /&gt;&#10;&lt;b&gt;注意:ビルドが成功してdllが作成されるところまでの確認しかしていない(未実行).&lt;/b&gt;&lt;/p&gt;&lt;br /&gt;&#10;&lt;p&gt;Houdini 18.0.460&lt;/p&gt;&#10;&lt;p&gt;VisualStudio 2017&lt;/p&gt;&#10;&lt;p&gt;対象のサンプルは SOP_Star&lt;/p&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3 id="事前準備"&gt;事前準備&lt;/h3&gt;&#10;&lt;p&gt;Houdiniインストール&lt;/p&gt;&#10;&lt;p&gt;VisualStudioインストール&lt;/p&gt;&#10;&lt;p&gt;cmake インストール&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;Houdiniインストール&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8"&gt;ディレクト&lt;/a&gt;リのtoolkit&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8"&gt;ディレクト&lt;/a&gt;リを丸ごと適当な&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8"&gt;ディレクト&lt;/a&gt;リにコピー(Documentsなど)&lt;/p&gt;&lt;p&gt;&lt;u&gt;コピー元&lt;/u&gt;&lt;br /&gt;&#10;C:/Program Files/Side Effects Software/Houdini 18.0.460/toolkit&lt;/p&gt;&lt;p&gt;&lt;u&gt;コピー先&lt;/u&gt;&lt;br /&gt;&#10;Documents等&lt;/p&gt;&lt;p&gt;以降はコピー先&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8"&gt;ディレクト&lt;/a&gt;リで作業する&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3&gt;対象のサンプル&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8"&gt;ディレクト&lt;/a&gt;リへ移動&lt;/h3&gt;&#10;&lt;p&gt;初期だと以下のような状態のはず&lt;br /&gt;&#10;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/71e22c4f03af5759aaee6fc13b8d66cc5c71144cb65389e9ef130de00fff4f2d.png" alt="f:id:nagakagachi:20200524181238p:plain" title="f:id:nagakagachi:20200524181238p:plain" 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;h3&gt;VisualStudioプロジェクト作成用&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8"&gt;ディレクト&lt;/a&gt;リ作成&lt;/h3&gt;&#10;&lt;p&gt;cmakeで作成するプロジェクトファイル群を入れる&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8"&gt;ディレクト&lt;/a&gt;リを適当な名前で作成(ここではbuildという名前)&lt;br /&gt;&#10;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/7a4ddea87d4d59ce6ecae61252fb0777c7ae226446f250e23514dbde6804f64e.png" alt="f:id:nagakagachi:20200524181336p:plain" title="f:id:nagakagachi:20200524181336p:plain" 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;h3 id="houdini-command-line-tools-起動"&gt;Houdini Command Line Tools 起動&lt;/h3&gt;&#10;&lt;p&gt;Houdiniの&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%DE%A5%F3%A5%C9%A5%E9%A5%A4%A5%F3"&gt;コマンドライン&lt;/a&gt;ツールHoudini Command Line Tools(以降Command Line)を起動&lt;figure class="figure-image figure-image-fotolife" title="Houdini Command Line Tools"&gt;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/fbc260599f9d90c243dcc795f75a82d2f7903ca5b9c906804c9d1e00e5e0b451.png" alt="f:id:nagakagachi:20200524175758p:plain" title="f:id:nagakagachi:20200524175758p:plain" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;figcaption&gt;Houdini Command Line Tools&lt;/figcaption&gt;&lt;/figure&gt;&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3&gt;プロジェクト作成&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8"&gt;ディレクト&lt;/a&gt;リに移動(Command Line)&lt;/h3&gt;&#10;&lt;p&gt;SOP_Star&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8"&gt;ディレクト&lt;/a&gt;リに作成したbuild&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8"&gt;ディレクト&lt;/a&gt;リに移動&lt;/p&gt;&lt;p&gt;cd /d "作業&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8"&gt;ディレクト&lt;/a&gt;リ"/toolkit/samples/SOP/SOP_Star/build&lt;br /&gt;&#10;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/c9468b8dcddfc4610cdae5577404bc4ec017d6e85c2ce6daad0a57699e79ed11.png" alt="f:id:nagakagachi:20200524181857p:plain" title="f:id:nagakagachi:20200524181857p:plain" 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;h3 id="cmakeコマンドでvisualstudioプロジェクト作成command-line"&gt;cmakeコマンドでVisualStudioプロジェクト作成(Command Line)&lt;/h3&gt;&#10;&lt;p&gt;cmakeに -G オプションで作成したいVisualStudioプロジェクトのバージョンを指定して実行する&lt;/p&gt;&#10;&lt;p&gt;cmake -help でマシンでサポートされているバージョン一覧が表示されるので参考に&lt;/p&gt;&#10;&lt;p&gt;今回はVisualStudio2017の64bitビルドプロジェクトを作りたいので以下のように指定&lt;/p&gt;&#10;&lt;p&gt;cmake -G "&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/Visual%20Studio"&gt;Visual Studio&lt;/a&gt; 15 2017 &lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/Win64"&gt;Win64&lt;/a&gt;" ..&lt;br /&gt;&#10;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/e1f5685ea303843ddc83b457291141eaf329caf64ca5ef51109b1b322795b087.png" alt="f:id:nagakagachi:20200524182709p:plain" title="f:id:nagakagachi:20200524182709p:plain" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;実行すると以下のようなログが流れる&lt;figure class="figure-image figure-image-fotolife" title="cmake実行結果"&gt;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/4e1e4ad5822336b0d024b3df06fda591ab88c0f3a5e6e9739d14783fb4005861.png" alt="f:id:nagakagachi:20200524182757p:plain" title="f:id:nagakagachi:20200524182757p:plain" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;figcaption&gt;cmake実行結果&lt;/figcaption&gt;&lt;/figure&gt;&lt;/p&gt;&lt;p&gt;成功すると実行した&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8"&gt;ディレクト&lt;/a&gt;リ(ここではbuild)に以下のようにVisualStudioソリューションファイルが作成される&lt;br /&gt;&#10;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/005e3084ae4a1465568cdc67ddd924586221c33e5b1559cab54ef2921ecc8a29.png" alt="f:id:nagakagachi:20200524183016p:plain" title="f:id:nagakagachi:20200524183016p:plain" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;br /&gt;&#10;&lt;/p&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><item><title>UE4 翻訳メモ Mesh Drawing Pipeline Conversion Guide for Unreal Engine 4.22</title><link>https://nagakagachi.github.io/entry/2019/04/18/150522/</link><pubDate>Thu, 18 Apr 2019 15:05:22 +0900</pubDate><guid>https://nagakagachi.github.io/entry/2019/04/18/150522/</guid><description>&lt;p&gt;4.22で大幅に変更されたらしいメッシュ描画パイプラインのドキュメントを&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/Google%CB%DD%CC%F5"&gt;Google翻訳&lt;/a&gt;先生の力を借りて翻訳しつつメモ&lt;/p&gt;&lt;p&gt;&lt;iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fdocs.unrealengine.com%2Fen-us%2FProgramming%2FRendering%2FMeshDrawingPipeline%2F4_22_ConversionGuide" title="Mesh Drawing Pipeline Conversion Guide for Unreal Engine 4.22" 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://docs.unrealengine.com/en-us/Programming/Rendering/MeshDrawingPipeline/4_22_ConversionGuide"&gt;docs.unrealengine.com&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;&lt;p&gt;より詳細は&lt;br /&gt;&#10;&lt;iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fdocs.unrealengine.com%2Fen-us%2FProgramming%2FRendering%2FMeshDrawingPipeline" title="Mesh Drawing Pipeline" 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://docs.unrealengine.com/en-us/Programming/Rendering/MeshDrawingPipeline"&gt;docs.unrealengine.com&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&#10;や&lt;br /&gt;&#10;&lt;iframe width="480" height="270" src="https://www.youtube.com/embed/qx1c190aGhs?feature=oembed" frameborder="0" allow="accelerometer; autoplay; 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?time_continue=526&amp;v=qx1c190aGhs"&gt;www.youtube.com&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&#10;を参照&lt;br /&gt;&#10;&lt;br /&gt;&#10;&lt;br /&gt;&#10;&lt;/p&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3 id="introduction"&gt;Introduction&lt;/h3&gt;&#10;&lt;p&gt;&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/Unreal%20Engine"&gt;Unreal Engine&lt;/a&gt;（&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/UE4"&gt;UE4&lt;/a&gt;）4.22リリースでは、Mesh Drawing Pipelineは完全に書き直されました。主な変更点は、フレーム毎に描画の準備をするImmediate Mode からすべてのシーン描画が事前に準備される Retained Mode に移行したことです。これは、シーン全体のシェーダ&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%F3%A5%C7%A5%A3%A5%F3%A5%B0"&gt;バインディング&lt;/a&gt;テーブルを必要とする&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/DirectX"&gt;DirectX&lt;/a&gt; Raytracing（DXR）や、CPUが可視性の情報無しに描画の準備をする必要がある &lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/GPU"&gt;GPU&lt;/a&gt;-Driven-Rendering など、今後のテク&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%CE%A5%ED"&gt;ノロ&lt;/a&gt;ジをサポートできるようになるための重要な変更です。&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/UE4"&gt;UE4&lt;/a&gt; 4.22でのMesh Drawing Pipelineの変更についての詳細は、Mesh Drawing PipelineのドキュメントおよびGame Developer's Conference（&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/GDC"&gt;GDC&lt;/a&gt;）のプレゼンテーション&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/Unreal%20Engine"&gt;Unreal Engine&lt;/a&gt; 4.22用Mesh Drawing Pipelineの&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%D5%A5%A1%A5%AF%A5%BF%A5%EA%A5%F3%A5%B0"&gt;リファクタリング&lt;/a&gt;を参照してください。&lt;/p&gt;</description></item><item><title> UE4 TArrayのSetNumZeroedふるまいメモ</title><link>https://nagakagachi.github.io/entry/2018/08/26/163803/</link><pubDate>Sun, 26 Aug 2018 16:38:03 +0900</pubDate><guid>https://nagakagachi.github.io/entry/2018/08/26/163803/</guid><description>&lt;p&gt;&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/UE4"&gt;UE4&lt;/a&gt;.20.2&lt;/p&gt;&lt;p&gt;&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/UE4"&gt;UE4&lt;/a&gt;のCodePluginでTArrayを多用していていつもSetNumZeroedの挙動を忘れるのでメモ&lt;/p&gt;&lt;br /&gt;&#10;&lt;p&gt;TArray::SetNumZeroed(NewSize, bAllowShrinking)&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;SetNumZeroed()によって要&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%C1%C7%BF%F4"&gt;素数&lt;/a&gt;が増える場合&#10;&lt;ul&gt;&#10;&lt;li&gt;ゼロ値要素が末尾に付加される。元の要素は変化しない。&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&lt;pre class="code" data-lang="" data-unlink&gt;TArray&amp;lt;float&amp;gt; testArray;&#10;testArray.Add(1.0f);&#10;testArray.Add(2.0f);&#10;testArray.Add(3.0f); // { 1.0, 2.0, 3.0 }&#10;testArray.SetNumZeroed(5); // { 1.0, 2.0, 3.0, 0.0, 0.0 }&lt;/pre&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;SetNumZeroed()によって要&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%C1%C7%BF%F4"&gt;素数&lt;/a&gt;が減る場合&#10;&lt;ul&gt;&#10;&lt;li&gt;単純に切り詰められる。元の要素は変化しない。&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&lt;pre class="code" data-lang="" data-unlink&gt;TArray&amp;lt;float&amp;gt; testArray;&#10;testArray.Add(1.0f);&#10;testArray.Add(2.0f);&#10;testArray.Add(3.0f); // { 1.0, 2.0, 3.0 }&#10;testArray.SetNumZeroed(1); // { 1.0 }&lt;/pre&gt;&lt;p&gt;&lt;br /&gt;&#10;関係ないけどTArray&lt;float&gt;の要素を指定した値（ゼロとか）にするメソッドがほしい&lt;br /&gt;&#10;（ないよね？）&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;p&gt;&lt;a href="https://nagakagachi.hatenablog.com/entry/2018/08/26/163803"&gt;元のはてなブログ記事&lt;/a&gt;&lt;/p&gt;</description></item></channel></rss>