Render Targets¶
A render target is a writable GPU texture you can draw into from the engine and sample from any material. They are the universal mechanism behind mirrors, portals, minimaps, GPU painting, dynamic decals, baking procedural textures, multi-pass post-FX, and headless rendering.
Asset types¶
| Class | Dim | Common use |
|---|---|---|
UTextureRenderTarget2D |
2D | Mirrors, monitors, minimaps, paint surfaces |
UTextureRenderTargetCube |
Cubemap | Reflection probes, env captures |
UTextureRenderTarget2DArray |
2D array | Volumetric LUTs, shadow maps, multi-pass FX |
UTextureRenderTargetVolume |
3D | 3D LUTs, fluid sims, volumetric fog |
UCanvasRenderTarget2D |
2D | Canvas/HUD-drawn dynamic textures |
Create from the Content Browser: right-click → Materials & Textures → Render Target (or Render Target Cube / Array / Volume).
Property cheat-sheet¶
| Setting | What it controls |
|---|---|
| Size X / Y | Resolution. Keep powers of 2 for streaming. |
| Render Target Format | RTF_RGBA8 (default), RTF_RGBA16f (HDR), RTF_R8 (single channel), RTF_R32f (depth/data) |
| Clear Color | Color used when cleared each frame |
| Auto Generate Mips | Build mips after each render — needed for sampling with anisotropy |
| Address X / Y | Clamp / wrap |
| Mips In UI | Use mips when drawn in UMG |
| Force Linear Gamma | Disable sRGB encoding — required for normal/data textures |
Writers — how content gets into a render target¶
1. SceneCaptureComponent2D — camera capture¶
The bread and butter. Attach to any actor:
USceneCaptureComponent2D* Cap = CreateDefaultSubobject<USceneCaptureComponent2D>(TEXT("Capture"));
Cap->TextureTarget = RT;
Cap->CaptureSource = ESceneCaptureSource::SCS_FinalColorLDR;
Cap->bCaptureEveryFrame = true;
Cap->ShowOnlyActors.Add(SomeActor); // optional include list
Capture sources:
| Source | Output |
|---|---|
SCS_FinalColorLDR |
Tonemapped, post-processed |
SCS_FinalColorHDR |
Pre-tonemapping HDR |
SCS_SceneColorHDR |
Pre-bloom HDR |
SCS_SceneColorSceneDepth |
RGB color + A depth |
SCS_DeviceDepth |
Hardware depth (NDC) |
SCS_Normal |
World normal G-buffer |
SCS_BaseColor |
Base color G-buffer |
2. DrawMaterialToRenderTarget — GPU compute via materials¶
The material's emissive output is rasterized onto a full-screen quad into the RT. This is the path for:
- Procedural texture baking (noise, gradients, heightmaps)
- GPU paint (brush material with prev-pass sample)
- Ping-pong simulations (fluid, wave equation)
- Distance-field generation
- Multi-pass filters
To ping-pong, allocate two RTs and swap which one is the source vs destination each tick.
3. CanvasRenderTarget2D — HUD-style drawing¶
Subclass UCanvasRenderTarget2D, bind OnCanvasRenderTargetUpdate:
void UMyCanvasRT::ReceiveUpdate(UCanvas* Canvas, int32 W, int32 H)
{
Canvas->K2_DrawText(MyFont, TEXT("HUD"), FVector2D(10,10), FVector2D(1,1), FLinearColor::White);
Canvas->K2_DrawTexture(MyTex, FVector2D(0,0), FVector2D(W,H), FVector2D(0,0));
}
Call UpdateResource() to trigger redraw.
4. Slate / UMG widget into RT¶
Or use UWidgetRenderer::DrawWidget for one-off captures from C++.
Readers — using the RT¶
Any material with a Texture Sample referencing the RT:
In a MaterialInstanceDynamic:
UMaterialInstanceDynamic* MID = MeshComp->CreateAndSetMaterialInstanceDynamic(0);
MID->SetTextureParameterValue(TEXT("ScreenTexture"), RT);
Cookbook¶
Mirror¶
- Create
RT_Mirror_1024.uasset(RGBA8, 1024×1024) - On the mirror actor:
USceneCaptureComponent2Dat the mirror plane - Set Capture Source =
SCS_FinalColorLDR - Material:
Unlitwith aSceneTexturethat usesScreenPosition.xy / ScreenPosition.was UV — gives a screen-space lookup - Mirror the capture component's transform across the surface plane on Tick
Portal¶
Same as mirror except the capture sits at the destination portal facing the right way. Use SceneCapture2D's CustomNearClippingPlane to clip behind the portal surface.
Minimap¶
- Top-down
SceneCaptureComponent2Dabove the level CaptureSource = SCS_FinalColorLDR,ProjectionType = Orthographic- OrthoWidth = world units to cover
- Drop the RT into a UMG
Imagewidget on the HUD
GPU paint¶
Two RTs (A, B):
- Read brush position from CPU into a material parameter
DrawMaterialToRenderTarget(B, BrushMaterial)where BrushMaterial samplesAfor previous state and writes new state- Swap A↔B next tick
- Use the active RT as the paint texture on the world surface
Headless screenshot at arbitrary resolution¶
import unreal
rt = unreal.SystemLibrary.create_render_target_2d(8192, 8192)
unreal.SystemLibrary.draw_material_to_render_target(world, rt, screenshot_material)
unreal.RenderingLibrary.export_render_target(world, rt, "C:/out", "shot.png")
Performance¶
| Lever | Effect |
|---|---|
| Format | RGBA8 < RGBA16f < RGBA32f in bandwidth |
| Auto Generate Mips | Adds a downsample pass each frame — turn off if not sampling with mip bias |
| Capture Every Frame | Off for static views (mirrors only when moving) |
| Hidden show flags | Disable Bloom/AA on SceneCapture if you don't need them |
| bAlwaysPersistRenderingState | Stops the renderer from rebuilding state every tick |
A 1080p RGBA16f RT captured every frame at the same cost as the main scene — that's effectively a second renderer pass. Use SceneCapture's ShowOnlyActors / HiddenActors lists to render only what you need.
Gotchas¶
- Auto-exposure runs independently in each SceneCapture — you may need to override exposure to match the main camera.
- Volumetric fog is disabled by default in captures; enable via Post Process settings on the capture.
- Lumen reflections in captures cost extra; turn off
Show Flag → Lumenif unnecessary. - Render target memory is GPU memory — at 4K RGBA16f that's 64MB per RT.
- Editor preview of an RT can lock the asset and prevent the renderer from writing — close the asset window during play.
Related¶
- SceneCaptureComponent details
- Post Process Materials — same RT writing/reading patterns inside the post-process pipeline
- Pixel Streaming — feeds RTs into WebRTC for browser delivery
- Composure — composite many RT layers together