<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>UE4 on ながむしメモ</title><link>https://nagakagachi.github.io/categories/ue4/</link><description>Recent content in UE4 on ながむしメモ</description><generator>Hugo</generator><language>ja-JP</language><lastBuildDate>Wed, 26 Jul 2023 13:52:33 +0900</lastBuildDate><atom:link href="https://nagakagachi.github.io/categories/ue4/index.xml" rel="self" type="application/rss+xml"/><item><title>Simplex頂点に任意の乱数を利用できるSimplex Noise Custom Node[UE][UE5]</title><link>https://nagakagachi.github.io/entry/2023/07/26/135233/</link><pubDate>Wed, 26 Jul 2023 13:52:33 +0900</pubDate><guid>https://nagakagachi.github.io/entry/2023/07/26/135233/</guid><description>&lt;p&gt;題名の通りです.&lt;/p&gt;&#10;&lt;p&gt;個人的な興味により Simplex Noiseの頂点毎の乱数計算 を差し替えられるCustomNodeを作成したので公開.&lt;/p&gt;&#10;&lt;p&gt;Simplex Noise には以下のShadertoyを参考にしています. thanks!&lt;br /&gt;&#10;&lt;a href="https://www.shadertoy.com/view/XsX3zB"&gt;https://www.shadertoy.com/view/XsX3zB&lt;/a&gt;&lt;br /&gt;&#10;(XsX3zB)&lt;/p&gt;&lt;p&gt;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/6341e8500430eef917d544f8bbfdce4695c1a4c941362eaa86570ca9392d3d32.png" width="1200" height="896" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&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="#前処理CustomNode"&gt;前処理CustomNode&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#乱数CustomNode-3D座標から3D乱数出力ができるものに置き換え可能"&gt;乱数CustomNode (3D座標から3D乱数出力ができるものに置き換え可能)&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#後処理CustomNode"&gt;後処理CustomNode&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;ul&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;div class="section"&gt;&#10;&lt;h3 id="前置き"&gt;前置き&lt;/h3&gt;&#10;&lt;p&gt;CustomNodeは3段階(コア部分は2段階)で,&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;前処理&#10;&lt;ul&gt;&#10;&lt;li&gt;Simplexの頂点情報他を出力&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;li&gt;乱数ノード&#10;&lt;ul&gt;&#10;&lt;li&gt;(ここが任意に差し替え可)&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;li&gt;後処理&#10;&lt;ul&gt;&#10;&lt;li&gt;Simplex頂点の乱数からノイズ出力&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;という構成です.&lt;/p&gt;&#10;&lt;p&gt;使用例としては以下のようになります.&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/1a45015452350cb2918ce03f7060bd4fc083c8bcfcac3def2bc52f7e6b2fcb22.png" width="1200" height="454" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;figcaption&gt;使用例&lt;/figcaption&gt;&lt;/figure&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/Twitter"&gt;Twitter&lt;/a&gt;等でお知らせください.&lt;/p&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h4 id="前処理CustomNode"&gt;前処理CustomNode&lt;/h4&gt;&#10;&lt;p&gt;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/e250ef305152f57f40e7c94ccbcb91414348dc489a18cd1ec49f4181f0ad3e60.png" width="381" height="386" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;/p&gt;&#10;&lt;pre class="code lang-hlsl" data-lang="hlsl" data-unlink&gt;Begin Object Class=/Script/UnrealEd.MaterialGraphNode Name=&lt;span class="synConstant"&gt;&amp;quot;MaterialGraphNode_109&amp;quot;&lt;/span&gt;&#10; Begin Object Class=/Script/Engine.MaterialExpressionCustom Name=&lt;span class="synConstant"&gt;&amp;quot;MaterialExpressionCustom_0&amp;quot;&lt;/span&gt;&#10; End Object&#10; Begin Object Name=&lt;span class="synConstant"&gt;&amp;quot;MaterialExpressionCustom_0&amp;quot;&lt;/span&gt;&#10; Code=&lt;span class="synConstant"&gt;&amp;quot;&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt;/*&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt; 3D SimplexNoise の前段処理&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt;[Reference materials]&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt;https://www.shadertoy.com/view/XsX3zB&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n\r\n\r\n&lt;/span&gt;&lt;span class="synConstant"&gt; input:&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt; // ノイズ計算座標.&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt; in_pos&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="synConstant"&gt; output:&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt; // Simplex(3DではTetrahedron)の頂点座標&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt; out_simplex_vtx_pos0&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt; out_simplex_vtx_pos1&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt; out_simplex_vtx_pos2&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt; out_simplex_vtx_pos3&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt; &lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt; // Simplexの頂点へのベクトル. 後段でのGradientNoise計算用.&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt; out_simplex_d0&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt; out_simplex_d1&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt; out_simplex_d2&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt; out_simplex_d3&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="synConstant"&gt;*/&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="synConstant"&gt;const float F3 = 0.33333;&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt;const float G3 = 0.16667;&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt;// Skew&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt;float3 s = floor(in_pos + dot(in_pos, F3));&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt;float3 x = in_pos - s + dot(s, G3);&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt;//&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt;float3 e = step(0.0, x - x.yzx);&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt;float3 i1 = e * (1.0 - e.zxy);&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt;float3 i2 = 1.0 - e.zxy*(1.0-e);&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="synConstant"&gt;//&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt;float3 x1 = x - i1 + G3;&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt;float3 x2 = x - i2 + 2.0 * G3;&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt;float3 x3 = x - 1.0 + 3.0*G3;&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="synConstant"&gt;out_simplex_vtx_pos0 = s;&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt;out_simplex_vtx_pos1 = s + i1;&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt;out_simplex_vtx_pos2 = s + i2;&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt;out_simplex_vtx_pos3 = s + 1;&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="synConstant"&gt;out_simplex_d0 = x;&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt;out_simplex_d1 = x1;&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt;out_simplex_d2 = x2;&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt;out_simplex_d3 = x3;&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="synConstant"&gt;return 1;&amp;quot;&lt;/span&gt;&#10; Description=&lt;span class="synConstant"&gt;&amp;quot;Custom_SimplexNoise3to1_Setup&amp;quot;&lt;/span&gt;&#10; &lt;span class="synIdentifier"&gt;Inputs&lt;/span&gt;(&lt;span class="synConstant"&gt;0&lt;/span&gt;)=(InputName=&lt;span class="synConstant"&gt;&amp;quot;in_pos&amp;quot;&lt;/span&gt;,Input=(Expression=/Script/Engine.MaterialExpressionAdd'&lt;span class="synConstant"&gt;&amp;quot;MaterialExpressionAdd_5&amp;quot;&lt;/span&gt;'))&#10; &lt;span class="synIdentifier"&gt;AdditionalOutputs&lt;/span&gt;(&lt;span class="synConstant"&gt;0&lt;/span&gt;)=(OutputName=&lt;span class="synConstant"&gt;&amp;quot;out_simplex_vtx_pos0&amp;quot;&lt;/span&gt;,OutputType=CMOT_Float3)&#10; &lt;span class="synIdentifier"&gt;AdditionalOutputs&lt;/span&gt;(&lt;span class="synConstant"&gt;1&lt;/span&gt;)=(OutputName=&lt;span class="synConstant"&gt;&amp;quot;out_simplex_vtx_pos1&amp;quot;&lt;/span&gt;,OutputType=CMOT_Float3)&#10; &lt;span class="synIdentifier"&gt;AdditionalOutputs&lt;/span&gt;(&lt;span class="synConstant"&gt;2&lt;/span&gt;)=(OutputName=&lt;span class="synConstant"&gt;&amp;quot;out_simplex_vtx_pos2&amp;quot;&lt;/span&gt;,OutputType=CMOT_Float3)&#10; &lt;span class="synIdentifier"&gt;AdditionalOutputs&lt;/span&gt;(&lt;span class="synConstant"&gt;3&lt;/span&gt;)=(OutputName=&lt;span class="synConstant"&gt;&amp;quot;out_simplex_vtx_pos3&amp;quot;&lt;/span&gt;,OutputType=CMOT_Float3)&#10; &lt;span class="synIdentifier"&gt;AdditionalOutputs&lt;/span&gt;(&lt;span class="synConstant"&gt;4&lt;/span&gt;)=(OutputName=&lt;span class="synConstant"&gt;&amp;quot;out_simplex_d0&amp;quot;&lt;/span&gt;,OutputType=CMOT_Float3)&#10; &lt;span class="synIdentifier"&gt;AdditionalOutputs&lt;/span&gt;(&lt;span class="synConstant"&gt;5&lt;/span&gt;)=(OutputName=&lt;span class="synConstant"&gt;&amp;quot;out_simplex_d1&amp;quot;&lt;/span&gt;,OutputType=CMOT_Float3)&#10; &lt;span class="synIdentifier"&gt;AdditionalOutputs&lt;/span&gt;(&lt;span class="synConstant"&gt;6&lt;/span&gt;)=(OutputName=&lt;span class="synConstant"&gt;&amp;quot;out_simplex_d2&amp;quot;&lt;/span&gt;,OutputType=CMOT_Float3)&#10; &lt;span class="synIdentifier"&gt;AdditionalOutputs&lt;/span&gt;(&lt;span class="synConstant"&gt;7&lt;/span&gt;)=(OutputName=&lt;span class="synConstant"&gt;&amp;quot;out_simplex_d3&amp;quot;&lt;/span&gt;,OutputType=CMOT_Float3)&#10; MaterialExpressionEditorX=-&lt;span class="synConstant"&gt;2048&lt;/span&gt;&#10; MaterialExpressionEditorY=&lt;span class="synConstant"&gt;2512&lt;/span&gt;&#10; MaterialExpressionGuid=4244B9A4494561E6D73F14B3D48C4E67&#10; Material=/Script/UnrealEd.PreviewMaterial'&lt;span class="synConstant"&gt;&amp;quot;/Engine/Transient.M_InnerLayerPm2&amp;quot;&lt;/span&gt;'&#10; bShowOutputNameOnPin=True&#10; bCollapsed=True&#10; &lt;span class="synIdentifier"&gt;Outputs&lt;/span&gt;(&lt;span class="synConstant"&gt;0&lt;/span&gt;)=(OutputName=&lt;span class="synConstant"&gt;&amp;quot;return&amp;quot;&lt;/span&gt;)&#10; &lt;span class="synIdentifier"&gt;Outputs&lt;/span&gt;(&lt;span class="synConstant"&gt;1&lt;/span&gt;)=(OutputName=&lt;span class="synConstant"&gt;&amp;quot;out_simplex_vtx_pos0&amp;quot;&lt;/span&gt;)&#10; &lt;span class="synIdentifier"&gt;Outputs&lt;/span&gt;(&lt;span class="synConstant"&gt;2&lt;/span&gt;)=(OutputName=&lt;span class="synConstant"&gt;&amp;quot;out_simplex_vtx_pos1&amp;quot;&lt;/span&gt;)&#10; &lt;span class="synIdentifier"&gt;Outputs&lt;/span&gt;(&lt;span class="synConstant"&gt;3&lt;/span&gt;)=(OutputName=&lt;span class="synConstant"&gt;&amp;quot;out_simplex_vtx_pos2&amp;quot;&lt;/span&gt;)&#10; &lt;span class="synIdentifier"&gt;Outputs&lt;/span&gt;(&lt;span class="synConstant"&gt;4&lt;/span&gt;)=(OutputName=&lt;span class="synConstant"&gt;&amp;quot;out_simplex_vtx_pos3&amp;quot;&lt;/span&gt;)&#10; &lt;span class="synIdentifier"&gt;Outputs&lt;/span&gt;(&lt;span class="synConstant"&gt;5&lt;/span&gt;)=(OutputName=&lt;span class="synConstant"&gt;&amp;quot;out_simplex_d0&amp;quot;&lt;/span&gt;)&#10; &lt;span class="synIdentifier"&gt;Outputs&lt;/span&gt;(&lt;span class="synConstant"&gt;6&lt;/span&gt;)=(OutputName=&lt;span class="synConstant"&gt;&amp;quot;out_simplex_d1&amp;quot;&lt;/span&gt;)&#10; &lt;span class="synIdentifier"&gt;Outputs&lt;/span&gt;(&lt;span class="synConstant"&gt;7&lt;/span&gt;)=(OutputName=&lt;span class="synConstant"&gt;&amp;quot;out_simplex_d2&amp;quot;&lt;/span&gt;)&#10; &lt;span class="synIdentifier"&gt;Outputs&lt;/span&gt;(&lt;span class="synConstant"&gt;8&lt;/span&gt;)=(OutputName=&lt;span class="synConstant"&gt;&amp;quot;out_simplex_d3&amp;quot;&lt;/span&gt;)&#10; End Object&#10; MaterialExpression=/Script/Engine.MaterialExpressionCustom'&lt;span class="synConstant"&gt;&amp;quot;MaterialExpressionCustom_0&amp;quot;&lt;/span&gt;'&#10; NodePosX=-&lt;span class="synConstant"&gt;2048&lt;/span&gt;&#10; NodePosY=&lt;span class="synConstant"&gt;2512&lt;/span&gt;&#10; NodeGuid=694DDEB64074FA334F4FD9A71A7FD483&#10; CustomProperties &lt;span class="synIdentifier"&gt;Pin &lt;/span&gt;(PinId=14B3EA4E44D4A873700D33A55F7AE5AD,PinName=&lt;span class="synConstant"&gt;&amp;quot;in_pos&amp;quot;&lt;/span&gt;,PinType.PinCategory=&lt;span class="synConstant"&gt;&amp;quot;required&amp;quot;&lt;/span&gt;,PinType.PinSubCategory=&lt;span class="synConstant"&gt;&amp;quot;&amp;quot;&lt;/span&gt;,PinType.PinSubCategoryObject=&lt;span class="synConstant"&gt;None&lt;/span&gt;,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=&lt;span class="synConstant"&gt;None&lt;/span&gt;,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(MaterialGraphNode_103 &lt;span class="synConstant"&gt;5246F&lt;/span&gt;4EE4F841D0B87A775BDC4A8D155,),PersistentGuid=&lt;span class="synPreProc"&gt;0&lt;/span&gt;&lt;span class="synConstant"&gt;0000000000000000000000000000000&lt;/span&gt;,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)&#10; CustomProperties &lt;span class="synIdentifier"&gt;Pin &lt;/span&gt;(PinId=B819619E4D1A27419AB524893B6ECD84,PinName=&lt;span class="synConstant"&gt;&amp;quot;return&amp;quot;&lt;/span&gt;,Direction=&lt;span class="synConstant"&gt;&amp;quot;EGPD_Output&amp;quot;&lt;/span&gt;,PinType.PinCategory=&lt;span class="synConstant"&gt;&amp;quot;&amp;quot;&lt;/span&gt;,PinType.PinSubCategory=&lt;span class="synConstant"&gt;&amp;quot;&amp;quot;&lt;/span&gt;,PinType.PinSubCategoryObject=&lt;span class="synConstant"&gt;None&lt;/span&gt;,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=&lt;span class="synConstant"&gt;None&lt;/span&gt;,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,PersistentGuid=&lt;span class="synPreProc"&gt;0&lt;/span&gt;&lt;span class="synConstant"&gt;0000000000000000000000000000000&lt;/span&gt;,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)&#10; CustomProperties &lt;span class="synIdentifier"&gt;Pin &lt;/span&gt;(PinId=9EE1744F4571B813B1BBDE890386E4B4,PinName=&lt;span class="synConstant"&gt;&amp;quot;out_simplex_vtx_pos0&amp;quot;&lt;/span&gt;,Direction=&lt;span class="synConstant"&gt;&amp;quot;EGPD_Output&amp;quot;&lt;/span&gt;,PinType.PinCategory=&lt;span class="synConstant"&gt;&amp;quot;&amp;quot;&lt;/span&gt;,PinType.PinSubCategory=&lt;span class="synConstant"&gt;&amp;quot;&amp;quot;&lt;/span&gt;,PinType.PinSubCategoryObject=&lt;span class="synConstant"&gt;None&lt;/span&gt;,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=&lt;span class="synConstant"&gt;None&lt;/span&gt;,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(MaterialGraphNode_111 9D0A05744027353F9E7118A2194B1162,),PersistentGuid=&lt;span class="synPreProc"&gt;0&lt;/span&gt;&lt;span class="synConstant"&gt;0000000000000000000000000000000&lt;/span&gt;,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)&#10; CustomProperties &lt;span class="synIdentifier"&gt;Pin &lt;/span&gt;(PinId=1E152C9B4E3FDD460C71EBBD7728B4F5,PinName=&lt;span class="synConstant"&gt;&amp;quot;out_simplex_vtx_pos1&amp;quot;&lt;/span&gt;,Direction=&lt;span class="synConstant"&gt;&amp;quot;EGPD_Output&amp;quot;&lt;/span&gt;,PinType.PinCategory=&lt;span class="synConstant"&gt;&amp;quot;&amp;quot;&lt;/span&gt;,PinType.PinSubCategory=&lt;span class="synConstant"&gt;&amp;quot;&amp;quot;&lt;/span&gt;,PinType.PinSubCategoryObject=&lt;span class="synConstant"&gt;None&lt;/span&gt;,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=&lt;span class="synConstant"&gt;None&lt;/span&gt;,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(MaterialGraphNode_113 &lt;span class="synConstant"&gt;8126F&lt;/span&gt;F97480C0E2317A4F7A582DAD0A3,),PersistentGuid=&lt;span class="synPreProc"&gt;0&lt;/span&gt;&lt;span class="synConstant"&gt;0000000000000000000000000000000&lt;/span&gt;,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)&#10; CustomProperties &lt;span class="synIdentifier"&gt;Pin &lt;/span&gt;(PinId=EDB6385B40CB4F839646B784E3E9D173,PinName=&lt;span class="synConstant"&gt;&amp;quot;out_simplex_vtx_pos2&amp;quot;&lt;/span&gt;,Direction=&lt;span class="synConstant"&gt;&amp;quot;EGPD_Output&amp;quot;&lt;/span&gt;,PinType.PinCategory=&lt;span class="synConstant"&gt;&amp;quot;&amp;quot;&lt;/span&gt;,PinType.PinSubCategory=&lt;span class="synConstant"&gt;&amp;quot;&amp;quot;&lt;/span&gt;,PinType.PinSubCategoryObject=&lt;span class="synConstant"&gt;None&lt;/span&gt;,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=&lt;span class="synConstant"&gt;None&lt;/span&gt;,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(MaterialGraphNode_112 164ABAAD466D2377D81D0CA5A60C9B3C,),PersistentGuid=&lt;span class="synPreProc"&gt;0&lt;/span&gt;&lt;span class="synConstant"&gt;0000000000000000000000000000000&lt;/span&gt;,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)&#10; CustomProperties &lt;span class="synIdentifier"&gt;Pin &lt;/span&gt;(PinId=72873D064EE5FD985F001AA3892D9F49,PinName=&lt;span class="synConstant"&gt;&amp;quot;out_simplex_vtx_pos3&amp;quot;&lt;/span&gt;,Direction=&lt;span class="synConstant"&gt;&amp;quot;EGPD_Output&amp;quot;&lt;/span&gt;,PinType.PinCategory=&lt;span class="synConstant"&gt;&amp;quot;&amp;quot;&lt;/span&gt;,PinType.PinSubCategory=&lt;span class="synConstant"&gt;&amp;quot;&amp;quot;&lt;/span&gt;,PinType.PinSubCategoryObject=&lt;span class="synConstant"&gt;None&lt;/span&gt;,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=&lt;span class="synConstant"&gt;None&lt;/span&gt;,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(MaterialGraphNode_114 7D8DCA5C4A5DE0ACA7BD0C82724D301A,),PersistentGuid=&lt;span class="synPreProc"&gt;0&lt;/span&gt;&lt;span class="synConstant"&gt;0000000000000000000000000000000&lt;/span&gt;,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)&#10; CustomProperties &lt;span class="synIdentifier"&gt;Pin &lt;/span&gt;(PinId=7746174D4FB60AF7C5C5F095B5CA2773,PinName=&lt;span class="synConstant"&gt;&amp;quot;out_simplex_d0&amp;quot;&lt;/span&gt;,Direction=&lt;span class="synConstant"&gt;&amp;quot;EGPD_Output&amp;quot;&lt;/span&gt;,PinType.PinCategory=&lt;span class="synConstant"&gt;&amp;quot;&amp;quot;&lt;/span&gt;,PinType.PinSubCategory=&lt;span class="synConstant"&gt;&amp;quot;&amp;quot;&lt;/span&gt;,PinType.PinSubCategoryObject=&lt;span class="synConstant"&gt;None&lt;/span&gt;,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=&lt;span class="synConstant"&gt;None&lt;/span&gt;,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(MaterialGraphNode_110 DB76CCAB48E57973572CEC889D1AD7A3,),PersistentGuid=&lt;span class="synPreProc"&gt;0&lt;/span&gt;&lt;span class="synConstant"&gt;0000000000000000000000000000000&lt;/span&gt;,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)&#10; CustomProperties &lt;span class="synIdentifier"&gt;Pin &lt;/span&gt;(PinId=00AD30144201B89E1E00758A88479315,PinName=&lt;span class="synConstant"&gt;&amp;quot;out_simplex_d1&amp;quot;&lt;/span&gt;,Direction=&lt;span class="synConstant"&gt;&amp;quot;EGPD_Output&amp;quot;&lt;/span&gt;,PinType.PinCategory=&lt;span class="synConstant"&gt;&amp;quot;&amp;quot;&lt;/span&gt;,PinType.PinSubCategory=&lt;span class="synConstant"&gt;&amp;quot;&amp;quot;&lt;/span&gt;,PinType.PinSubCategoryObject=&lt;span class="synConstant"&gt;None&lt;/span&gt;,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=&lt;span class="synConstant"&gt;None&lt;/span&gt;,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(MaterialGraphNode_110 &lt;span class="synConstant"&gt;62F&lt;/span&gt;D7FB84275385A5AE2688318A0242F,),PersistentGuid=&lt;span class="synPreProc"&gt;0&lt;/span&gt;&lt;span class="synConstant"&gt;0000000000000000000000000000000&lt;/span&gt;,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)&#10; CustomProperties &lt;span class="synIdentifier"&gt;Pin &lt;/span&gt;(PinId=A101A4114BE2E007A7A9DE8B88751614,PinName=&lt;span class="synConstant"&gt;&amp;quot;out_simplex_d2&amp;quot;&lt;/span&gt;,Direction=&lt;span class="synConstant"&gt;&amp;quot;EGPD_Output&amp;quot;&lt;/span&gt;,PinType.PinCategory=&lt;span class="synConstant"&gt;&amp;quot;&amp;quot;&lt;/span&gt;,PinType.PinSubCategory=&lt;span class="synConstant"&gt;&amp;quot;&amp;quot;&lt;/span&gt;,PinType.PinSubCategoryObject=&lt;span class="synConstant"&gt;None&lt;/span&gt;,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=&lt;span class="synConstant"&gt;None&lt;/span&gt;,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(MaterialGraphNode_110 68133C4D4BE01D7D4C180184CC5A24C8,),PersistentGuid=&lt;span class="synPreProc"&gt;0&lt;/span&gt;&lt;span class="synConstant"&gt;0000000000000000000000000000000&lt;/span&gt;,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)&#10; CustomProperties &lt;span class="synIdentifier"&gt;Pin &lt;/span&gt;(PinId=CF20B6B54351C38C12EB46B59994524D,PinName=&lt;span class="synConstant"&gt;&amp;quot;out_simplex_d3&amp;quot;&lt;/span&gt;,Direction=&lt;span class="synConstant"&gt;&amp;quot;EGPD_Output&amp;quot;&lt;/span&gt;,PinType.PinCategory=&lt;span class="synConstant"&gt;&amp;quot;&amp;quot;&lt;/span&gt;,PinType.PinSubCategory=&lt;span class="synConstant"&gt;&amp;quot;&amp;quot;&lt;/span&gt;,PinType.PinSubCategoryObject=&lt;span class="synConstant"&gt;None&lt;/span&gt;,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=&lt;span class="synConstant"&gt;None&lt;/span&gt;,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(MaterialGraphNode_110 1419241C4116FF68392D659CFBE3035C,),PersistentGuid=&lt;span class="synPreProc"&gt;0&lt;/span&gt;&lt;span class="synConstant"&gt;0000000000000000000000000000000&lt;/span&gt;,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)&#10;End Object&#10;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h4 id="乱数CustomNode-3D座標から3D乱数出力ができるものに置き換え可能"&gt;乱数CustomNode (3D座標から3D乱数出力ができるものに置き換え可能)&lt;/h4&gt;&#10;&lt;p&gt;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/090f0c3bf42a233eab6c57b069cad5278d65b33a3b41b6e077285f7b51e60b76.png" width="305" height="160" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;/p&gt;</description></item><item><title>DepthPrepass有効時のCoplanar PolygonによるGPU負荷増大 [UE][Rendering]</title><link>https://nagakagachi.github.io/entry/2022/12/31/080000/</link><pubDate>Sat, 31 Dec 2022 08:00:00 +0900</pubDate><guid>https://nagakagachi.github.io/entry/2022/12/31/080000/</guid><description>&lt;p&gt;DepthPrepass&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%EC%A5%F3%A5%C0%A5%EA%A5%F3%A5%B0"&gt;レンダリング&lt;/a&gt;に関連して, &lt;br /&gt;モデルやレベルの作りによって&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/GPU"&gt;GPU&lt;/a&gt;負荷が増大してしまう特殊な状況について説明します.&lt;/p&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3 id="問題"&gt;問題&lt;/h3&gt;&#10;&lt;p&gt;同一平面で重なり合うポリゴン(&lt;em&gt;Coplanar Polygon&lt;/em&gt;)は, 重なりの数だけBasePass PixelShaderが実行される可能性があります.&lt;br /&gt;&lt;u&gt;これにより本来DepthPrepass環境で除去される不要なBasePass負荷が追加で発生します.&lt;/u&gt;&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;&lt;span style="font-size: 50%;"&gt;同一平面で重なり合うポリゴン を &lt;u&gt;Coplanar Polygon&lt;/u&gt; と呼んでいます.&lt;br /&gt;Lamina Faces や Z-Fighting状態のポリゴン というような表現もあると思います.&lt;br /&gt;もっと良い呼び名があれば教えてください!&lt;/span&gt;&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;p&gt;&lt;br /&gt;以下のサンプルシーンは&lt;u&gt;Opaque&lt;/u&gt;で適当ワールドノイズマテリアルのCubeをいくつか配置した状態です.&lt;br /&gt;よくOverDraw負荷が問題となる半透明が無いシーンなので安心と思いきや, 表示モードを「シェーダ複雑度」へ切り替えてみると.&lt;/p&gt;&#10;&lt;figure class="figure-image figure-image-fotolife" title="サンプルシーン"&gt;&lt;img src="images/c272dc256ecc74375b4877e418f9aece697a71c86bd6127d341d415a59f7952a.png" width="1200" height="819" loading="lazy" title="" class="hatena-fotolife" style="width: 250px;" itemprop="image" /&gt; &lt;img src="images/a677d850b9bfe572bc8a5c7266cf9e69dddd2dcab9c69a6e33f03b69da90597a.png" width="1200" height="814" loading="lazy" title="" class="hatena-fotolife" style="width: 250px;" itemprop="image" /&gt;&#10;&lt;figcaption&gt;サンプルシーン&lt;/figcaption&gt;&#10;&lt;/figure&gt;&#10;&lt;p&gt;&lt;u&gt;何故か高負荷を示す真っ白な部分があります&lt;/u&gt;.&lt;/p&gt;&#10;&lt;p&gt;RenderDocでキャプチャして 「&lt;u&gt;Quad Over Draw (Pass)&lt;/u&gt;」でOverDrawを確認します.&lt;/p&gt;&#10;&lt;figure class="figure-image figure-image-fotolife" title="RenderDoc Quad Over Draw (Pass)"&gt;&lt;img src="images/5581b84e591e4b8ad0c9549404a169faf37c5f1d03c470168dc9ee1e23b48d5a.png" width="1020" height="666" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /&gt;&#10;&lt;figcaption&gt;RenderDoc Quad Over Draw (Pass)&lt;/figcaption&gt;&#10;&lt;/figure&gt;&#10;&lt;p&gt;RenderDoc上でも確かに右側の配置でBasePassのOverDrawが発生しているようです.&lt;/p&gt;&#10;&lt;p&gt;BasePassではDeferredの場合はGBuffer書き込み, Forwardであれば複雑なLighting計算が実行されるため,本来実行されないはずのOpaqueでのBasePass OverDrawは&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/GPU"&gt;GPU&lt;/a&gt;負荷に大きな影響を与えます.&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3 id="原因"&gt;原因&lt;/h3&gt;&#10;&lt;p&gt;この問題の原因は深度が完全に一致するポリゴンが複数重なっている点と, DepthPrepass有りBasePassの仕組みの関係によるものです.&lt;/p&gt;&#10;&lt;p&gt;まずシーンの配置ですが, 左側の配置と同じ3つのCubeをポリゴンが重なるように配置しています &lt;a href="#f-9dd25646" id="fn-9dd25646" name="fn-9dd25646" title="1モデル内のポリゴン同士でも, レベルに配置した別モデルのポリゴン同士でも関係なくこの問題は発生します."&gt;*1&lt;/a&gt;.&lt;br /&gt;&lt;img src="images/86f7777de4998b3ffd7e612339bc77651597f293595d2c33f3f21683589a12c9.png" width="1200" height="817" loading="lazy" title="" class="hatena-fotolife" style="width: 250px;" itemprop="image" /&gt; &lt;img src="images/c48411fd5c3bc351c2e59974c39d4469d52a31f9e23dbb2a29b1f67fa3b605fb.png" width="1200" height="813" loading="lazy" title="" class="hatena-fotolife" style="width: 250px;" itemprop="image" /&gt;&lt;/p&gt;&#10;&lt;p&gt;このような状況では, DepthPrepass有効時のBasePassは重なり合ったポリゴンそれぞれについて全て実行されてしまい, 高負荷なBasePassが何度も実行されることにより&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/GPU"&gt;GPU&lt;/a&gt;負荷を増大させます.&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3 id="BasePassが複数回実行される理由"&gt;BasePassが複数回実行される理由&lt;/h3&gt;&#10;&lt;p&gt;本来のDepthPrepass手法は, DepthPreapssで先に生成したDepthBufferを頼りに, 各Meshの可視&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%D4%A5%AF%A5%BB%A5%EB"&gt;ピクセル&lt;/a&gt;のマテリアルBasePass PixelShaderだけを最小限実行することで高速化するためのものです.&lt;br /&gt;例として背景, 円柱, 板で構成されたシーンのDepthPrepass有りBasePassの挙動を以下に示します.&lt;br /&gt;右側図の緑色部分がDepthTestを通過してBasePassのPixelShaderが実行された&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%D4%A5%AF%A5%BB%A5%EB"&gt;ピクセル&lt;/a&gt;になります.&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;DepthPrepassでDepthBufferが完成&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;img src="images/59936b850442a7a395812d241e30d7fbdf9a56980124ad6698d1b70727d32ba8.png" width="1070" height="714" loading="lazy" title="" class="hatena-fotolife" style="width: 250px;" itemprop="image" /&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;円柱モデルBasePass描画&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;img src="images/0a300dab9c592601ce13587e02a2a295ec8497277f6896b50f330d7bd3997ca2.png" width="1068" height="711" loading="lazy" title="" class="hatena-fotolife" style="width: 250px;" itemprop="image" /&gt; &lt;img src="images/a43c6b573e3814646727af503df327c0499aa2723e377fab7ca90b0df466c219.png" width="1069" height="713" loading="lazy" title="" class="hatena-fotolife" style="width: 250px;" itemprop="image" /&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;背景モデルBasePass描画&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;img src="images/a51f5fb7597a3719fb354d1e0cada8730dccd901c7346a72f6e4c0744198105a.png" width="1070" height="714" loading="lazy" title="" class="hatena-fotolife" style="width: 250px;" itemprop="image" /&gt; &lt;img src="images/803ab8d758963f5b703032bfb6984ce851646438c5a167151baefa3f2d22dc78.png" width="1069" height="712" loading="lazy" title="" class="hatena-fotolife" style="width: 250px;" itemprop="image" /&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;板モデルBasePass描画&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;img src="images/536d0d26f787eb50b831f285ab440bd31a185067995c2c3b24adf697416e7c76.png" width="1071" height="712" loading="lazy" title="" class="hatena-fotolife" style="width: 250px;" itemprop="image" /&gt; &lt;img src="images/3269379750a785f5ea7673a9ba4273e00a4526ccb8514482654abfa5c4fce4ff.png" width="1070" height="712" loading="lazy" title="" class="hatena-fotolife" style="width: 250px;" itemprop="image" /&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;各モデルのBasePassが, 最終的に画面に見えている部分でだけ働いているのがわかると思います.&lt;br&gt;&#10;このようにBasePassが無駄に実行されないようにして高速化するというのがDepthPrepassの目的となります.&lt;/p&gt;&#10;&lt;p&gt;これを実現するためにBasePassは&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;DepthWrite=OFF 且つ DepthTest=GreaterEqual&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;p&gt;という設定をされます &lt;a href="#f-9b586fdf" id="fn-9b586fdf" name="fn-9b586fdf" title="GreaterEqualなのはReverseZ環境でのことで, StandardZの場合はLessEqualです."&gt;*2&lt;/a&gt;.&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;&lt;span style="font-size: 80%;"&gt;指摘がありましたので追記-&amp;gt; Maskedを含めたマテリアルをDepthPrePassを利用してEarlyZ有効で効率的に描画するために Equal なDepthTestで描画する場合があります. 本件のシーンではOpaqueを対象とし且つRenderDocキャプチャ等も確認したところGreaterEqualであったためこのように記述しています(UE5.3).&lt;/span&gt;&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;p&gt;この設定によって, 各モデルのBasePass描画では&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;DepthPrepassで確定した深度値に対して&lt;br /&gt;&lt;u&gt;&lt;strong&gt;同じか&lt;/strong&gt;&lt;/u&gt;それより近い場合にのみ描画する&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;p&gt;という挙動をすることになります.&lt;/p&gt;&#10;&lt;p&gt;この &lt;u&gt;&lt;strong&gt;同じかそれより近い&lt;/strong&gt;&lt;/u&gt; という点と, 深度が完全に一致してしまう Coplanar Polygon の関係によって今回のような問題が起きています.&lt;/p&gt;&#10;&lt;/div&gt;</description></item><item><title>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> TextureSampleGradのCustomNode</title><link>https://nagakagachi.github.io/entry/2021/12/31/193043/</link><pubDate>Fri, 31 Dec 2021 19:30:43 +0900</pubDate><guid>https://nagakagachi.github.io/entry/2021/12/31/193043/</guid><description>&lt;p&gt;UEのマテリアルでTextureからSampleGradでサンプリングするメモ.&lt;/p&gt;&#10;&lt;p&gt;これが2021年最後の記事. 良いお年を!&lt;/p&gt;&#10;&lt;ul class="table-of-contents"&gt;&#10;&lt;li&gt;&lt;a href="#CustomNodeの内容"&gt;CustomNodeの内容&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#CustomNodeコピペ用"&gt;CustomNodeコピペ用&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;p&gt;ノードとしてSampleGradが提供されていないようなので、CustomNodeでSampleGrad関数を直接呼ぶこととする.&lt;/p&gt;&#10;&lt;p&gt;(提供されているようならこの記事は見なかったことにしてください.)&lt;/p&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3 id="CustomNodeの内容"&gt;CustomNodeの内容&lt;/h3&gt;&#10;&lt;p&gt;TextureとUV, &lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/ddx"&gt;ddx&lt;/a&gt;, ddy を引数にとって内部で TextureSampleGrad関数を利用する.&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="synComment"&gt; Input&lt;/span&gt;&#10;&lt;span class="synComment"&gt; InTexture ( and InTextureSampler)&lt;/span&gt;&#10;&lt;span class="synComment"&gt; InUv&lt;/span&gt;&#10;&lt;span class="synComment"&gt; InDdx&lt;/span&gt;&#10;&lt;span class="synComment"&gt; InDdy&lt;/span&gt;&#10;&lt;span class="synComment"&gt; &lt;/span&gt;&#10;&lt;span class="synComment"&gt; Output&lt;/span&gt;&#10;&lt;span class="synComment"&gt; float4&lt;/span&gt;&#10;&lt;span class="synComment"&gt;*/&lt;/span&gt;&#10;&lt;p&gt;float4 tex = &lt;span class="synIdentifier"&gt;Texture2DSampleGrad&lt;/span&gt;(InTexture, InTextureSampler, InUv, InDdx, InDdy);&#10;&lt;span class="synStatement"&gt;return&lt;/span&gt; tex;&#10;&lt;/pre&gt;&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3 id="CustomNodeコピペ用"&gt;CustomNodeコピペ用&lt;/h3&gt;&#10;&lt;p&gt;コピペで利用したい場合は以下のテキストをマテリアルエディタに貼り付ければCustomNodeが生成される.&lt;/p&gt;&#10;&lt;pre class="code lang-cpp" data-lang="cpp" data-unlink&gt;&#10;Begin Object Class=/Script/UnrealEd.MaterialGraphNode Name=&lt;span class="synConstant"&gt;&amp;quot;MaterialGraphNode_21&amp;quot;&lt;/span&gt;&#10; Begin Object Class=/Script/Engine.MaterialExpressionCustom Name=&lt;span class="synConstant"&gt;&amp;quot;MaterialExpressionCustom_2&amp;quot;&lt;/span&gt;&#10; End Object&#10; Begin Object Name=&lt;span class="synConstant"&gt;&amp;quot;MaterialExpressionCustom_2&amp;quot;&lt;/span&gt;&#10; Code=&lt;span class="synConstant"&gt;&amp;quot;&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt;/*&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt; Input&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt; InTexture ( and InTextureSampler)&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt; InUv&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt; InDdx&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt; InDdy&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt; &lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt; Output&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt; float4&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt;*/&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="synConstant"&gt;float4 tex = Texture2DSampleGrad(InTexture, InTextureSampler, InUv, InDdx, InDdy);&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n&lt;/span&gt;&lt;span class="synConstant"&gt;return tex;&lt;/span&gt;&lt;span class="synSpecial"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="synConstant"&gt;&amp;quot;&lt;/span&gt;&#10; OutputType=CMOT_Float4&#10; &lt;span class="synIdentifier"&gt;Inputs&lt;/span&gt;(&lt;span class="synConstant"&gt;0&lt;/span&gt;)=(InputName=&lt;span class="synConstant"&gt;&amp;quot;InTexture&amp;quot;&lt;/span&gt;,Input=(Expression=MaterialExpressionTextureObjectParameter'&lt;span class="synConstant"&gt;&amp;quot;MaterialExpressionTextureObjectParameter_1&amp;quot;&lt;/span&gt;'))&#10; &lt;span class="synIdentifier"&gt;Inputs&lt;/span&gt;(&lt;span class="synConstant"&gt;1&lt;/span&gt;)=(InputName=&lt;span class="synConstant"&gt;&amp;quot;InUv&amp;quot;&lt;/span&gt;,Input=(Expression=MaterialExpressionReroute'&lt;span class="synConstant"&gt;&amp;quot;MaterialExpressionReroute_0&amp;quot;&lt;/span&gt;'))&#10; &lt;span class="synIdentifier"&gt;Inputs&lt;/span&gt;(&lt;span class="synConstant"&gt;2&lt;/span&gt;)=(InputName=&lt;span class="synConstant"&gt;&amp;quot;InDdx&amp;quot;&lt;/span&gt;,Input=(Expression=MaterialExpressionDDX'&lt;span class="synConstant"&gt;&amp;quot;MaterialExpressionDDX_0&amp;quot;&lt;/span&gt;'))&#10; &lt;span class="synIdentifier"&gt;Inputs&lt;/span&gt;(&lt;span class="synConstant"&gt;3&lt;/span&gt;)=(InputName=&lt;span class="synConstant"&gt;&amp;quot;InDdy&amp;quot;&lt;/span&gt;,Input=(Expression=MaterialExpressionDDY'&lt;span class="synConstant"&gt;&amp;quot;MaterialExpressionDDY_0&amp;quot;&lt;/span&gt;'))&#10; MaterialExpressionEditorX=-&lt;span class="synConstant"&gt;352&lt;/span&gt;&#10; MaterialExpressionEditorY=&lt;span class="synConstant"&gt;240&lt;/span&gt;&#10; MaterialExpressionGuid=A6C202464ABAD8F6E9734E9B54C6742D&#10; Material=PreviewMaterial'&lt;span class="synConstant"&gt;&amp;quot;/Engine/Transient.M_TexturePreview&amp;quot;&lt;/span&gt;'&#10; End Object&#10; MaterialExpression=MaterialExpressionCustom'&lt;span class="synConstant"&gt;&amp;quot;MaterialExpressionCustom_2&amp;quot;&lt;/span&gt;'&#10; NodePosX=-&lt;span class="synConstant"&gt;352&lt;/span&gt;&#10; NodePosY=&lt;span class="synConstant"&gt;240&lt;/span&gt;&#10; ErrorType=&lt;span class="synConstant"&gt;1&lt;/span&gt;&#10; ErrorMsg=&lt;span class="synConstant"&gt;&amp;quot;Custom material Custom missing input 1 (InTexture)&amp;quot;&lt;/span&gt;&#10; NodeGuid=98660A2E479B2DED7843C29DD7E144AB&#10; CustomProperties &lt;span class="synIdentifier"&gt;Pin &lt;/span&gt;(PinId=&lt;span class="synConstant"&gt;3F&lt;/span&gt;B004F94791B89E090EB9B99B713C0F,PinName=&lt;span class="synConstant"&gt;&amp;quot;InTexture&amp;quot;&lt;/span&gt;,PinType.PinCategory=&lt;span class="synConstant"&gt;&amp;quot;required&amp;quot;&lt;/span&gt;,PinType.PinSubCategory=&lt;span class="synConstant"&gt;&amp;quot;&amp;quot;&lt;/span&gt;,PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,LinkedTo=(MaterialGraphNode_83 FF18694A45E6BEAA46EA3F8C083A2CBC,),PersistentGuid=&lt;span class="synPreProc"&gt;0&lt;/span&gt;&lt;span class="synConstant"&gt;0000000000000000000000000000000&lt;/span&gt;,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)&#10; CustomProperties &lt;span class="synIdentifier"&gt;Pin &lt;/span&gt;(PinId=3E114E314D9BAB61118B329013A0C05A,PinName=&lt;span class="synConstant"&gt;&amp;quot;InUv&amp;quot;&lt;/span&gt;,PinType.PinCategory=&lt;span class="synConstant"&gt;&amp;quot;required&amp;quot;&lt;/span&gt;,PinType.PinSubCategory=&lt;span class="synConstant"&gt;&amp;quot;&amp;quot;&lt;/span&gt;,PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,LinkedTo=(MaterialGraphNode_Knot_7 &lt;span class="synConstant"&gt;18F&lt;/span&gt;E939F4A97C00C67CC16A085BED853,),PersistentGuid=&lt;span class="synPreProc"&gt;0&lt;/span&gt;&lt;span class="synConstant"&gt;0000000000000000000000000000000&lt;/span&gt;,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)&#10; CustomProperties &lt;span class="synIdentifier"&gt;Pin &lt;/span&gt;(PinId=B5C056784D5BAD800E83398A08AD56B8,PinName=&lt;span class="synConstant"&gt;&amp;quot;InDdx&amp;quot;&lt;/span&gt;,PinType.PinCategory=&lt;span class="synConstant"&gt;&amp;quot;required&amp;quot;&lt;/span&gt;,PinType.PinSubCategory=&lt;span class="synConstant"&gt;&amp;quot;&amp;quot;&lt;/span&gt;,PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,LinkedTo=(MaterialGraphNode_85 80EC1CDF4B3A1C9667D72EB37399E8C0,),PersistentGuid=&lt;span class="synPreProc"&gt;0&lt;/span&gt;&lt;span class="synConstant"&gt;0000000000000000000000000000000&lt;/span&gt;,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)&#10; CustomProperties &lt;span class="synIdentifier"&gt;Pin &lt;/span&gt;(PinId=905889CC49E11D9C88DB2792EF254574,PinName=&lt;span class="synConstant"&gt;&amp;quot;InDdy&amp;quot;&lt;/span&gt;,PinType.PinCategory=&lt;span class="synConstant"&gt;&amp;quot;required&amp;quot;&lt;/span&gt;,PinType.PinSubCategory=&lt;span class="synConstant"&gt;&amp;quot;&amp;quot;&lt;/span&gt;,PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,LinkedTo=(MaterialGraphNode_86 BBAD4B0443CF6057D92E17A5A0BB730A,),PersistentGuid=&lt;span class="synPreProc"&gt;0&lt;/span&gt;&lt;span class="synConstant"&gt;0000000000000000000000000000000&lt;/span&gt;,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)&#10; CustomProperties &lt;span class="synIdentifier"&gt;Pin &lt;/span&gt;(PinId=8EFEA7514110CC30D32E41B0B1689991,PinName=&lt;span class="synConstant"&gt;&amp;quot;Output&amp;quot;&lt;/span&gt;,PinFriendlyName=&lt;span class="synIdentifier"&gt;NSLOCTEXT&lt;/span&gt;(&lt;span class="synConstant"&gt;&amp;quot;MaterialGraphNode&amp;quot;&lt;/span&gt;, &lt;span class="synConstant"&gt;&amp;quot;Space&amp;quot;&lt;/span&gt;, &lt;span class="synConstant"&gt;&amp;quot; &amp;quot;&lt;/span&gt;),Direction=&lt;span class="synConstant"&gt;&amp;quot;EGPD_Output&amp;quot;&lt;/span&gt;,PinType.PinCategory=&lt;span class="synConstant"&gt;&amp;quot;&amp;quot;&lt;/span&gt;,PinType.PinSubCategory=&lt;span class="synConstant"&gt;&amp;quot;&amp;quot;&lt;/span&gt;,PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,LinkedTo=(MaterialGraphNode_Root_0 1653EE4D4D08EED8A95A3CA74981CFA2,),PersistentGuid=&lt;span class="synPreProc"&gt;0&lt;/span&gt;&lt;span class="synConstant"&gt;0000000000000000000000000000000&lt;/span&gt;,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)&#10;End Object&#10;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3 id="利用例"&gt;利用例&lt;/h3&gt;&#10;&lt;p&gt;TextureObjectとUV, &lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/ddx"&gt;ddx&lt;/a&gt;, ddy をCustomNodeに入力する.&lt;/p&gt;&#10;&lt;figure class="figure-image figure-image-fotolife" title="当記事のCustomNodeの利用例"&gt;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/2e3423d49d6483a9c5d2b66d4970c02ffe9d900ccf2d17fd49f8834aaa349200.png" alt="f:id:nagakagachi:20211231190816p:plain" width="1181" height="819" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;figcaption&gt;当記事のCustomNodeの利用例&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;/div&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> 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> 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>UE5の発表についてのメモ</title><link>https://nagakagachi.github.io/entry/2020/05/14/120000/</link><pubDate>Thu, 14 May 2020 12:00:00 +0900</pubDate><guid>https://nagakagachi.github.io/entry/2020/05/14/120000/</guid><description>&lt;p&gt;&lt;s&gt;In-house Engineでこれと戦わなきゃいけないってマジ？&lt;/s&gt;&lt;/p&gt;&lt;p&gt;PlayStation5 上で動作している &lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/Unreal%20Engine"&gt;Unreal Engine&lt;/a&gt; 5 のデモが発表されたので、この時点で感じたことなど覚えておくためにメモ。&lt;/p&gt;&lt;p&gt;目玉は動的GIシステムLumenと微細ジオメトリの&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%F3%A5%C0%A5%EA%A5%F3%A5%B0"&gt;レンダリング&lt;/a&gt;を実現するNanite。&lt;br /&gt;&#10;&lt;iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.unrealengine.com%2Fja%2Fblog%2Fa-first-look-at-unreal-engine-5%3Flang%3Dja" title="Unreal Engine 5 初公開" 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://www.unrealengine.com/ja/blog/a-first-look-at-unreal-engine-5?lang=ja"&gt;www.unrealengine.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="#Lumen-動的GI"&gt;Lumen (動的GI)&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#Nanite-仮想化マイクロポリゴンジオメトリ"&gt;Nanite (仮想化マイクロポリゴンジオメトリ)&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="#Niagara"&gt;Niagara&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="#Chaos"&gt;Chaos&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="Lumen-動的GI"&gt;Lumen (動的GI)&lt;/h3&gt;&#10;&lt;p&gt;動的なGlobal IlluminationシステムでDiffuse及びSpecular間接光を&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%F3%A5%C0%A5%EA%A5%F3%A5%B0"&gt;レンダリング&lt;/a&gt;する。&lt;br /&gt;&#10;動的なライトは最近のGIだと半分当然のようなところがあるが、動的なジオメトリはどこまでサポートされるのか気になる。&lt;br /&gt;&#10;レイトレハードウェアは使ってないらしいのでCompute Shaderによるものか、EnlightenのようにCPU側で非同期計算する方式なのか。&lt;figure class="figure-image figure-image-fotolife" title="LumenによるGI有効"&gt;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/680ed60850f8b2a6024cd37b26e36b24381350ceb4d4f9c9ee5dab290ed45f5f.png" alt="f:id:nagakagachi:20200514071027p:plain" title="f:id:nagakagachi:20200514071027p:plain" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;figcaption&gt;LumenによるGI有効&lt;/figcaption&gt;&lt;/figure&gt;&lt;figure class="figure-image figure-image-fotolife" title="GI無し"&gt;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/a84bdee9f74fb5bd111fbb0bfc1948a7a3f2229a6952b73f2cad6064cb25fa4f.png" alt="f:id:nagakagachi:20200514071116p:plain" title="f:id:nagakagachi:20200514071116p:plain" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;figcaption&gt;GI無し&lt;/figcaption&gt;&lt;/figure&gt;&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3 id="Nanite-仮想化マイクロポリゴンジオメトリ"&gt;Nanite (仮想化マイクロポリゴンジオメトリ)&lt;/h3&gt;&#10;&lt;p&gt;Texture-StreamingのようにジオメトリをStreamingし、&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D4%A5%AF%A5%BB%A5%EB"&gt;ピクセル&lt;/a&gt;レベルのジオメトリ描画を可能にする。&lt;br /&gt;&#10;デモでは10億Triを超えるソースジオメトリを、Naniteが適切にコン&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%ED%A1%BC%A5%EB"&gt;トロール&lt;/a&gt;して2000万Triのジオメトリを描画しているらしい。&lt;figure class="figure-image figure-image-fotolife" title="もはやノイズにしか見えないトライアングル群"&gt;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/1051d3b5480215bf9fb7c9b059eba35139f999b4c33708b3b913b4cf8322a03d.png" alt="f:id:nagakagachi:20200514070258p:plain" title="f:id:nagakagachi:20200514070258p:plain" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;figcaption&gt;もはやノイズにしか見えないトライアングル群&lt;/figcaption&gt;&lt;/figure&gt;DCCツールでの特別な作業は不要で、&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/ZBRush"&gt;ZBRush&lt;/a&gt;などで作ったものをそのままインポート可能。&lt;br /&gt;&#10;いままでNormalMapで表現していたディ&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C6%A5%A3%A1%BC"&gt;ティー&lt;/a&gt;ルをジオメトリによって直接表現する。&lt;br /&gt;&#10;LoDもNaniteがやってくれる。&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;div class="section"&gt;&#10;&lt;h3 id="Niagara"&gt;&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/Niagara"&gt;Niagara&lt;/a&gt;&lt;/h3&gt;&#10;&lt;p&gt;エフェクト以外にもコウモリや蟲の群れなどにも&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/Niagara"&gt;Niagara&lt;/a&gt;を利用している。&lt;br /&gt;&#10;パーティクル同士の通信や環境の知覚などもできるらしい。&lt;br /&gt;&#10;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/e72ea0bc52f8a0fecd0a8166001aba95939376e4dc15fe84d85df347bd52e3e8.png" alt="f:id:nagakagachi:20200514072020p:plain" title="f:id:nagakagachi:20200514072020p: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="流体シミュレーション"&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/c7d7a0b043b5c9918422647928809b18d6bed35a60e1f489f9c0ef0723678e35.png" alt="f:id:nagakagachi:20200514072246p:plain" title="f:id:nagakagachi:20200514072246p: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="Chaos"&gt;Chaos&lt;/h3&gt;&#10;&lt;p&gt;スカーフのClothシミュレーションや落石にはChaosを使用。&lt;br /&gt;&#10;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/869cc4ea7f5c126866c715ab15a729a2a74db68e34e1bc52ae05293ed2d12b03.png" alt="f:id:nagakagachi:20200514072548p:plain" title="f:id:nagakagachi:20200514072548p: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 周期的なリムエミッシブ</title><link>https://nagakagachi.github.io/entry/2019/01/19/090000/</link><pubDate>Sat, 19 Jan 2019 09:00:00 +0900</pubDate><guid>https://nagakagachi.github.io/entry/2019/01/19/090000/</guid><description>&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;周期的リムライトで遊んでみたり。グ&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%EC%A5%A4%A5%DE%A5%F3"&gt;レイマン&lt;/a&gt;さんみたいに凹凸が多いと水面の反射みたいになる。後半の球はリム計算用のベクトルを視線ではなくワールド空間ベクトル(この場合は+Z)にして周期的リムのパラメータを変えたところ。リムってなんだっけ…&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://twitter.com/hashtag/UE4?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#UE4&lt;/a&gt; &lt;a href="https://t.co/zGuOW6giG1"&gt;pic.twitter.com/zGuOW6giG1&lt;/a&gt;&lt;/p&gt;&amp;mdash; なが (@nagakagachi) &lt;a href="https://twitter.com/nagakagachi/status/1086286532242137093?ref_src=twsrc%5Etfw"&gt;2019年1月18日&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;p&gt;視線ベクトルと&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%D4%A5%AF%A5%BB%A5%EB"&gt;ピクセル&lt;/a&gt;法線の&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/%C6%E2%C0%D1"&gt;内積&lt;/a&gt;を利用して縁をエミッシブで光らせるリムライト的表現をすることがよくあると思います。今回はこのリムライト的表現で使われる値をそのまま使わずに周期関数へ入力してから使うことで、周波数を変えたり波にオフセットをかけたりできるヘンなリムライト？を作ってみます。&lt;/p&gt;&lt;p&gt;視線ベクトルvの逆向きベクトル-vと法線ベクトルnの&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/%C6%E2%C0%D1"&gt;内積&lt;/a&gt;は正面から縁に向かって1から0に変化します。&lt;br /&gt;&#10;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/529e5d85dfcee3d1c51c5080afab4d6fe039297c48e2c79185bd322abc528f9c.png" width="1023" height="526" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&#10;&lt;p&gt;&lt;span class="math-inline"&gt;\(1 - dot(\vec{-v},\vec{n})\)&lt;/span&gt;&lt;br /&gt;&#10;とすれば正面が0で縁が1になり、単純にこれをエミッシブに出力すれば縁が光ると思います。&lt;/p&gt;&lt;p&gt;これを周期関数である sin() に入力します。&lt;br /&gt;&#10;&lt;span class="math-inline"&gt;\(sin(1 - dot(\vec{-v},\vec{n}))\)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;このままだと -1 ~ +1 の値になるので、1を足して0.5を掛けることで 0 ~ 1 の値に変換します。&lt;br /&gt;&#10;&lt;span class="math-inline"&gt;\((sin(1 - dot(\vec{-v},\vec{n})) + 1)*0.5\)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;さらに周波数を変えるための変数 freq をsin() の中にかけ合わせます。&lt;br /&gt;&#10;&lt;span class="math-inline"&gt;\((sin( (1-dot(\vec{-v},\vec{n}) )*freq)+1)*0.5\)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;周期のオフセットのための変数 offset をsin() の中に足します。&lt;br /&gt;&#10;&lt;span class="math-inline"&gt;\((sin( (1-dot(\vec{-v},\vec{n}) )*freq+offset)+1)*0.5\)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;最後に0から1への変化の急峻さをコン&lt;a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%C8%A5%ED%A1%BC%A5%EB"&gt;トロール&lt;/a&gt;する変数 sharpness を使ってべき乗します。&lt;br /&gt;&#10;&lt;span class="math-inline"&gt;\((power(sin( (1-dot(\vec{-v},\vec{n}) )*freq+offset)+1)*0.5, sharpness)\)&lt;/span&gt;&lt;/p&gt;&#10;&lt;p&gt;この値を適当なカラーにかけてエミッシブ出力するなどすれば完成。&lt;/p&gt;&#10;&lt;p&gt;freqを大きくするとリムライトの波の数が増え、&lt;/p&gt;&#10;&lt;p&gt;offsetを増やすと波の位置が移動し、&lt;/p&gt;&#10;&lt;p&gt;sharpnessを大きくすると明るい部分が狭く（鋭く）なります。&lt;/p&gt;&#10;&lt;br /&gt;&#10;&lt;p&gt;プロジェクトはこちら&lt;br /&gt;&#10;(サンプルプロジェクトではsin()ではなく自前で周期関数モドキ作っていますがsin()などに置き換えても同じような挙動になるはずです)&lt;br /&gt;&#10;&lt;iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fdrive.google.com%2Fopen%3Fid%3D1JOK3EEDW2qqXo1PYR7uBqqa402GCGuxQ" title="PeriodicRimEmissiveMaterial.zip" 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://drive.google.com/open?id=1JOK3EEDW2qqXo1PYR7uBqqa402GCGuxQ"&gt;drive.google.com&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;</description></item><item><title>UE4 マテリアルブループリントでGPUバイトニックソート</title><link>https://nagakagachi.github.io/entry/2018/12/15/080000/</link><pubDate>Sat, 15 Dec 2018 08:00:00 +0900</pubDate><guid>https://nagakagachi.github.io/entry/2018/12/15/080000/</guid><description>&lt;p&gt;多分2018年最後の記事。（思ったほど効果がなかったので温めずに公開）&lt;/p&gt;&#10;&lt;p&gt;&lt;iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fnagakagachi%2Fue4%2Fblob%2Fmaster%2Fproject%2Fsample%2FMaterialBitonicSort.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/MaterialBitonicSort.zip"&gt;github.com&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;&lt;p&gt;&lt;iframe width="480" height="270" src="https://www.youtube.com/embed/C8mmNhjWrNw?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://youtu.be/C8mmNhjWrNw"&gt;youtu.be&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;&lt;br /&gt;&#10;&lt;p&gt;&lt;b&gt;&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/UE4"&gt;UE4&lt;/a&gt;のマテリアルBPでバイトニックソート&lt;/b&gt;を作ってみました。&lt;br /&gt;&#10;RG32fテクスチャを「R=キー, G=値」の配列に見立ててテクセルを並べ替えます。&lt;br /&gt;&#10;&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/GPU"&gt;GPU&lt;/a&gt;パーティクル等でテクスチャに格納した情報をソートする場合に、&lt;br /&gt;&#10;&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/GPU"&gt;GPU&lt;/a&gt;からCPUへデータをフィードバックしてCPUでソート、&lt;br /&gt;&#10;再び&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/GPU"&gt;GPU&lt;/a&gt;に戻すよりも全部&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/GPU"&gt;GPU&lt;/a&gt;でやったほうが速いだろうということで。&lt;/p&gt;&lt;p&gt;バイトニックソート自体はDirect Computeのサンプルなどがわかりやすいです。&lt;br /&gt;&#10;&lt;a href="https://msdn.microsoft.com/ja-jp/library/ee416561(v=vs.85).aspx"&gt;ComputeShaderSort11 &amp;#x30B5;&amp;#x30F3;&amp;#x30D7;&amp;#x30EB;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;今回のマテリアルBPを利用した方法はほぼ&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D4%A5%AF%A5%BB%A5%EB"&gt;ピクセル&lt;/a&gt;シェーダ実装なのでt-pot様も参考になると思います。&lt;br /&gt;&#10;&lt;a href="https://t-pot.com/program/90_BitonicSort/index.html"&gt;t-pot&amp;#x300E;Bitonic sort&amp;#x300F;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&#10;&lt;p&gt;バイトニックソートの大まかな流れは&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;ステップ1&#10;&lt;ul&gt;&#10;&lt;li&gt;サブステップ 2要素毎に1個隣と入れ替え&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;ステップ2&#10;&lt;ul&gt;&#10;&lt;li&gt;サブステップ 4要素毎に2個隣と入れ替え&lt;/li&gt;&#10;&lt;li&gt;サブステップ 2要素毎に1個隣と入れ替え&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;ステップ3&#10;&lt;ul&gt;&#10;&lt;li&gt;サブステップ 8要素毎に4個隣と入れ替え&lt;/li&gt;&#10;&lt;li&gt;サブステップ 4要素毎に2個隣と入れ替え&lt;/li&gt;&#10;&lt;li&gt;サブステップ 2要素毎に1個隣と入れ替え&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;ステップi&#10;&lt;ul&gt;&#10;&lt;li&gt;同様に最大要素の半分の要素毎のステップまで続ける&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&lt;p&gt;という感じです。要&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%C1%C7%BF%F4"&gt;素数&lt;/a&gt;が 2^n の場合は合計で n*(n+1)/2 のサブステップによってソートが完了します。&lt;br /&gt;&#10;65536=2^16 なら 136サブステップです。&lt;br /&gt;&#10;実際には昇順降順を入れ違いにするので詳細は先に挙げたページを参考にしてください。&lt;br /&gt;&#10;また、バイトニックソートの制限として要&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%C1%C7%BF%F4"&gt;素数&lt;/a&gt;が2のべき乗でないとダメなのでそのあたりはBPで調整してます。&lt;/p&gt;</description></item><item><title>UE4 内部構造が透けているように見える疑似透過シェーダ(CEDEC2018?)</title><link>https://nagakagachi.github.io/entry/2018/09/08/203717/</link><pubDate>Sat, 08 Sep 2018 20:37:17 +0900</pubDate><guid>https://nagakagachi.github.io/entry/2018/09/08/203717/</guid><description>&lt;p&gt;UE4.20.2&lt;/p&gt;&#10;&lt;p&gt;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/f8eedb14d990b17be3a2393435fda19ea0ea8bb5e94465427a27daf1d2f798f6.png" width="951" height="571" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;/p&gt;&#10;&lt;p&gt;CEDEC2018のモンスターハンター：ワールドのシェーダ関連講演で触れられていた「疑似透過シェーダ」が面白そうだったのでUE4マテリアルでやってみる.&lt;/p&gt;&#10;&lt;p&gt;MH:Wのストーリーラストのアイツのように内部が透けて見えるようなことをしたいというもの。&lt;/p&gt;&#10;&lt;p&gt;&lt;iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ftwitter.com%2Fnagakagachi%2Fstatus%2F1037723917933207552" title="X" 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;br /&gt;&#10;&lt;blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"&gt;&lt;p lang="ja" dir="ltr"&gt;&lt;a href="https://x.com/hashtag/UE4?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#UE4&lt;/a&gt; &lt;a href="https://x.com/hashtag/UE4Study?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#UE4Study&lt;/a&gt; 疑似透過シェーダで遊ぶ。後でブログ書いてサンプルプロジェクト貼る。BlenderとUE4を完全に理解してたらグレイマンの骨モデル作ってもっとそれっぽくできそうだけどﾑﾘ &lt;a href="https://t.co/ZfOc05uD2G"&gt;pic.twitter.com/ZfOc05uD2G&lt;/a&gt;&lt;/p&gt;&amp;mdash; なが (@nagakagachi) &lt;a href="https://x.com/nagakagachi/status/1038247245819260928?ref_src=twsrc%5Etfw"&gt;2018年9月8日&lt;/a&gt;&lt;/blockquote&gt; &lt;script async src="https://platform.x.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt; &lt;br /&gt;&#10;「普通の不透明な外側モデル」の内部に「疑似透過シェーダのモデル」を配置すると&lt;br /&gt;&#10;内部のモデルが透けて見えるようになる。&lt;/p&gt;&lt;br /&gt;&#10;&lt;p&gt;3行説明&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Translucentマテリアルで&lt;/li&gt;&#10;&lt;li&gt;深度テスト無効で&lt;/li&gt;&#10;&lt;li&gt;SceneDepthよりPixelDepthのほうが大きい場合だけその差に応じて色を決定&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;以上&lt;/p&gt;&#10;&lt;p&gt;CEDECの講演については以下の記事の下の方。&lt;br /&gt;&#10;&lt;iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.famitsu.com%2Fnews%2F201808%2F23162839.html" title="『モンスターハンター：ワールド』開発を支えた“アーティストが作ったシェーダー”とは？【CEDEC 2018】&#9; - ファミ通.com" 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://www.famitsu.com/news/201808/23162839.html"&gt;www.famitsu.com&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;&#10;&lt;p&gt;講演時は内部構造モデルをカメラの方に引き寄せて描画するという説明で、内部構造モデルが手前に飛び出しているような絵で説明されていた。&lt;/p&gt;&#10;&lt;p&gt;ただ本当に頂点操作で手前に飛び出させると色々問題がありそうなのであれはあくまでイメージで、きっと深度テストの工夫でやっていたと予想。&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;追記:実際に頂点操作でやっていたらしいので深度ではないらしい&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;p&gt;&lt;br /&gt;&#10;というわけで以下のように半分埋まった球を透けさせてみる。&lt;br /&gt;&#10;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/dc0b457f995da4ac2cc2bc641744f6ee9619673b3ce1d12f56dce2eb3d7e1ab1.png" width="859" height="566" 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;新規マテリアルを作成してメッシュにセットしておく. マテリアル名はとりあえず MAT_PseudoTranslucentTest で.&lt;/li&gt;&#10;&lt;li&gt;マテリアルの Blend Mode を Additive に変更. Opaqueだと後述する 深度テスト無効 が使えないので.&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/c243fc36cb236e7051b018c89cabc4aed01a6047beee50c80c143e25982836a1.png" width="317" height="341" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;li&gt;マテリアルの Disable Depth Test (深度テスト無効) をONにする.&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/810a23f228b795d18625463b04112ab2def3bdbc1df65788817c4bda6a8a6a15.png" width="317" height="429" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;li&gt;エミッシブに赤を入力する. 後のために乗算ノードを挟んでおく.&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/18dd05b3d447b6a23824cad55560f13df0ad6630c523f20ad6db7a59a8e0bfd2.png" width="597" height="512" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;li&gt;ここまででこうなる. 深度テスト無効で描いてるのだから当然.&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/f582cc17f742a43033986ad6b03a5601714121bad1d9a18c29a9fa048f51b5d9.png" width="951" height="566" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;li&gt;次は透過の表現のためにPixelDepthとSceneDepthの差を使ってグラデーションを計算する. PixelDepthとSceneDepthの出力はMax2048らしいので0~1の範囲にするために割っている. DepthRangeパラメータは深度差のグラデーション範囲を制御する(値は0.02). Sharpnessパラメータはグラデーションの鋭さを制御する(値は2).&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/67dc3fea909e5d3cd4714d77908881079c1b5b94c599312d5c36e9270745a96b.png" width="1024" height="317" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;li&gt;ここまでで以下のようにメッシュが埋まっている部分が表面に近いほど色が濃いグラデーションになる.&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/2a3ed3f8dd5a1a304fabff509e11900b1ea6cfe91ac8cd08a3678984d22c81e8.png" width="951" height="566" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;li&gt;PixelDepthのほうがSceneDepthのほうが手前の場合は表示しないように条件と乗算を追加.&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/bc3d37cdb47fba27f34c1399d573bf418d1be8ee92b8826c5c4d1d276a60d9bb.png" width="1024" height="403" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;li&gt;埋まってる部分だけが表示される.&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/707bf40683806a61aea873eaa76f518fab7da381978058d5056b9a20df8f4a1b.png" width="951" height="566" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;li&gt;わかりにくいので壁メッシュのマテリアルをスターターコンテンツの"M_Tech_Hex_Tile"に変えてみたところ.&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/50a2e36139559220f693971ac02179700225eecb6031c6b6ba7a95d3ceb7dc63.png" width="951" height="566" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/f8eedb14d990b17be3a2393435fda19ea0ea8bb5e94465427a27daf1d2f798f6.png" width="951" height="571" loading="lazy" title="" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;　わかりやすいように位置調整.&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;なんとなく表面からの距離によって透過度合いが変わって透けているように見えるかな？あくまで外側は普通のOpaqueマテリアルで、内部構造側のマテリアルが透けているように見せている。&lt;/p&gt;</description></item><item><title>UE4 動的にStaticMeshを生成する</title><link>https://nagakagachi.github.io/entry/2018/09/02/152927/</link><pubDate>Sun, 02 Sep 2018 15:29:27 +0900</pubDate><guid>https://nagakagachi.github.io/entry/2018/09/02/152927/</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;Add Static Mesh Component ( Static Mesh Component を追加 )&lt;br /&gt;&#10;でStaticMesh&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;をアクターに新規追加&lt;/p&gt;&lt;p&gt;必要なら AttachToComponent でルート&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;に紐づけ&lt;br /&gt;&#10;必要なら Set Collision Enable などで&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%EA%A5%B8%A5%E7%A5%F3"&gt;コリジョン&lt;/a&gt;無効化などを設定&lt;/p&gt;&lt;p&gt;Set Static Mesh&lt;br /&gt;&#10;によってスタティックメッシュアセットをStaticMesh&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;に設定&lt;/p&gt;&lt;p&gt;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/c8ae99346b4faa9fc02998646448a9795c7589d5f022bfeee2e9d51df35c9139.png" alt="f:id:nagakagachi:20180902151411p:plain" title="f:id:nagakagachi:20180902151411p:plain" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;球メッシュ&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;をもったアクターの周りにキューブスタティックメッシュを動的に生成してみた図&lt;br /&gt;&#10;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/424c2dd70ef240b987a40a43e786b0e0018d40252fb26cc04b6dfbcb1a4f7639.png" alt="f:id:nagakagachi:20180902152006p:plain" title="f:id:nagakagachi:20180902152006p:plain" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;/p&gt;&#10;&lt;p&gt;通常のStaticMeshだとDrawCallがバンバン増えるので、同一メッシュをたくさん出すなら&lt;/p&gt;&#10;&lt;p&gt;InstancedStaticMeshを使ってAddInstanceで配置したほうが良さそう&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;p&gt;&lt;a href="https://nagakagachi.hatenablog.com/entry/2018/09/02/152927"&gt;元のはてなブログ記事&lt;/a&gt;&lt;/p&gt;</description></item><item><title>UE4 エディタ操作をMaya風にする4.20.2</title><link>https://nagakagachi.github.io/entry/2018/09/02/124544/</link><pubDate>Sun, 02 Sep 2018 12:45:44 +0900</pubDate><guid>https://nagakagachi.github.io/entry/2018/09/02/124544/</guid><description>&lt;p&gt;&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/UE4"&gt;UE4&lt;/a&gt;の&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A1%BC"&gt;バー&lt;/a&gt;ジョンが変わるたびに微妙に設定する場所が変わっていく&lt;br /&gt;&#10;「エディタのMaya風操作設定」&lt;/p&gt;&lt;p&gt;&lt;a class="keyword" href="http://d.hatena.ne.jp/keyword/UE4"&gt;UE4&lt;/a&gt;.20.2 ではついに（もっと前から？）項目名から Maya という単語が&lt;br /&gt;&#10;消えてしまったのでメモしておく&lt;/p&gt;&#10;&lt;p&gt;エディタの環境設定&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&gt;レベルエディタ&lt;/li&gt;&#10;&lt;li&gt;&gt;ビューポート&lt;/li&gt;&#10;&lt;li&gt;&gt;Invert Middle Mouse Pan をON&lt;/li&gt;&#10;&lt;/ul&gt;&lt;p&gt;&lt;span itemscope itemtype="http://schema.org/Photograph"&gt;&lt;img src="images/74dae8ea2c3c5adf4d172015b863caab5292142076c8212bc9cb482f27b3c102.png" alt="f:id:nagakagachi:20180902124305p:plain" title="f:id:nagakagachi:20180902124305p:plain" class="hatena-fotolife" itemprop="image"&gt;&lt;/span&gt;&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;p&gt;&lt;a href="https://nagakagachi.hatenablog.com/entry/2018/09/02/124544"&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>