2
\$\begingroup\$

What is the best method to share the projection matrix and view matrix with all graphic entity shaders in a custom game engine? The refer graphic entities have glUseProgram({shader_program_id}); glDrawArrays(GL_XXXX, x);

One of my ideas is to have a camera object that manages the current view and projection matrix. Then, I pass a reference of that camera object to all the entities. However, my issue with that approach is syncing the current camera across all the entities/objects when switching views.

I could make the Camera global, however, that could have many issues.

\$\endgroup\$

4 Answers 4

6
\$\begingroup\$

In this answer I am assuming that you have a standard 3-matrix setup: projection, view and model. For your static objects the model matrix will be identity; for moving objects it will not. In your shaders you have something like:

out = projection * view * model * in;

Therefore projection and view don't change, model does, and hence your question.

This is actually an inefficient way of doing it. Instead you should premultiply the 3 matrices on the CPU and upload a single combined MVP matrix to the GPU.

So, in your C or C++ code:

MVP = projection * view * model;
glUniformMatrix4fv (..., MVP, ...);

And in your GLSL:

out = MVP * in;

This solves your initial problem in that you now no longer need to upload global projection or view matrices; since you're uploading a new model matrix per-object anyway you have no change there aside from the fact that it's now a combined MVP rather than an isolated model matrix.

This also solves your performance problem because you're now calculating the combined MVP once per-object only, rather than once per-vertex.

\$\endgroup\$
1
  • \$\begingroup\$ This is my current setup. I understand the performance increase, due to not solving the MVP for every vertex. However, making sure that the projection and view matrix stay the same across all entities is what I'm stuck on/worry about implementing. I noticed someone down below suggesting a Renderer class, and that does seem like a nice idea. However, I would like to keep the entities modular in some sense. I think I'm going to try and merge the Renderer class and Scene class into one manager type object... Again, this is me just trying to inquire other people's methods and opinions. \$\endgroup\$
    – NateAGeek
    Commented Sep 23, 2016 at 2:22
1
\$\begingroup\$

Did i get that right that you have the actual render method specified in the code for each different graphic entity? That is super inefficient, code-wise. Make a renderer-class and put all your shaders and draw-methods into there. Have a main render method that calls all the other render-methods specific to shaders or types of entities. Then you just have to pass your view matrix and projection matrix to that renderer object once and you can use it for each drawable.

In my engine, i store the projection matrix in that renderer class (it never changes though) and pass my camera to the renderer in each call of the render-method.

\$\endgroup\$
4
  • \$\begingroup\$ I do like this idea, and I am curious how Framebuffers are managed in your pipeline? Also, I'm curious how are you drawing everything at once? \$\endgroup\$
    – NateAGeek
    Commented Sep 23, 2016 at 2:38
  • \$\begingroup\$ I use two FBOs in my engine, one for shadow mapping and one that i render my scene before post-processing to. That one gets displayed on a screen-wide quad using the standard framebuffer. \$\endgroup\$
    – Djindjidj
    Commented Sep 23, 2016 at 8:02
  • \$\begingroup\$ I have a top-level renderer class in which i register every entity or drawable that is to be drawn. In that "top-level"-renderer I have multiple specific renderers that draw the registered drawables with their specific shaders (e.g.one entitiy-renderer and one post-processing-renderer). My fbos are stored in the "top-level" renderer and get passed to the specific renderes for the drawcalls as sometimes multiple renderers need to access the same fbos. \$\endgroup\$
    – Djindjidj
    Commented Sep 23, 2016 at 8:28
  • 1
    \$\begingroup\$ Now I am not sure what you mean by "draw everything at once", but I think you mean how I draw the whole scene and not only the output of one renderer? I just call the draw()-methods of every renderer (that has something to draw at that point in time) in my top-level-renderer's draw(). They all output to one fbo (that is then used for postprocessing) and thus i can test for depth etc. \$\endgroup\$
    – Djindjidj
    Commented Sep 23, 2016 at 8:32
1
\$\begingroup\$

I'm working in DX11 so idk how this will work for you.

I have one constant buffer that is common over all of my standard shaders, it has view, projection, far clip and camera position.

I update this one constant buffer at the start of the frame and have it set to slot 0 for all my drawing and then just set it once, so its update CB->set CB-> draw everything that uses the same buffer.

I hope I'm close to what u wanted to know?

\$\endgroup\$
1
  • 1
    \$\begingroup\$ +1, the OpenGL equivalent would be a Uniform Buffer Object. \$\endgroup\$ Commented Sep 22, 2016 at 9:14
0
\$\begingroup\$

In my "engine" I have a Scene class which contains all entities and cameras available. I also have a material component which is attached to the entity. At the rendering phase I call the entities material component from the Scene and passing the camera(s) to it.

\$\endgroup\$

You must log in to answer this question.

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