3
\$\begingroup\$

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).

\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

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:

<Material>
    <Shader source="shaders/water.shader" />
    <ShaderFlag name="_F02_NormalMapping" />

    <Sampler name="albedoMap" map="/textures/smallRock_diffuse.dds" />
    <Sampler name="causticMap" map="/textures/caustics/001.dds" />
    <Sampler name="normalMap" map="/textures/smallRock_normal.dds" />

    <Uniform name="textureMatrixRow0" a="0.0" b="0.0" c="0.0" d="0.0" />
    <Uniform name="textureMatrixRow1" a="0.0" b="0.0" c="0.0" d="0.0" />
    <Uniform name="textureMatrixRow2" a="0.0" b="0.0" c="0.0" d="0.0" />
    <Uniform name="textureMatrixRow3" a="0.0" b="0.0" c="0.0" d="0.0" />
    <Uniform name="fogColor" a="0.0" b="0.0" c="0.0" d="0.0" />
    <Uniform name="texScale" a="1.0" b="0.0" c="0.0" d="0.0" />
</Material>

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.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Thanks for the info. Horde3D seems to be doing just the same thing that the Ogre rendering engine relies on to tackle this issue. The only drawback is that this approach is by far not flexible enough to support the plethora of uniform and attribute variable families (for skinning, normal mapping, animation, custom particle effects, weather and so on). You end up sighing and accepting a certain compromise. I'll look into the way Cg handles it, although I know that their fx files are quite similar to what I already have. \$\endgroup\$
    – teodron
    Commented Aug 3, 2012 at 16:22

You must log in to answer this question.

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