<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>unreal on Transdimensional Phoenix</title><link>https://blog.opengbh.net/tags/unreal/</link><description>Recent content in unreal on Transdimensional Phoenix</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Thu, 29 Jun 2023 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.opengbh.net/tags/unreal/index.xml" rel="self" type="application/rss+xml"/><item><title>Reading a cubemap pixel by direction in Unreal Engine 5</title><link>https://blog.opengbh.net/posts/0010-reading-cubemap-by-direction/</link><pubDate>Thu, 29 Jun 2023 00:00:00 +0000</pubDate><guid>https://blog.opengbh.net/posts/0010-reading-cubemap-by-direction/</guid><description>In order to implement an early version of pre-rendered 2D skybox I needed to compare the skyboxes with sun enabled and disabled in order to obtain the required tinting of the sun for 2D skybox (so the sun doesn&amp;rsquo;t render on top of it, shining right through dense clouds).
This system is no longer used, now a texture mask is used instead to remove stars, sun and moon and other background objects from being rendered where the clouds are.</description><content>&lt;p>In order to implement an early version of &lt;a href="https://blog.opengbh.net/posts/0003-pre-rendered-2d-skybox/">pre-rendered 2D skybox&lt;/a> I needed to compare the skyboxes with sun enabled and disabled in order to obtain the required tinting of the sun for 2D skybox (so the sun doesn&amp;rsquo;t render on top of it, shining right through dense clouds).&lt;/p>
&lt;p>This system is no longer used, now a texture mask is used instead to remove stars, sun and moon and other background objects from being rendered where the clouds are.&lt;/p>
&lt;p>Here is the function for sampling the cube map:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>FLinearColor USynesthesiaBlueprintFunctions&lt;span style="color:#f92672">::&lt;/span>SampleTextureCubeByDirection(UTextureRenderTargetCube&lt;span style="color:#f92672">*&lt;/span> RenderTarget, &lt;span style="color:#66d9ef">const&lt;/span> FVector&lt;span style="color:#f92672">&amp;amp;&lt;/span> Direction)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>RenderTarget) &lt;span style="color:#66d9ef">return&lt;/span> FLinearColor&lt;span style="color:#f92672">::&lt;/span>Black;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Get the correct resource
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> FTextureRenderTargetResource&lt;span style="color:#f92672">*&lt;/span> RenderTargetResource &lt;span style="color:#f92672">=&lt;/span> RenderTarget&lt;span style="color:#f92672">-&amp;gt;&lt;/span>GameThread_GetRenderTargetResource();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>RenderTargetResource) &lt;span style="color:#66d9ef">return&lt;/span> FLinearColor&lt;span style="color:#f92672">::&lt;/span>Black;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> FTextureRenderTargetCubeResource&lt;span style="color:#f92672">*&lt;/span> CubeResource &lt;span style="color:#f92672">=&lt;/span> RenderTargetResource&lt;span style="color:#f92672">-&amp;gt;&lt;/span>GetTextureRenderTargetCubeResource();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>CubeResource) &lt;span style="color:#66d9ef">return&lt;/span> FLinearColor&lt;span style="color:#f92672">::&lt;/span>Black;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Normalize the direction vector
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> FVector NormalizedDirection &lt;span style="color:#f92672">=&lt;/span> Direction.GetSafeNormal();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Get the correct cube face for the normalized direction
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> ECubeFace CubeFace &lt;span style="color:#f92672">=&lt;/span> ECubeFace&lt;span style="color:#f92672">::&lt;/span>CubeFace_NegX;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">double&lt;/span> MaxAbsValue &lt;span style="color:#f92672">=&lt;/span> FMath&lt;span style="color:#f92672">::&lt;/span>Max3(FMath&lt;span style="color:#f92672">::&lt;/span>Abs(NormalizedDirection.X), FMath&lt;span style="color:#f92672">::&lt;/span>Abs(NormalizedDirection.Y), FMath&lt;span style="color:#f92672">::&lt;/span>Abs(NormalizedDirection.Z));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> (FMath&lt;span style="color:#f92672">::&lt;/span>Abs(NormalizedDirection.X) &lt;span style="color:#f92672">==&lt;/span> MaxAbsValue) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> CubeFace &lt;span style="color:#f92672">=&lt;/span> NormalizedDirection.X &lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> &lt;span style="color:#f92672">?&lt;/span> ECubeFace&lt;span style="color:#f92672">::&lt;/span>CubeFace_PosX : ECubeFace&lt;span style="color:#f92672">::&lt;/span>CubeFace_NegX;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#a6e22e">if&lt;/span> (FMath&lt;span style="color:#f92672">::&lt;/span>Abs(NormalizedDirection.Y) &lt;span style="color:#f92672">==&lt;/span> MaxAbsValue) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> CubeFace &lt;span style="color:#f92672">=&lt;/span> NormalizedDirection.Y &lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> &lt;span style="color:#f92672">?&lt;/span> ECubeFace&lt;span style="color:#f92672">::&lt;/span>CubeFace_PosY : ECubeFace&lt;span style="color:#f92672">::&lt;/span>CubeFace_NegY;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#a6e22e">if&lt;/span> (FMath&lt;span style="color:#f92672">::&lt;/span>Abs(NormalizedDirection.Z) &lt;span style="color:#f92672">==&lt;/span> MaxAbsValue) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> CubeFace &lt;span style="color:#f92672">=&lt;/span> NormalizedDirection.Z &lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> &lt;span style="color:#f92672">?&lt;/span> ECubeFace&lt;span style="color:#f92672">::&lt;/span>CubeFace_PosZ : ECubeFace&lt;span style="color:#f92672">::&lt;/span>CubeFace_NegZ;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Calculate coordinates of the point on the selected cube maps cube face
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">float&lt;/span> CubeFaceU &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0.0f&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">float&lt;/span> CubeFaceV &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0.0f&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> FVector FaceDirection &lt;span style="color:#f92672">=&lt;/span> NormalizedDirection.GetAbs();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> (CubeFace &lt;span style="color:#f92672">==&lt;/span> ECubeFace&lt;span style="color:#f92672">::&lt;/span>CubeFace_PosX) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> CubeFaceU &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">-&lt;/span>NormalizedDirection.Z &lt;span style="color:#f92672">/&lt;/span> FaceDirection.X;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> CubeFaceV &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">-&lt;/span>NormalizedDirection.Y &lt;span style="color:#f92672">/&lt;/span> FaceDirection.X;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#a6e22e">if&lt;/span> (CubeFace &lt;span style="color:#f92672">==&lt;/span> ECubeFace&lt;span style="color:#f92672">::&lt;/span>CubeFace_NegX) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> CubeFaceU &lt;span style="color:#f92672">=&lt;/span> NormalizedDirection.Z &lt;span style="color:#f92672">/&lt;/span> FaceDirection.X;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> CubeFaceV &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">-&lt;/span>NormalizedDirection.Y &lt;span style="color:#f92672">/&lt;/span> FaceDirection.X;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#a6e22e">if&lt;/span> (CubeFace &lt;span style="color:#f92672">==&lt;/span> ECubeFace&lt;span style="color:#f92672">::&lt;/span>CubeFace_PosY) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> CubeFaceU &lt;span style="color:#f92672">=&lt;/span> NormalizedDirection.X &lt;span style="color:#f92672">/&lt;/span> FaceDirection.Y;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> CubeFaceV &lt;span style="color:#f92672">=&lt;/span> NormalizedDirection.Z &lt;span style="color:#f92672">/&lt;/span> FaceDirection.Y;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#a6e22e">if&lt;/span> (CubeFace &lt;span style="color:#f92672">==&lt;/span> ECubeFace&lt;span style="color:#f92672">::&lt;/span>CubeFace_NegY) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> CubeFaceU &lt;span style="color:#f92672">=&lt;/span> NormalizedDirection.X &lt;span style="color:#f92672">/&lt;/span> FaceDirection.Y;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> CubeFaceV &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">-&lt;/span>NormalizedDirection.Z &lt;span style="color:#f92672">/&lt;/span> FaceDirection.Y;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#a6e22e">if&lt;/span> (CubeFace &lt;span style="color:#f92672">==&lt;/span> ECubeFace&lt;span style="color:#f92672">::&lt;/span>CubeFace_PosZ) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> CubeFaceU &lt;span style="color:#f92672">=&lt;/span> NormalizedDirection.X &lt;span style="color:#f92672">/&lt;/span> FaceDirection.Z;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> CubeFaceV &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">-&lt;/span>NormalizedDirection.Y &lt;span style="color:#f92672">/&lt;/span> FaceDirection.Z;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#a6e22e">if&lt;/span> (CubeFace &lt;span style="color:#f92672">==&lt;/span> ECubeFace&lt;span style="color:#f92672">::&lt;/span>CubeFace_NegZ) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> CubeFaceU &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">-&lt;/span>NormalizedDirection.X &lt;span style="color:#f92672">/&lt;/span> FaceDirection.Z;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> CubeFaceV &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">-&lt;/span>NormalizedDirection.Y &lt;span style="color:#f92672">/&lt;/span> FaceDirection.Z;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Read correct pixel from the resource
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> TArray&lt;span style="color:#f92672">&amp;lt;&lt;/span>FFloat16Color&lt;span style="color:#f92672">&amp;gt;&lt;/span> ImageData;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>CubeResource&lt;span style="color:#f92672">-&amp;gt;&lt;/span>ReadPixels(ImageData, FReadSurfaceDataFlags(ERangeCompressionMode&lt;span style="color:#f92672">::&lt;/span>RCM_UNorm, CubeFace))) &lt;span style="color:#66d9ef">return&lt;/span> FLinearColor&lt;span style="color:#f92672">::&lt;/span>Black;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Calculate pixel coordinates of the point on selected cubemap face
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> int32 SizeX &lt;span style="color:#f92672">=&lt;/span> CubeResource&lt;span style="color:#f92672">-&amp;gt;&lt;/span>GetSizeX();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> int32 SizeY &lt;span style="color:#f92672">=&lt;/span> CubeResource&lt;span style="color:#f92672">-&amp;gt;&lt;/span>GetSizeY();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> int32 U &lt;span style="color:#f92672">=&lt;/span> FMath&lt;span style="color:#f92672">::&lt;/span>RoundToInt((CubeFaceU &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">1.0f&lt;/span>) &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#ae81ff">0.5f&lt;/span> &lt;span style="color:#f92672">*&lt;/span> (SizeX &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> int32 V &lt;span style="color:#f92672">=&lt;/span> FMath&lt;span style="color:#f92672">::&lt;/span>RoundToInt((CubeFaceV &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">1.0f&lt;/span>) &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#ae81ff">0.5f&lt;/span> &lt;span style="color:#f92672">*&lt;/span> (SizeY &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> int32 Offset &lt;span style="color:#f92672">=&lt;/span> V &lt;span style="color:#f92672">*&lt;/span> SizeX &lt;span style="color:#f92672">+&lt;/span> U;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Sample the cubemap data
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> (ImageData.IsValidIndex(Offset)) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> ImageData[Offset].GetFloats();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> FLinearColor&lt;span style="color:#f92672">::&lt;/span>Black;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>And here is the function for saving a cube map to disk, just in case it might be useful in a similar context:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>UTextureCube&lt;span style="color:#f92672">*&lt;/span> USynesthesiaBlueprintFunctions&lt;span style="color:#f92672">::&lt;/span>RenderTargetCreateStaticTextureCubeEditorOnly(UTextureRenderTargetCube&lt;span style="color:#f92672">*&lt;/span> RenderTarget, FString InName, TextureCompressionSettings CompressionSettings, TextureMipGenSettings MipSettings)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#if WITH_EDITOR
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">// Save the render target image as an asset
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>RenderTarget) { &lt;span style="color:#75715e">// Invalid RT
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> FMessageLog(&lt;span style="color:#e6db74">&amp;#34;Blueprint&amp;#34;&lt;/span>).Warning(LOCTEXT(&lt;span style="color:#e6db74">&amp;#34;RenderTargetCreateStaticTextureCube_InvalidRenderTarget&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;RenderTargetCreateStaticTextureCubeEditorOnly: RenderTarget must be non-null.&amp;#34;&lt;/span>));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">nullptr&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#a6e22e">if&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>RenderTarget&lt;span style="color:#f92672">-&amp;gt;&lt;/span>GetResource()) { &lt;span style="color:#75715e">// Invalid RT resource
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> FMessageLog(&lt;span style="color:#e6db74">&amp;#34;Blueprint&amp;#34;&lt;/span>).Warning(LOCTEXT(&lt;span style="color:#e6db74">&amp;#34;RenderTargetCreateStaticTextureCube_ReleasedRenderTarget&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;RenderTargetCreateStaticTextureCubeEditorOnly: RenderTarget has been released.&amp;#34;&lt;/span>));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">nullptr&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> { &lt;span style="color:#75715e">// Valid inputs, generate static texture
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> FString Name;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> FString PackageName;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> IAssetTools&lt;span style="color:#f92672">&amp;amp;&lt;/span> AssetTools &lt;span style="color:#f92672">=&lt;/span> FModuleManager&lt;span style="color:#f92672">::&lt;/span>Get().LoadModuleChecked&lt;span style="color:#f92672">&amp;lt;&lt;/span>FAssetToolsModule&lt;span style="color:#f92672">&amp;gt;&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;AssetTools&amp;#34;&lt;/span>).Get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Use asset name only if directories are specified, otherwise full path
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>InName.Contains(TEXT(&lt;span style="color:#e6db74">&amp;#34;/&amp;#34;&lt;/span>))) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> FString AssetName &lt;span style="color:#f92672">=&lt;/span> RenderTarget&lt;span style="color:#f92672">-&amp;gt;&lt;/span>GetOutermost()&lt;span style="color:#f92672">-&amp;gt;&lt;/span>GetName();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> FString SanitizedBasePackageName &lt;span style="color:#f92672">=&lt;/span> UPackageTools&lt;span style="color:#f92672">::&lt;/span>SanitizePackageName(AssetName);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> FString PackagePath &lt;span style="color:#f92672">=&lt;/span> FPackageName&lt;span style="color:#f92672">::&lt;/span>GetLongPackagePath(SanitizedBasePackageName) &lt;span style="color:#f92672">+&lt;/span> TEXT(&lt;span style="color:#e6db74">&amp;#34;/&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">//AssetTools.CreateUniqueAssetName(PackagePath, InName, PackageName, Name);
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> PackageName &lt;span style="color:#f92672">=&lt;/span> PackagePath &lt;span style="color:#f92672">+&lt;/span> InName;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> InName.RemoveFromStart(TEXT(&lt;span style="color:#e6db74">&amp;#34;/&amp;#34;&lt;/span>));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> InName.RemoveFromStart(TEXT(&lt;span style="color:#e6db74">&amp;#34;Content/&amp;#34;&lt;/span>));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> InName.StartsWith(TEXT(&lt;span style="color:#e6db74">&amp;#34;Game/&amp;#34;&lt;/span>)) &lt;span style="color:#f92672">==&lt;/span> true &lt;span style="color:#f92672">?&lt;/span> InName.InsertAt(&lt;span style="color:#ae81ff">0&lt;/span>, TEXT(&lt;span style="color:#e6db74">&amp;#34;/&amp;#34;&lt;/span>)) &lt;span style="color:#f92672">:&lt;/span> InName.InsertAt(&lt;span style="color:#ae81ff">0&lt;/span>, TEXT(&lt;span style="color:#e6db74">&amp;#34;/Game/&amp;#34;&lt;/span>));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">//AssetTools.CreateUniqueAssetName(InName, TEXT(&amp;#34;&amp;#34;), PackageName, Name);
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> PackageName &lt;span style="color:#f92672">=&lt;/span> InName;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> int32 LastSlashIndex &lt;span style="color:#f92672">=&lt;/span> InName.Find(TEXT(&lt;span style="color:#e6db74">&amp;#34;/&amp;#34;&lt;/span>), ESearchCase&lt;span style="color:#f92672">::&lt;/span>CaseSensitive, ESearchDir&lt;span style="color:#f92672">::&lt;/span>FromEnd);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> (LastSlashIndex &lt;span style="color:#f92672">!=&lt;/span> INDEX_NONE &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> LastSlashIndex &lt;span style="color:#f92672">&amp;lt;&lt;/span> InName.Len() &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Name &lt;span style="color:#f92672">=&lt;/span> InName.RightChop(LastSlashIndex &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Name &lt;span style="color:#f92672">=&lt;/span> InName;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Create the package
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> UPackage&lt;span style="color:#f92672">*&lt;/span> Package &lt;span style="color:#f92672">=&lt;/span> CreatePackage(&lt;span style="color:#f92672">*&lt;/span>PackageName);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>Package) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> UE_LOG(LogSynth, Error, TEXT(&lt;span style="color:#e6db74">&amp;#34;Failed to create package %s&amp;#34;&lt;/span>), &lt;span style="color:#f92672">*&lt;/span>PackageName);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">nullptr&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Package&lt;span style="color:#f92672">-&amp;gt;&lt;/span>FullyLoad();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Create or overwrite the texture
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> UTextureCube&lt;span style="color:#f92672">*&lt;/span> NewTexture &lt;span style="color:#f92672">=&lt;/span> Cast&lt;span style="color:#f92672">&amp;lt;&lt;/span>UTextureCube&lt;span style="color:#f92672">&amp;gt;&lt;/span>(RenderTarget&lt;span style="color:#f92672">-&amp;gt;&lt;/span>ConstructTextureCube(Package, Name, RenderTarget&lt;span style="color:#f92672">-&amp;gt;&lt;/span>GetMaskedFlags() &lt;span style="color:#f92672">|&lt;/span> RF_Public &lt;span style="color:#f92672">|&lt;/span> RF_Standalone));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// If the texture is valid, set its parameters and return it
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> (NewTexture &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nullptr&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Package needs saving
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">//NewTexture-&amp;gt;MarkPackageDirty();
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> Package&lt;span style="color:#f92672">-&amp;gt;&lt;/span>SetDirtyFlag(true);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Package&lt;span style="color:#f92672">-&amp;gt;&lt;/span>PackageMarkedDirtyEvent.Broadcast(Package, true);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Notify the asset registry
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> FAssetRegistryModule&lt;span style="color:#f92672">::&lt;/span>AssetCreated(NewTexture);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Update Compression and Mip settings
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> NewTexture&lt;span style="color:#f92672">-&amp;gt;&lt;/span>CompressionSettings &lt;span style="color:#f92672">=&lt;/span> CompressionSettings;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> NewTexture&lt;span style="color:#f92672">-&amp;gt;&lt;/span>MipGenSettings &lt;span style="color:#f92672">=&lt;/span> MipSettings;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> NewTexture&lt;span style="color:#f92672">-&amp;gt;&lt;/span>PostEditChange();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> NewTexture;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> FMessageLog(&lt;span style="color:#e6db74">&amp;#34;Blueprint&amp;#34;&lt;/span>).Warning(LOCTEXT(&lt;span style="color:#e6db74">&amp;#34;RenderTargetCreateStaticTextureCube_FailedToCreateTexture&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;RenderTargetCreateStaticTextureCubeEditorOnly: Failed to create a new texture.&amp;#34;&lt;/span>));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#else
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> FMessageLog(&lt;span style="color:#e6db74">&amp;#34;Blueprint&amp;#34;&lt;/span>).Error(LOCTEXT(&lt;span style="color:#e6db74">&amp;#34;RenderTargetCreateStaticTextureCube_RuntimeFailedToCreateTexture&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;RenderTargetCreateStaticTextureCubeEditorOnly: Can&amp;#39;t create TextureCube at run time. &amp;#34;&lt;/span>));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">nullptr&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></content></item></channel></rss>