So around 4.5 Epic changed something behind the scenes, breaking some code I was using for a couple projects. They used render targets with a canvas to draw onto a texture, a handy trick for masking between shaders. I grumped and groused over this, asked help from a few friends as well as the IRC, and nobody could work out how to use this functionality now. I put off asking here because :mad: but I’ve got the itch to revive these projects that got killed.
I figure to start with, I’d post some code showing two methods I worked out to accomplish this. The first uses the CanvasRenderTarget2D class, which as far as I worked out had a limitation. The code cleared the texture every frame, making persistent drawing onto the texture impossible.
The finished product (minus shaders) can be seen here:
The code just draws a given texture centered on the given coordinates, and expands it over time. It worked great for this water rings effect.
The second method I worked out preserves the texture, allowing you to draw over what was already written onto the texture. It doesn’t use CanvasRenderTarget2D, instead setting up the texture resource and Canvas at runtime. This was a bear to get together, as C++ and I have a mutual hatred. But I got it working from poring over half-baked examples on the Answerhub.
The finished product (Again just showing the raw texture) is here:
I used this effect for masking between dirty/fresh ice in a Zamboni game I’ve been tinkering with for ages, but when I went to mess about with another project using this system I was a bit suprised to find it crashed the engine.
The second method crashes with the following error:
Fatal error: [File:D:\BuildFarm\buildmachine_++depot+UE4-Releases+4.5\Engine\Source\Runtime\RenderCore\Private\RenderingThread.cpp] [Line: 641]
Rendering thread exception:
Assertion failed: IsInGameThread() [File:D:\BuildFarm\buildmachine_++depot+UE4-Releases+4.5\Engine\Source\Runtime\Engine\Private\GlobalShader.cpp] [Line: 341]
I guessed the issue is the Canvas->Flush() call, since according to the documentation there’s an alternative to this to flush in the rendering thread. It requires a convoluted argument, which it took myself and about 3 people on IRC to figure out how to even get. And using that it still crashes.
The first method just crashes on this line in BeginPlay()
CanvasTarget = UCanvasRenderTarget2D::CreateCanvasRenderTarget2D(UCanvasRenderTarget2D::StaticClass(), 1024, 1024);
Any ideas? Canvas render targets are useful things, and whatever got changed pretty much sunk one project of mine that I was working on.