[Question/Request] Render textures to textures

Hi,

Sorry for the frequent questions/requests. You guys are awesome reading and replying to them !

I was wondering if its possible to render textures to textures. For example. I want to render an alpha stamp to a texture at a particular UV location (scale and translate the input texture map to generate a stamp on the new texture map which would be persistent, i.e., when I do the next stamp the previous stamp should still be there even when I remove the logic causing the stamp) and I would do it a few times during the game. Hence the texture would ‘evolve’ during the game. This texture can be used as mask for, let’s say, landscape texture. Is it possible to setup Render Target texture to do that without having to set up an actual scene rendering, i.e., just render textures directly to textures ?

Many thanks !
Cheers,
Shailen

You can render to anything you want to a texture with the canvas and its provided drawing functions (you must do this in code, not blueprint). I don’t have any sample code to hand, but if noone jumps in before tomorrow I’ll have a quick look. It should be quite easy to set up if you can handle c++.

In short, you’ll need to create a new render texture object, and you should be able to draw directly to it using that render texture object’s interface.

Ah I see, I was trying to find stuff in blueprints regarding it. I will try my hands with C++. Although I wouldn’t mind if someone already has a sample code for it :slight_smile:

Ok, without any reference code I think it might take me forever to figure out. I would really appreciate some code. In the meanwhile I will still try to fiddle with it. Many thanks !

This should help get you started:

// Create a Render Texture and initialise it.
RenderTexture = CastChecked(StaticConstructObject(UTextureRenderTarget2D::StaticClass()));
RenderTexture->ClearColor = FLinearColor::Black;
RenderTexture->InitAutoFormat(RenderTargetRes, RenderTargetRes);
RenderTexture->UpdateResourceImmediate();

// Create a Canvas and assign the render texture resource to it
FTextureRenderTarget2DResource* TextureResource = (FTextureRenderTarget2DResource*)RenderTexture->Resource;
Canvas = new FCanvas(TextureResource, NULL, 0, 0, 0);
Canvas->Clear(FLinearColor::Black);

//Your drawing code goes here
Canvas->DrawWhatever(StuffIWant);

//Assign render texture to material
MyMaterial->SetTextureParameterValue(TEXT("Target"), RenderTexture);

Notably this is just sample code to create the render texture, create a canvas to draw to that texture with and assigning the render texture resource - this part you only need to do once.

You can draw to this canvas when you need to update your texture as you need to, and I don’t believe you need to reassign the texture parameter afterwards, that should only need to be set once.

In UE3, Canvas was a bit finicky about when you were allowed to draw to it - you’ll probably want to do it before the scene renders or you may potentially not see it update. You may also need to call something like Canvas->Flush() to get it to update after each time you finish drawing stuff to it.

Many thanks ! This is awesome and should get me started. I will try it out.

This worked for me initially but with 4.5 Flush has gone and I can’t see how to get the RenderTarget updated.

There are now two versions of flush, one from the gamethread and one for the renderthread.

Replacing the previous Flush with Flush_GameThread(true or false) the function can be stepped over (in my case called from MyGameMode::Tick) but I then get a fatal assert from the renderthread. Really got to get symbols working on my computer but the callstack looks like this:

KernelBase.dll!000007fefd273ca2() Unknown
UE4Editor-Core.dll!000007fee6c4cd68() Unknown
UE4Editor-Core.dll!000007fee6c1e844() Unknown
UE4Editor-Engine.dll!000007fee468cb4a() Unknown
UE4Editor-Engine.dll!000007fee449ae4a() Unknown
UE4Editor-Engine.dll!000007fee447a66f() Unknown
UE4Editor-Engine.dll!000007fee50f282b() Unknown
UE4Editor-Engine.dll!000007fee50fdd62() Unknown
UE4Editor-Core.dll!000007fee6b56504() Unknown
UE4Editor-Core.dll!000007fee6b5668d() Unknown
UE4Editor-RenderCore.dll!000007feef4efc33() Unknown
UE4Editor-RenderCore.dll!000007feef4f00bb() Unknown
UE4Editor-Core.dll!000007fee6da6316() Unknown
UE4Editor-Core.dll!000007fee6d9ad2e() Unknown
[External Code]

And the assertion:
The thread 0x1190 has exited with code 0 (0x0).
The thread 0x2af8 has exited with code 0 (0x0).
Assertion failed: IsInGameThread() [File:D:\BuildFarm\buildmachine_++depot+UE4-Releases+4.5\Engine\Source\Runtime\Engine\Private\GlobalShader.cpp] [Line: 341]

Without the flush nothing is rendered to the texture.

Ideas?

Looked at engine source and saw it was trying to build shaders for a new platform, on the renderthread and that was triggering the assertion (wanted to do this on the gamethread).

My solution was to link RHI and use it to get the current feature level.

FCanvas((FTextureRenderTarget2DResource*)RenderTexture->Resource, NULL, 0.0f, 0.0f, 0.0f, GetMaxRHIFeatureLevel())

To get this to link you may have to add RHI to your build dependencies - see myProject.Build.sc, extend PublicDependencyModuleNames

Would be super awesome nice if this was represented in the FCanvas constructor documentation as being a newbie this cost me some hours! :slight_smile:

Hi,

This is an archived post from our beta for UE4 that is no longer being tracked. There is or may be outdated information provided here. I’m closing this thread.

Thank you!

Tim