cginternals / globjects

C++ library strictly wrapping OpenGL objects.
https://globjects.org
MIT License
538 stars 59 forks source link

Proper way to create a generic container of uniforms? #345

Open andrew-kennedy opened 7 years ago

andrew-kennedy commented 7 years ago

In my program I'm trying to store a map of "global uniforms" where drawn meshes can optionally override these with their own internal maps of uniforms. I am really struggling to get it to compile though, what with needing a generic container. I am struggling to understand if the container should be of type unordered_map<string, AbstractUniform> or unordered_map<string, ref_ptr<AbstractUniform>>.

As I understand it, I need to use the AbstractUniform abstract class in order to have containers of uniforms of arbitrary types. I would update these values by doing something like

container["modelview"]->as<glm::mat4>()->set(glm::mat4(1.0f));

However, I cannot figure out the necessary type signatures of functions to be able to pass around uniforms. I need to pass uniforms into my individual meshes, and I can't pass around a raw ref_ptr<AbstractUniform> because it can't be instantiated.

andrew-kennedy commented 7 years ago

Alright, so I got my project to compile again. My solution is to use a container of ref_ptr<AbstractUniform>. The problem I was having is I was using code like this:

auto uni = make_ref<Uniform<glm::mat4>>("projection");
container["projection"] = uni;

where the type of container was: unordered_map<string, ref_ptr<AbstractUniform>>

I can't figure out what exactly was the problem with this, but instead of using make_ref and auto, I now use:

ref_ptr<AbstractUniform> uni = new Uniform<glm::mat4>("projection");
container["projection"] = uni;
scheibel commented 7 years ago

Seems like a pecularity in C++ or a design flaw within our ref_ptr :wink: In your first example using make_ref you create a typed uniform and this type is bound to auto. Later on, this reference pointer of a typed uniform should get assigned to a reference pointer of an abstract uniform which isn't defined in our interface (but I see no reason against such functionality besides our current approach of explicit ownership and thus, a discontinued ref_ptr). In your second example, you declare a reference pointer on an abstract uniform whose constructor expects a pointer of AbstractUniform and, fortunately, your typed uniform pointer is convertible.