Drawing Alpha channel to a TextureRenderTarget2D?

I’m currently working on a system which uses the Canvas system to draw other assets (such as text, textures, etc) onto a TextureRenderTarget2D.

These elements are then overlayed on top of another texture in a material according to the rendered texture’s alpha channel.

However, Canvas’ handling of alpha channels appears to be pretty much completely random.

I was able to get basic stuff running by setting the ClearColor of the TextureRenderTarget2D to be completely translucent, which gives me a translucent base to start drawing to.

When I draw text to the canvas via an FCanvasTextItem, by default, the text is drawn to the color channels of the TextureRenderTarget2D, but it leaves the Alpha unchanged from the base transparency despite the color of the CanvasTextItem set to be opaque. However, I was able to get this to draw to the alpha properly by setting the CanvasTextItem’s BlendMode to ESimpleElementBlendMode::SE_BLEND_Opaque. However, this has the side effect of doing weird things to the color channels: the text’s color is drawn to the texture as just a rectangular blob, though only the letters are visible since only the actual font is drawn to the alpha channel. So that’s okay, I guess.

But when it comes to drawing other CanvasItems to the Canvas (specifically, FCanvasBoxItems and FCanvasLineItems) nothing I do seems to make the items draw to the TextureRenderTarget2D’s alpha channel. The color of the items are completely opaque, and I’ve tried going through every single option for ESimpleElementBlendMode with no effect.

I know the drawing is otherwise working, since I can see the boxes and lines in the color channels of the texture. But without them setting the alpha, they’re invisible.

There’s a bit of suspicious code in the line drawing function:
// Ensure the line isn’t masked out. Some legacy code relies on Color.A being ignored.
FLinearColor OpaqueColor(Color);
OpaqueColor.A = 1;

But given that it’s setting the alpha to entirely opaque, I don’t see why this would cause problems, but may indicate some weirdness around the handling of transparency elsewhere. Does anyone know what the deal is with CanvasItems and transparency? Is there a correct way of doing this?

1 Like

Darn it. Thanks for the reply and glad to hear you solved your problem.

I’m having very similar problems. I’m trying to use an additive blend material to write to a render target using a canvas but nothing I do will allow me to write to the alpha channel in the material.

Did you manage to resolve the issue in any way?

Not really. I ended up bailing on slate and moving to UMG. UMG’s FWidgetRenderer renders to the alpha channel correctly, but you need a full widget instead of just slate elements.

I had a similar problem. I Used SE_BLEND_AlphaBlend from the DrawTile implentation in Canvas.cpp.
I copied the implementation and used it in my code with a few minor adjustment. Works like a charm. My overlapped
textures on rendertarget are properly blended, and the result with the background is correct as well. No weird stuff as i was getting before. Like where the two textures were overlapping and supposed to be blending, there was just a block of transparency with the background shining through.

I have to opposite problem.

FCanvasTileItem works.
FCanvasTextItem does not work.

if I set FCanvasTextItem blend mode to opaque it crashes in:

if (GetFontCacheType() == EFontCacheType::Runtime)
	{
		// The runtime font cache uses an alpha-only texture, so we have to force this blend mode so we use the correct shader
		check(BlendModeToUse == SE_BLEND_Translucent || BlendModeToUse == SE_BLEND_TranslucentAlphaOnly || BlendModeToUse == SE_BLEND_TranslucentAlphaOnlyWriteAlpha);
		BlendModeToUse = SE_BLEND_TranslucentAlphaOnly;
	}

edit: Using a offline font with SE_BLEND_Masked works!