Light and shadow

· by Steve · Read in about 3 min · (618 Words)

Well, this week is the start of my new working life proper, and whilst I’ve had to spend a bit of time sorting out admin type things, I’ve been trying to polish off a feature I’ve had in my head for a couple of weeks before I get stuck into a client project tomorrow.

Ogre’s always had some pretty cool real time lighting and shadowing features, not least of which was 4 dynamic shadow techniques (2 stencil and 2 texture based), with a ton of configuration options and, in particular with texture shadows, lots of opportunity to do funky shader-type things. Recently as part of the Summer of Code, the ability to customise the projection bases for texture shadows was streamlined, leading to the potential for plugin classes for plane-optimal shadows, or others like PSM / TSM.

We’ve also had a pretty rich multipass system to deal with both modulative and additive lighting routines, which have worked well - however, whilst they are convenient, in that they lay right on top of pretty much any material giving you shadows with almost no thought, they also don’t represent the best efficiency or the most flexible lighting algorithms, since the automation locks you into a particular shading sequence (post-process darkening, or iterative per-light masked adding). What I really wanted to do was let savvy people compress these into the minimum passes they needed, and give them the ability to do more complex routines with the information to hand.

This has led to several new options when using texture shadows. You can now append _CUSTOM_SEQUENCE to the end of either of the texture shadow techniques, and immediately you’re in control of how the texture shadows are used. The shadow textures are still rendered for you, but they are not applied to objects automatically - you’re in charge of doing that (although we make it as painless as we can). You simply include the directive ‘content_type shadow’ in your texture unit, and Ogre will bind a shadow texture in there and set up the projection (if you use a shader you can use the texture_viewproj_matrix auto-binding). You can do this in more than one unit in one pass, taking into account multiple lights and their shadows at once, and if you use pass iteration to deal with many lights, the subset of lights / textures reflects that iteration. One major difference is that you can now use the iteration option ‘per_n_lights’ instead of just ‘per_light’, and you can also use ‘start_light’ to offset the starting point. This lets you do clever things like packing most of your complex diffuse work (including shadows) into your first pass, then iterating for however many remaining lights are remaining, grouped into ‘n’ lights per pass, then perhaps do a final specular pass in one go with the most important lights again masked by the shadow textures. That’s a lot less passes than normal but still with full additive lighting accuracy.

That’s just one example but it can significantly cut down the number of passes you need to do for a lot of lights, and at the same time give you more power in your shaders. In the right hands it will be pretty darn useful I think - although novice users may well want to stick to the simpler but less flexible / slower bolt-on approaches.

I’m not meant to be working evenings anymore but I stayed up to finish this. No screenshots yet, my tests are just hideous programmer art and I’m out of time (it’s midnight and I promised my wife I wouldn’t be doing this anymore - oops). If I get time later in the week I’ll knock up an attractive example 😉