<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Chich Chichovsky</title>
    <description>The latest articles on DEV Community by Chich Chichovsky (@chich_chichovsky_689c67dd).</description>
    <link>https://dev.to/chich_chichovsky_689c67dd</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1898490%2F1575ab59-4552-4f75-b110-e6a771ebafa6.jpg</url>
      <title>DEV Community: Chich Chichovsky</title>
      <link>https://dev.to/chich_chichovsky_689c67dd</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/chich_chichovsky_689c67dd"/>
    <language>en</language>
    <item>
      <title>Custom material node in Unreal 5.6+</title>
      <dc:creator>Chich Chichovsky</dc:creator>
      <pubDate>Sat, 27 Jun 2026 12:38:43 +0000</pubDate>
      <link>https://dev.to/chich_chichovsky_689c67dd/custom-material-node-in-unreal-56-3l5b</link>
      <guid>https://dev.to/chich_chichovsky_689c67dd/custom-material-node-in-unreal-56-3l5b</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe331t8etqwyusacy8skz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe331t8etqwyusacy8skz.png" alt=" " width="467" height="226"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I was in the middle of creating a game and wanted to test some &lt;strong&gt;blurring post-processing&lt;/strong&gt; effects. To my surprise, I didn't find any production ready postprocessing implementations of post processing blur materials.&lt;/p&gt;

&lt;h1&gt;
  
  
  Choosing the right approach
&lt;/h1&gt;

&lt;p&gt;So, while trying to create an effect my requirements were:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwy2x2wjfhxdmlfqyfpo6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwy2x2wjfhxdmlfqyfpo6.png" alt=" " width="447" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fast iteration;&lt;/li&gt;
&lt;li&gt;Rapid prototyping.
&lt;code&gt;三三ᕕ( ᐛ )ᕗ 三三ᕕ( ᐛ )ᕗ 三三ᕕ( ᐛ )ᕗ&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This I could achieve by using &lt;strong&gt;Global Custom Shaders&lt;/strong&gt; or &lt;strong&gt;Post-process Material&lt;/strong&gt;. I chose the latter due to faster prototyping. Which was crucial for me. Also, it was suggested to me by _DeepSeek _and _Qwen _ LLMs which I'm using to simplify the development process.&lt;/p&gt;

&lt;h1&gt;
  
  
  Development
&lt;/h1&gt;

&lt;p&gt;I was really confused by the Unreal's Custom Shader node. The first iterations of the code that were suggested by Qwen were not working. The blur implementation was correct, but the integration in the engine was not right. So, after several hours of trying to make it work, I quickly understood that this is the task that requires for me to do the research by myself. &lt;code&gt;ᕙ(  •̀ ᗜ •́  )ᕗ&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I haven't dig too deep into the node still. But I got it to the extent where it covers my needs.&lt;/p&gt;

&lt;p&gt;So let's get to the grits of it!&lt;/p&gt;

&lt;p&gt;First I got this useful page &lt;br&gt;
&lt;a href="https://www.kodeco.com/57-unreal-engine-4-custom-shaders-tutorial" rel="noopener noreferrer"&gt;https://www.kodeco.com/57-unreal-engine-4-custom-shaders-tutorial&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Compiling the sample
&lt;/h2&gt;

&lt;p&gt;Here I found a real example that I can work upon.&lt;/p&gt;

&lt;p&gt;It did the Guassian blur too. I loaded the project and... The material didn't compile of course ¯\&lt;em&gt;(ツ)&lt;/em&gt;/¯. You can see the original code below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hlsl"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;int&lt;/span&gt; &lt;span class="n"&gt;SceneTextureId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;float2&lt;/span&gt; &lt;span class="n"&gt;TexelSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;View&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ViewSizeAndInvSize&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;zw&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;float2&lt;/span&gt; &lt;span class="n"&gt;UV&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GetDefaultSceneTextureUV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Parameters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SceneTextureId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;float3&lt;/span&gt; &lt;span class="n"&gt;PixelSum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;float3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;float&lt;/span&gt; &lt;span class="n"&gt;WeightSum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Radius&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;Radius&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;int&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Radius&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;Radius&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;float2&lt;/span&gt; &lt;span class="n"&gt;Offset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UV&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="kt"&gt;float2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;TexelSize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;float3&lt;/span&gt; &lt;span class="n"&gt;PixelColor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SceneTextureLookup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Offset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SceneTextureId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;float&lt;/span&gt; &lt;span class="n"&gt;Weight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Calculate1DGaussian&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;Radius&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;Calculate1DGaussian&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;Radius&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;PixelSum&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;PixelColor&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;Weight&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;WeightSum&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;Weight&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;PixelSum&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;WeightSum&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem was &lt;code&gt;SceneTextureLookup(Offset, SceneTextureId, 0)&lt;/code&gt; function call. The compiler outputted that it just couldn't find this function. In the error log there also were the link to the shader which was used while compiling the material. You can get this debug info if you turn on shader developer mode in engine settings.&lt;/p&gt;

