gelly-gmod / gelly

Library to integrate fluids into a game engine
GNU General Public License v3.0
18 stars 3 forks source link

Rewrite the renderer #94

Closed yogwoggf closed 1 month ago

yogwoggf commented 2 months ago

Context

The renderer is absolutely one of the worst parts of Gelly. It is genuinely horrible, in all aspects. Before I dive into the scope, I'll provide a brief examination on why it is terrible.

Flaw 1: Custom rendering API

When Gelly was made, it was thought to be a generic library capable of interacting with different games. As time passed, this vision was quickly outmoded by the advancement in rendering within GMod--and the fact that Gelly would only be popular in GMod.

It's also a unrealistic decision founded upon the idea that all games have similar rendering pipelines to GMod which was just.. a deranged thought in entirety.

Graphics APIs

It was planned that I would add support for D3D11, 12 and maybe even Vulkan. This is why IRenderContext exists, to facilitate usage of said APIs without exposing the actual API being used. This was decided when I thought that an API was just a library, which was dead wrong. Every API has a philosophy attached to it, which means that making the same code work on different APIs is an invalid idea.

Resources were not considered

Again, every API has a philosophy to it--and resources were simply just never considered. Because of this, every resource class has far too many functions and exposes way too much internal data. They're very awkward and difficult to work with.

Pipelines are not a thing

The API that I exposed generally caused most code to become procedural, so there's no clear separation between what is a pipeline (i.e., a focused set of commands to generate something) and what isn't. This causes the separation of concerns to become muddy and forces us to perform entire resets of the pipeline each time we try to render something.

Flaw 2: Forcing OOP

Gelly's generic nature forced my hand at trying out Valve-style interfaces, which made everything so much more complicated than it should have been. Everything must be a class, even simple things like mapping a buffer.

OOP mixes data and functionality

This is a major issue in Gelly, data and functions are not separated. This means that we can't do no-copy constant buffers, or pass textures along to a raw rendering API call easily. In fact, who knows what the compiler does to our "fat" classes.

SRP was not respected

The best example of this is the splatting fluid renderer, weighing in at a staggering 45 member variables and 24 functions. All of these reduce the cohesion of the class to zero. Seriously, any function you examine will probably use less than five member variables.

It was not the right tool

Many things in Gelly simply do not fit into the paradigm. Mapping buffers require an interface, a class header and a class implementation. That is three source files to keep track of for every class. It also caused stuff like textures to become engorged classes with too many responsibilities. The lack of flexibility made it incredibly difficult to concisely write code for basic rendering operations. As of writing, this made the fluid renderer take up 62% of Gelly in terms of lines of code.

Flaw 3: Not keeping it simple

There was a strange, probably autism-related fascination with complicated rendering pipelines. I have got rid of this, to an extent, and it needs to be corrected in this ticket. Everything is way too complicated. Bridges between the simulation and the renderer needs to be clear, our pipelines should be easily readable and above all only have a single reason to change.

Scope

Acceptance Criteria

Other