Best way to draw camera frustum on minimap?


I am trying to create a graphic of camera frustum projected on a minimap of an RTS game. I want it to be dynamic, so that it reacts to zoom and rotation of the camera, so the idea of pre-rendered projected frame mapped into UMG widget component fails.

I am doing 4 line traces for each corner of the camera view, and then gathering the world locations, and remapping XY coordinates of those 4 world locations from the world map size into 2D vectors in 0-1 range.

The question is how to use them, and how to do it efficiently.

  1. There is a DrawLines function in UMG, which requires to be called from overriden OnPaint. It’s great because it takes exactly array of 2D vectors to connect into a continous closed shape. The problem is I absolutely can not figure out how to erase the buffer. I think it’s meant to do literally painting and painting only, not actual per frame drawing. What this means that I always get accumulation of the every frame, rather than fresh image every frame:
    Since I can’t figure out how to clear the UMG Paint result every time, this approach has failed.

  2. Then I tried using BeginDrawCanvasToRenderTarget, which creates canvas on which the primitive shapes can be drawn on too. The problem here is that by default, it accumulates too. Luckily, this can be mitigated by calling ClearRenderTarget2D. The problem I’ve ran into here is that one has to Being and End drawing each frame. If I do BeginDraw -> Draw Line -> End Draw, everything works, but I need to draw multiple lines, and unlike UMG, Draw to Canvas function set has only DrawLine function, not DrawLines. So I have to do 4 line draws. As soon as I execute a loop of 4 line draws, and call EndDrawCanvasToRenderTarget, for some reason the RenderTarget clearing stops working, and I run into the exact same issue as with #1.

  3. I also tried to do some craziness with the material, where I tried to distor the UV space using the 4 corner 2D vector (Something like 4 pin warp in Photoshop):

    And using this craziness, I’ve managed to get it sort of working, but it completely falls apart as soon as I rotate the camera around Z axis even slightly.

So all 3 approaches have failed.

So I was wondering if someone knows about something else I can try. Ideally it should be as simple and performance friendly as possible.

Thank you in advance.

By just drawing triangles.

It’s fully redrawn every frame, it just draws what’s in the array. Instead of adding elements to the array, set them.

How does drawing triangles help with drawing lines? Or is this supposed to be filled? Then draw triangles for sure. :slight_smile:

Yeah. Nevermind. I just found a bug where I was adding to the array rather than overriding it. So it was not a clearing issue (Or rather it was, but it was about clearing the array, not the resulting rasterization, which clears by default, as one would expect) :slight_smile: It works well now via OnPaint in UMG.

That being said, I am also curious about the triangle approach by @Deathrey , since I would want to eventually stylize the frustum frame with some sort of decorative texture. I saw some functions to draw triangles, but let’s say I’d draw two of them. How would I generate proper UVs for them so that they form a seamless UV space across resulting quad? Also, I am worried that if it was a triangle based quad, distoring it in perspectives would actually create a sharp bend across the line where the two triangles join.

So while that could be a valid approach, I am not sure it meets the “Simple” criteria.

Consider looking into the HUD class and its Draw Material Triangle:

I don’t have an answer to your questions, would need to get my hands dirty with it first. It’s quite similar to procedural meshes. Not sure if you find it helpful.

I can try it in future, but so far I try to avoid HUD and stay in the Widget Blueprint, as it can become a bit too complicated juggling between the two, especially when HUD uses screen space while Widgets seem to use viewport space. The conversions then become a bit ugly.

Thank you non the less :slight_smile:

So I’ve managed to get the triangle duo going, and it’s working pretty well (Better turn down the volume as I forget to pause music while recording):

I am a bit confused about one thing though.Draw to canvas is set of functions BeginDrawCanvasToRenderTarget and EndDrawCanvasToRenderTarget. The minimap will be displayed throughout the whole game, but I am unsure if I should call BeginDrawCanvasToRenderTarget and never call End, or if I should call both before and after drawing every single frame. I think former is a way to go, but I am worried about some garbage possibly accumulating during the game, as I am really unsure how this works.

Neat! I remember drawing entire polygons this way, but there was some kind of limitation I couldn’t crack back then.