Drawing from Lua could be better in Spring-106

Drawing from Lua could be better in Spring-106

Discuss the source code and development of Spring Engine in general from a technical point of view. Patches go here too.

Moderator: Moderators

Post Reply
CommanderSpice
Posts: 29
Joined: 29 Jun 2011, 13:14

Drawing from Lua could be better in Spring-106

Post by CommanderSpice »

In spring-105 we used the fixed function pipeline of OpenGL more or less directly:

Code: Select all

function draw()
    gl.Color(1,0,0,1)
    gl.Vertex(0, 0, 0)
    gl.Vertex(1, 0, 0)
    gl.Vertex(1, 1, 0)
    gl.Vertex(0, 1, 0)
end
gl.BeginEnd(GL.QUADS, draw)
That was very flexible, because you could do anything with OpenGL from Lua.
Also it was trivial to write a wrapper like this in Lua:

Code: Select all

DrawRectangle(x1, y1, x2, y2, color)
Spring-106 dropped OpenGL 3.

Now you need to create shaders and a vertex array and update it from Lua.
It is not flexible, because you cannot define vertex attributes from Lua, you have to select from available attributes and shoehorn them to your use case.
You have to know how many vertices you want to draw at most, because the vertex array has a fixed size. And the full vertex array is sent from Lua to C++ whenever you update it.
Writing the DrawRectangle wrapper is not trivial.
And it is not accessible for new widget creators: This is a lot of stuff to know for some dude who just wants to draw a rectangle on the screen to visualize where your units would do their square patrol.

So wrapping the OpenGL API in Lua worked great for OpenGL 3, not so much for OpenGL 4.

I am not complaining about the direction the engine development took, having seen 4-digit FPS early game with spring-106. I just think this part is broken and needs to be fixed.

I did try writing stuff on the Lua side to provide the old interface. It works, but it is a dirty hack. And the performance is not that great.

I think Spring should provide the draw functions that every game (and some widgets even) used to define, so widgets can draw with functions like Spring.GFX.DrawRectangle() and the engine sets up the shaders, manages a vertex buffer for the widget and does whatever neccessary to draw the rectangle. I know the engine does not know about different widgets, so the details still need some thought.
A handful of draw functions (or like 20) should cover most of the use cases.
Spring.GFX could be mostly independent of the graphics API, so the Lua side would need little or no update when someone does a Vulkan port of the engine.
It would be less flexible, but the OpenGL 4 API would still be there for fancy stuff.

Any comments on the technical aspect of this? This is just a request for feedback before I start any work on the engine.
CommanderSpice
Posts: 29
Joined: 29 Jun 2011, 13:14

Re: Drawing from Lua could be better in Spring-106

Post by CommanderSpice »

Pull request is here https://github.com/spring/spring/pull/581.
I settled for Spring.Draw.Lines, Spring.Draw.Triangle, Spring.Draw.Rectangle. Encountering several BA widgets that did their own bevels and radii each, Spring.Draw.Rectangle has parameters for that when drawing to screen. Also borders are probably useful there.
raaar
Metal Factions Developer
Posts: 1094
Joined: 20 Feb 2010, 12:17

Re: Drawing from Lua could be better in Spring-106

Post by raaar »

I think Spring should provide the draw functions that every game (and some widgets even) used to define, so widgets can draw with functions like Spring.GFX.DrawRectangle() and the engine sets up the shaders, manages a vertex buffer for the widget and does whatever neccessary to draw the rectangle. I know the engine does not know about different widgets, so the details still need some thought.
This.

The key here is that the engine should provide an interface with functions to generate basic UI components : draw rectangles with some border,color,texture configuration and drawing fonts.

There could be an extra ID parameter that's passed to help the engine figure out which calls can be "bundled together" for more efficiency.

Although I'll end up using BAR105 engine, thanks for doing this work. It'd be nice if both engines converged to use the same interface.
CommanderSpice
Posts: 29
Joined: 29 Jun 2011, 13:14

Re: Drawing from Lua could be better in Spring-106

