Note: the following description is a cut&paste of now closed issue #1741. We reopen it here to create an Epic, a container for a number of related issues.
The current renderer is largely an hardcoded implementation. It features a number of features that can be toggled on/off, i.e. light shafts, or enabled to some pre-defined level, i.e. Depth of Field blur levels. But it is inflexible in the sense that new features must be added to the source code rather than, say, injected at runtime by a module.
Also, while the renderer might eventually support the concept of multiple cameras, each camera would have to render in pretty much the same visual style, dictated by the settings stored in the rendering config unless some kind of overriding machinery is added to enable/disable features separately from the rendering config. For example, CCTV-like cameras might not require the full range of visual effects currently available through the renderer, but might require some additional or alternative processing to provide their typical black&white, grainy/noisy look.
In this context I'd like to propose here the embryo of a new architecture for the renderer.
The current renderer is mostly a collection of conceptually atomic rendering tasks. I.e, first the shadow map for the main light is rendered into a buffer. Then the scene reflected in the water surfaces is rendered into another buffer. Then the sky, the landscape and its inhabitants. Transparent objects are blended in and (skipping a number of steps for brevity) a number of post-processing effects are added eventually leading to (ta-dah!!!) the final image shown on screen or saved into a screenshot.
The key idea of the new architecture is to recognize that these tasks are organized into a Directed Acyclic Graph (DAG), by virtue of the fact that each task is potentially dependent on the output of other tasks being executed first and the fact that most tasks eventually provide the inputs for tasks that follow. This DAG is what is commonly referred to as the rendering pipeline, despite it not being quite a line but a number of branching and potentially overlapping paths.
In this context, adding new features should be as easy as adding tasks to the pipeline, or to better put it, nodes to the graph. Similarly, disabling features should be as easy as removing nodes from the graph. For example, at this stage OculusVR code is intertwined with the standard mono rendering mode. Enabling or disabling a given stereo mode (not just Oculus) would then be a matter of replacing a number of tasks in the pipeline with the stereo-only or mono-only version of them. All at runtime.
The new architecture should also allow for multiple pipelines to coexist.
Also to keep in mind as potential, advanced, self-optimization features:
From the time the description in #1741 was written an important thing happened: our organization was accepted in the Google Summer of Code (GSOC) initiative.
This in turn had a number of consequences:
In particular the concept of nodes and tasks is now built in the rendering engine and all the _conceptual_ rendering steps are now wrapped into nodes which in turn trigger (or not!) rendering tasks. The rendering tasks are then executed every frame.
Also, one of the item described above is the automatic elimination of redundant OpenGL state changes, i.e. preventing the binding of the same frame buffer multiple times in a row, unnecessarily. This has been accomplished via classes implementing the StateChange interface.
Much remain to be done to complete this overhaul of the rendering engine. I will strive to add issues to this epic detailing what needs to be done. But let me list a few big items:
I'd like to conclude here this update. Stay tuned.
@emanuele3d I'm considering redesigning this system for GSoC, and I have a few questions:
@hybrideagle: Hi. Please note this issue is an "Epic". An Epic is a container for smaller issues, but you can see it that way only installing ZenHub: in GitHub you'll see it as a standard issue.
Regarding your questions:
This issue is a bit vague in what it describes, but it looks like it's now complete, with the extraction of the rendering graph to the CoreRendering module.
Most helpful comment
Since then
From the time the description in #1741 was written an important thing happened: our organization was accepted in the Google Summer of Code (GSOC) initiative.
This in turn had a number of consequences:
In particular the concept of nodes and tasks is now built in the rendering engine and all the _conceptual_ rendering steps are now wrapped into nodes which in turn trigger (or not!) rendering tasks. The rendering tasks are then executed every frame.
Also, one of the item described above is the automatic elimination of redundant OpenGL state changes, i.e. preventing the binding of the same frame buffer multiple times in a row, unnecessarily. This has been accomplished via classes implementing the StateChange interface.
To be done
Much remain to be done to complete this overhaul of the rendering engine. I will strive to add issues to this epic detailing what needs to be done. But let me list a few big items:
I'd like to conclude here this update. Stay tuned.