I’m wondering about whether it would be possible to improve the speed of drawing lines in the Engine. I’m hitting a hard wall with my current implementation, but I see no reason why (with better implementation) I couldn’t draw ten times as many lines as I currently am before being GPU bound or something.
So here’s what I’m trying to create, and I’ve got fairly far with it. It’s a local-area radar that essentially scans it’s surrounding environment and draws blips for objects and a wireframe of the terrain underneath. It also rotates to always point north (like a compass) relative to the players rotation. I do this by using the DrawLines() functionality of UMG/Slate – which draws a bunch of elements to the screen that connect together. However, it seems incredibly slow to do so.
Goal:
Current in Unreal:
A little background on how I’m doing it – I break a big volume brush around the level into a sparse grid, and do a series of line-traces from the heavens to the ground to work out the location at each grid point (really, I only need the altitude since I know the column and row of each point, and the density, but I’ll get to that later) – and then store that in a 1D array of FVectors in the GameInstance (1D array is faster to access and UE doesn’t support nested containers anyway). This is only done once on level load, so there’s no runtime overhead here.
I then go column-by-column then row-by-row, transform each point to the correct position on the screen accordingly (via a rotated FLookAtMatrix and ForthoMatrix) and submit an Array of 2D points to UMG/Slates DrawLines() function in OnPaint(), which actually creates the visual lines as part of a UserWidget. All the transforming is done in Code and eventually the OnPaint method will be as well, but this is it in Blueprint at the moment:
The code which projects the points into screen space is pretty **** fast (< 0.3ms for 10000 points), but the bottleneck appears to be not only multiple calls (Columns * Rows) to DrawLines() per-frame, but also the actual drawing of the lines themselves.
I did a few tests, and submitting a single Batch of 65536 points to DrawLines() takes slate about 9ms to draw, which still seems extremely high considering it’s only drawing lines. I feel like this could be a lot faster, or maybe there’s a better system for doing it?
My current method does a call to DrawLines() for each column and row, so for a 100*100 grid with 10,000 vertices, I’m doing 200 calls to DrawLines() per frame and slate takes a full 30ms to draw on it’s own. 10,000 vertices isn’t a lot, and I want to be able to draw them much faster. I need a way to submit all the lines in one Batch by creating my own version of DrawLines() - which still maintains the grid-shape with no connecting lines at the start/end of each column/row. Anybody know how I could do that?
Another huge performance boost I can gain is by only submitting the lines that I need to draw. Right now I’m submitting the entire array, but I actually want to draw a circle of points around the player (up to Range X) – so is there a way I can extract the points from the array in a circular pattern and still draw them correctly in a grid pattern? This should result in far less lines being unnecessarily drawn before then being clipped by the widgets screen size bounds anyway.
Perhaps doing this with Slate Elements isn’t the way to even go about this. Is there a preferable solution?