Post by CommanderSpice »

I agree that addon compatibility between Spring-106 and Spring-bar would be a good thing.

You should talk to the maintainers of spring-bar about this. Spring.Draw should be easy to merge into the engine fork as it is not very tightly coupled to the OpenGL wrappers of the engine. Be warned that I do not consider the interface stable, until the port of BA as a reference game is done.

For a dirty workaround, a compatibility layer in Lua to translate Spring.Draw calls to OpenGL 3 is easy to do. This would allow to use all Spring-106 addons with Spring-105.
CommanderSpice
Posts: 29
Joined: 29 Jun 2011, 13:14

Re: Drawing from Lua could be better in Spring-106

Post by CommanderSpice »

Test host running spring-develop and BA-106 is up.
Lots of UI still missing, but it is playable.

Performance looks good: I get 1600 FPS at game start.

Widget status overview: https://github.com/Balanced-Annihilatio ... 1360418713
User avatar
Beherith
Posts: 5145
Joined: 26 Oct 2007, 16:21

Re: Drawing from Lua could be better in Spring-106

Post by Beherith »

I admire the effort you are undertaking here, CommanderSpice.

I have looked at the Spring.Draw engine PR, and if I'm not mistaken, then it looks like a vertex array-based wrapper for what could have been done through Lua, but now its faster because its running natively in the engine.

While this approach does solve the opengl core profile issue, I'm unsure that it will scale well. Having each widget execute a Spring.Draw call every frame, for every UI element, and moreso each unit it wants to draw something around, and having to query the visibility of that unit every single frame is excessive overhead.

This approach is identical to the old maintenance approach, and not sustainable even in the medium term, and also loses out on OpenGL 2 display list gpu-side caching.

When drawing multiple similar things every frame (like UI elements, or unit selection indicators, or healthbars), these elements should be grouped together and submitted in a single Draw call, using DrawArraysInstanced, or DrawElementsInstanced.
CommanderSpice
Posts: 29
Joined: 29 Jun 2011, 13:14

Re: Drawing from Lua could be better in Spring-106

Post by CommanderSpice »

I am aware of the immediate ^^ downside of the approach and I understand your doubts about it scaling well: Replacing display lists with draw calls cannot improve performace. But this is not about improving performance. This is about dragging the engine kicking and screaming into the future. Display lists and stippled lines are sacrificed on the altar of progress.

It may not run as fast as 105 at first. But it will be playable. Then it can be optimized, free of ancient OpenGL. I know that there is no way around caching vertex data in VRAM and instanced drawing. It would be nice to have this optimizations engine-side and not bother addon authors with it more that necessary, but we'll see about that.

The engine needs to learn to crawl again, before it can fly.
ivand
Posts: 310
Joined: 27 Jun 2007, 17:05

Re: Drawing from Lua could be better in Spring-106

Post by ivand »

CommanderSpice wrote: 20 Dec 2022, 09:57 I agree that addon compatibility between Spring-106 and Spring-bar would be a good thing.

You should talk to the maintainers of spring-bar about this. Spring.Draw should be easy to merge into the engine fork as it is not very tightly coupled to the OpenGL wrappers of the engine. Be warned that I do not consider the interface stable, until the port of BA as a reference game is done.

For a dirty workaround, a compatibility layer in Lua to translate Spring.Draw calls to OpenGL 3 is easy to do. This would allow to use all Spring-106 addons with Spring-105.
While I agree with the first sentence, this is not what we should build a common ground upon. Uploading the geometry from Lua every draw frame is like the worst thing you can do. I missed that initially in your PR, but it's a big design flaw.

Coil/BAR105 API is based on GL4. Our APIs assume the data is uploaded once and is drawn in instanced or indirect way. Copying the API proposed here would be a step back. As is it's worse than the old and now removed in 106+ gl.BeginEnd(), because the latter could at least be cached GPU side with the use of display lists.

This will need API re-design and re-implementation to become a common ground standard.
Post Reply

Return to “Engine”