Thursday, May 14, 2015

shaders - What is an efficient way to manage uniforms in a game?


Most engines on the market have their drawbacks and it's difficult to find a simple/light-weight one that's open-source and doesn't have to put you through a rather complex learning process. Writing one is a difficult task on its own, but it might not be a bad idea if what you want that engine to do is to support a specific kind of games (e.g. 2.5 D games on mobile devices).


So, in search for a good game engine architecture, I've found a few logistical issues. Consider this scenario:


Objects:


Each object is comprised of two principle structures of render information:



  • a model (geometry mainly) and

  • a material (that tells the object what textures and what shaders to use).



Of course, it is natural to allow an object to switch its material definition on the fly. But a material encapsulates the shaders, so these drag along with them some slots for uniforms and vertex attributes.


Since an uniform, for example, can be:



  • object specific (color, specular exponent, etc.)

  • global/superglobal (lights, weather conditions/fog/wind,etc.) or

  • specific to a group of objects (they all have, let's say, a reflectivity factor)


then it means that it's wrong to put them in either the object's property region or in the material's property region. It's clear that both uniforms and attributes are always declared in the shader sections of a material, but where their values come from is an enigma in the frames of a pretty general rendering engine. You have to allow for the existence of numerous types (by semnatics!) of uniforms: position, colour, bone matrices, indices, lighting parameters, etc.




The big question now: how would you suggest to organize and manage uniforms? (especially the information flow - they're declared by shaders, but their values are supplied by apparently different type of entities - some renderable, some more abstract, being themselves controllers or managers).




Answer



The way Horde3D (open source OpenGL engine for desktop) handles it is by putting the shader into the material. For instance, we have the following material definition:



















Horde3D says: a uniform is part of the shader and the shader is part of the material. So a material should be able to set its uniform variables.


What they've also introduced is the concept of ShaderFlag's. This is a define in the shader source that turns features on or off. They have a shader preprocessor that resolves these settings to generate the final source. What this allows is for several materials to share the same shader, but with different settings.



For instance, our main character needs animation, so it has the _F02_Animation flag, but a rock doesn't need it. The generated source is therefor completely different, but they use the same shader.


In my own engine, I store the uniform variables per shader object. When I render my particle emitters, I enable the particle shader and let every emitter attach their vertex attribute array and textures. So the shaders handles certain uniform variables (projection matrix, corner points for screenspace quad), but the emitters supply their positions, sizes, rotation and color.


This also allows for a fallback path: preferably, a geometry shader is used to convert points to textured quads, but if that capability is unavailable the corner points will be calculated on the CPU.


I can't give you a final and definitive answer (I'm still working this stuff out myself), but a good starting point could also be to look at how Cg shaders abstracts things.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...