Hello GameDev.net,
This is going to be a comprehensive question and I don't expect a single person to be able or have the time to answer the whole thing. Rather, I would appreciate if the community can chime in on parts that they know and so that this can be used to collect information on creating a modern renderer for future beginners looking into it.
I'm currently trying to write a renderer for my engine. In the past, I just did a for loop on all the meshes in a scene and rendered them. The issue is, as many of you know, if you're working with a scene node hierarchy, the ability to do that breaks. That and that you have to manually write things in the correct draw order (shadows, gBuffer write step, lighting step, skybox). At this point, you need to start using render commands, render queues, etc… to implement a job based system.
Now, I always hear a lot of terms being thrown around and as someone who's inexperienced in this, it can be hard to see how all these terms come together and how they are implemented in actual code. The terms I hear are:
- Drawables
- Bindables
- Render Command
- Render Queue
- Render Step
- Render Pass
- Render Technique
- Render Context
I roughly understand each of these terms but struggle in designing something that implements them as any engine source code I look at uses different terms or has the code of these implementations spread out through multiple files so it becomes cumbersome to bring things all together.
So here are my following questions to help me and others build and understand a proper renderer:
- Could I please have a list of common bindables?
- If a bindable is an abstract class, how do we define its call signature? This is because some things bounded need to be identified using strings and numbers such as textures (in OpenGL) and somethings don't need that information such as vertex arrays. If we define a call signature as: Bind(RenderContext& context) for example, how will a texture know what name or location it should use? Unless we define that in the texture class itself when it's loaded?
- What would we put inside a render command? Does someone have any basic class diagram for a render command?
- If each pass has it's own queue, how does a drawable know which pass to put a render command in? How does it even know which passes exist? I don't think a drawable should know about the existence of passes because what if you want to add a new pass? Do you then have to add more code in each different type of drawable?
- What is a render step?
- What is a render technique? I know this is where in general you'll have information on passes and steps and this is where you would define the technique used to render a PBR pipeline for example, but what is it in general? and how does it connect with other parts of the renderer?
- What data is necessary to keep in a render context?
- Does anyone have any UML diagrams or any other sort of architecture designs for a renderer that might prove useful?
I'll edit this question with the most comprehensible answers given to each question as they come. If anyone wants to add any questions and I see them, I'll add them to the list.
Thank you for your time!