&lt;p&gt;So I went to that generated shader file and inspected it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hlsl"&gt;&lt;code&gt;&lt;span class="c1"&gt;// line 3512 "/Engine/Generated/Material.ush"&lt;/span&gt;
&lt;span class="kt"&gt;float4&lt;/span&gt; &lt;span class="nf"&gt;SceneTextureLookup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FMaterialPixelParameters&lt;/span&gt; &lt;span class="n"&gt;Parameters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float2&lt;/span&gt; &lt;span class="n"&gt;UV&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;int&lt;/span&gt; &lt;span class="n"&gt;SceneTextureIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;bFiltered&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the number of parameters are different. The new function version had new &lt;strong&gt;FMaterialPixelParameters&lt;/strong&gt; argument. So I decided to dig a little bit further and found that the function was indeed changed and the current implementation&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hlsl"&gt;&lt;code&gt;&lt;span class="err"&gt;@@&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;Engine&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;Shaders&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;Private&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;MaterialTemplate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ush&lt;/span&gt; &lt;span class="mi"&gt;3408&lt;/span&gt;
&lt;span class="c1"&gt;// SceneTextureLookup function used by new translator.  Shading path agnostic, and handles conditional application of exposure scale, so generated code doesn't need to vary.&lt;/span&gt;
&lt;span class="kt"&gt;float4&lt;/span&gt; &lt;span class="nf"&gt;SceneTextureLookup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FMaterialPixelParameters&lt;/span&gt; &lt;span class="n"&gt;Parameters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float2&lt;/span&gt; &lt;span class="n"&gt;UV&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;int&lt;/span&gt; &lt;span class="n"&gt;SceneTextureIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;bFiltered&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So currently there is a new translator that uses new signature for the function. Good, one problem solved ദ്ദി（• ˕ •マ.ᐟ&lt;/p&gt;

&lt;h2&gt;
  
  
  Correct SceneTextureLookup usage
&lt;/h2&gt;

&lt;p&gt;The material did compile, but the material output was black. So there must be another problem (╥‸╥). And there was. The original material uses &lt;code&gt;SceneTexture&lt;/code&gt; with &lt;code&gt;World Normal&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffrces8vcnogslnhn0kms.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffrces8vcnogslnhn0kms.png" alt=" " width="800" height="646"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And after experimenting for a bit I got the solution. So the &lt;code&gt;World Normal&lt;/code&gt; parameter should be changed to &lt;code&gt;PostProcessInput0&lt;/code&gt;. The reason is.. I didn't dig that deep. But if you use &lt;code&gt;Normal&lt;/code&gt; for SceneTexture you can't use &lt;code&gt;SceneTextureLookup()&lt;/code&gt; function for querying only for &lt;code&gt;World Normal&lt;/code&gt; Texture. So After the change you can query for &lt;code&gt;PostProcessInput0&lt;/code&gt; Texture.&lt;/p&gt;

&lt;p&gt;Volia! ٩(^ᗜ^ )و ´-٩(^ᗜ^ )و ´-٩(^ᗜ^ )و ´- The blur works as intended&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fet5i4aw01yvjjssqzfxw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fet5i4aw01yvjjssqzfxw.png" alt=" " width="531" height="582"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A little afterword
&lt;/h2&gt;

&lt;p&gt;After that there some questions for me that I didn't dig deep enough to find answers, but have an intuational guess.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Does external shader have shader optimisations, like Global shaders, if used in Custom node? Probably not, because the the code is just copied to the generated material shader, so there is no optimisation. But I invite readers to research this deeper.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Also why I can lookup textures in custom node only that are inputs to that custon node? To me it seems like before you could lookup for any TextureId, but now, for optimization, only for specific, that were inputed.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Other useful links
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.epicgames.com/documentation/unreal-engine/post-process-material-user-scene-textures-in-unreal-engine" rel="noopener noreferrer"&gt;https://dev.epicgames.com/documentation/unreal-engine/post-process-material-user-scene-textures-in-unreal-engine&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>shaders</category>
    </item>
  </channel>
</rss>
