1
\$\begingroup\$

In my 2D game project, as well as in LibGDX in general, are a lot of different entities that need to be rendered(static images, sprites, animations, etc...), as well as have certain effects applied (shaders). Most, if not all, tutorials show a simple hardcoded way of rendering each sprite instance, or at the most, a loop iterating over one type of renderable entity and rendering it.

I have a need to render a decent number of entities (~1000 static(background/tilesets) and dynamic(characters) per screen) where certain entities might have one or even multiple shaders applied to them. I'll also probably have to deal with rendering to FBO's to be able to apply multiple shaders on entities, though I haven't yet reached that point so I'm not sure yet (so far my entities have either 0 or 1 shader, but I'm planning on placing multiple shaders per entity soon so I need to take that into account).

I don't know what rendering techniques would allow me to accomplish this task however I've got some ideas I'm stuck with.

For more context I'm also using an ECS but I'm not coupling rendering to it.

My current idea is to have a RenderingEngine of sorts, decoupled from ECS. It would basically contain a queue of... something, some message POJO describing what and where to render. This queue would then, each render cycle, be sorted according to layer, type, shader and then be distributed to their own appropriate renderer.

The gist is that other game systems send a message to the RenderingEngine describing what they want rendered and then the engine works out what to do with it the next rendering cycle.

Current issues I've got with this idea:

  • Messages might prove to be a performance overhead as they are plain objects created for the sole purpose of sending a message over. This could probably be alleviated via pooling.
  • Shaders. Without shaders rendering logic is fairly simple [sort by layer -> for each layer sort by type -> render]. Shaders however are applied per batch and that confuses me. I am not sure where in the above rendering logic would shaders fit in...

Am I reinventing the wheel? Is there a standard technique of accomplishing this kind of "flexible" rendering?

Is the queueing idea I've described above a part of some well known technique I could investigate for clues?(My searches have given me no anwsers so far)

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

You have started reinventing the wheel the moment you have started writing your own engine, but there is nothing wrong with that, that is why game frameworks exist (and this approach has many benefits over using an existing engine).

What you describe is somewhat similar to how libGDX's ModelBatch works. It deals with 3D graphics, but the sorting is similar, just instead of messages it uses Renderables, which are your "POJOs of what needs to be rendered". By the way, you may also want to sort by texture, unless you have everything on single texture atlas page.


The gist is that other game systems send a message to the RenderingEngine describing what they want rendered and then the engine works out what to do with it the next rendering cycle.

Have you considered creating a "Render" component and system in your ECS? Typically every system in ECS decomposition does only one thing (and does not concern itself with rendering - unless it is a render system, in which case it does not do anything else).

I am not saying that this is a bad idea or that it won't work, but it might simplify your code by gathering everything render-related into one single system. Then you can apply all sort of sorting/batching optimizations (if you need them) without affecting whole codebase.

\$\endgroup\$
2
  • \$\begingroup\$ I'll check ModelBatch source out and see what I can "lift" off of it :D. Regarding the Render component. I'm using artemis-odb which doesn't seem to quite work with polymorphic components (so I can't for example make a system which gathers all Renderables), though my idea was to basically have a RenderSystem which would pass renderable data over to the RenderEngine thing i mentioned in the OP. \$\endgroup\$
    – user99146
    Commented Aug 15, 2018 at 7:00
  • \$\begingroup\$ Polymorphism isn't the only way to do this. You could have separate passes that act on each of your renderer types, or use a common RenderSort component to gather and sort them into rendering batches. \$\endgroup\$
    – DMGregory
    Commented Aug 21, 2020 at 11:25

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .