1
\$\begingroup\$

I am planning to build a Shader system which can be accessed through different components/modules in C++. Each component has its own functionality like transform-relevated stuff (handle the MVP matrix, ...), texture handler, light calculation, etc...

So here's an example:

I would like to display an object which has a texture and a toon shading material applied and it should be moveable.

So I could write ONE shading program that handles all 3 functionalities and they are accessed through 3 different components (texture-handler, toon-shading, transform).

This means I have to take care of feeding a GLSL shader with different uniforms/attributes. This implies to know all necessary uniform locations and attribute locations, that the GLSL shader owns. And it would also necessary to provide different algorithms to calculate the value for each input variable. Similar functions would be grouped together in one component.

A possible way would be, to wrap all shaders in a own definition file written in JSON/XML and parse that file in C++ to get all input members and create and compile the resulting GLSL. But maybe there is another way that is not so complex?

So I'm searching for a way to build a system like that, but I'm not sure yet which is the best approach.

\$\endgroup\$
  • \$\begingroup\$ Why not implement it yourself? If you implement only functionality you need, and use XML parsing lib -it is just a few lines of code. \$\endgroup\$ – wondra Aug 23 '14 at 23:22
2
\$\begingroup\$

There are many ways to handle this kind of logic in a shader:

  • Use dynamic branching: Plain ifs are not that slow on modern hardware. Test and profile it. If it doesn't slow down your application, this is probably the most straightforward and flexible solution.

  • Use shader subroutines: This is a new GLSL feature. It is supposed to be faster than dynamic branching and provides a lot of flexibility to shader code writing.

  • Use compile-time directives: Write the shader code with #ifdefs that enable/disable paths according to the global flags set at compile time. This is also a very common approach that has no runtime cost.

  • Build the shader during runtime from code snippets: This is what you are proposing with the XML/JSON idea, I believe. It is pretty much the same as using #ifdefs and conditional compilation, but can give you more flexibility to adjust the shader code for providing fallback to older hardware/missing features. This can be a fairly complex approach, which I would try to avoid for a small to mid size project. It can involve a lot of code and maintenance overhead for the programmers. Read this blog post for an interesting discussion on this subject.

Overall, you will probably end up using some or all of the above options.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.