IrrlichtWrapper Library

Lighting


Introduction

An extremely important aspect of creating a pleasing and realistic scene is getting the lighting right, while this can become a very complex subject there are many simple things you can do to make you scene look better.

Face Sizes

Lighting is applied to a model on a per vertex basis, when you are not using shaders, so having a good even spread of vertices should help you produce a good even lighting spread around the model. Avoiding long polygons to help stop long streaks of light on flat diffuse surfaces..


Scale and Normals

The normals in your model determine the direction that your vertices are facing, and are a very important as a part of lighting because the angle between the light, the surface and the camera determines the brightness of the vertex. One point of great concern when working with Normals is the fact that the normals have to be 'Unit Length' that is when the X, Y and Z of the normals are added up they should result in the number 1 (or very near to it).

In the example to the right the center node has the correct illumination, but the other nodes have been scaled with a call to IrrSetNodeScale and their normals have also been scaled the smaller nodes normals have become smaller and the node has therefore become brighter, the larger nodes normals have become larger and it has therefore become darker.
There are two ways to counter this effect when using dynamic lighting. After scaling your node with IrrSetNodeScale  you can then make the following call for the node.

IrrSetNodeMaterialFlag ( SceneNode, IRR_EMF_normalize_normals, IRR_On)

This call will make sure your normals are the correct length during rendering, however it may have a performance impact on your system. Another way is to use the new IrrScaleMesh call to scale the mesh instead without effecting the nodes. Scaling the mesh however will effect the scaling on all of your nodes.

Vertex Lighting

Vertex lighting lights your model by calculating how brightly illuminated each vertex should be. This depends on the angle between the light source and the camera, it also depends on the direction the vertex is pointing and the colour and material properties of that vertex. There are four main types of light sources that you can introduce to your scene.
  • Point Lighting - Radiates lighting out from a point in all directions. This is the default light time in Irrlicht.
  • Directional Lighting - Casts light in the direction that the light source is facing as if the lightsource was an infinate distance away. This light illuminates your objects from the same direction no matter where they are in the scene and is a good choice for sunlight.
  • Spot Lighting - Casts light in the direction that the light source is facing in a cone  that gets larger the further away you are from the light. This is a good choice for stage lights, flashlights etc ...
  • Ambient Lighting - This is a special light setting that effects all points in the model no matter which direction they are facing, it simulates the lighting that bounces around the environment from object to object making sure that some light is cast on surfaces that are facing away from the lightsource and looking unnaturally dark.
Equally as important are the materials that are applied to the object, these control how the lighting is reflected off your object as can be seen in the high detail object in the image below. 
  • Diffuse Color - Is the color of light reflected normally from the surface.
  • Specular Color - Is the color of the highlight where the lightsource is most brightly reflected. Specular color is added to diffuse color so to remove highlights set your specular color to black.
  • Ambient Color - Is the color of the light that is reflected ambiently from the ambient light setting in the scene. You could for example set a dim grey ambient light and then make the object reflect only blue ambient light, giving the object a blue tint.
  • Emissive Color - Is the color of the light that the object emits. Although the object itself does not become a lightsource you can make it appear as though it is glowing. This is useful for neon signs and very hot objects.
  • Shininess - This defines how small the highlights on your object are, the larger the number the smaller the highlights.

Each vertex in your model can also have a color and by default this vertex color overrides the diffuse color you set with an IrrMaterialSetDiffuseColor call. You can change which property is effected byt he vertex color or ensure that it effects no properties with a call to IrrMaterialVertexColorAffects( Material, ECM_NONE )

Diffuse lighting works well even with low resoloution objects but specular lighting is most effect with objects that contain lots of small polygons.

Shader Lighting


Another way to light your model is through the use of advanced shaders, GLSL and HLSL are two examples that can perform advanced lighting effects that programmatically control how light is reflected from the surface of your object.

In the example shown to the right a basic GLSL lighting shader has been added that is creating high quality highlights on the object. In the vertex lighting example above the highlights were improved by using a 9,000 vertex object. The pot to the left achieves the same level of detail on an object with just 1,000 verticies.

While many quality effects are now available you should consider that fact that not all PC graphics support shaders (this is especially true for integrated graphics).
It is always good practice to check the capabilities of your users system and to provide the best experience that you can for their hardware.

Shadows

When drawing an object Irrlicht determines the amount of light that hits the surface as if the whole scene was transparent, it does not perform the expensive task of detecting if that light is blocked by another object in the scene. This means shadows are an effect that need to be calculated seperately. There are currently four ways to create shadows within Irrlicht and each has its own benefits and its own drawbacks.
  • Shadow Baking.
  • Shadow Decals
  • Stencil Shadows
  • Shader Shadows

Shadow Baking

Shadow baking works by applying a texture to the object,  a texture that has the shadows already rendered into the image. This technique can only be applied to static objects and static lights but is perfect for things like buildings. As the shadows are pre-computed they can contain very expensive and realistic shadow calculations.

Shadows can either be baked into a texture along with the color information or it can be stored in its own image and applied with a seperate set of texture co-ordinates allowing color textures to be tiled for more detail, this is the technique used in many loaded BSP maps.

Here you can see that the object is casting a shadow onto the pedestal, there is a more defined shadow lighting down the side of the pot and the underneath of the rim of the pot is darkened into shadow.
The shadow map can also be mixed with dynamic lighting however to add dynamic tones to the object., this allows you to still use colored lights and to change the intensity of the light but you still cannot move the object or the light.

Many 3D packages support texture baking and your Graphics Artist should be familiar with the feature, we will examine implementation of the technique in Blender v2.49.
  1. Cleanly UV map your object. You can UV map it anyway you like automatically or by hand but you cannot have overlapping faces. Each face must occupy a seperate location on the texture. The quickest way to do this is to use the Lightmap UVPack feature.
  2. With your object selected and in edit mode, create a new image from a UV/Image Editor window. The higher the resoloution the better the shadow quality but the more memory that will be used.
  3. From the scene tab select the Bake pane and click on Bake. You will now see your shadow map rendered to the UV/Image editor window.
Before you load your texture it is advisible to switch off mipmaps for the shadow maps. Shadowmaps and Mipmapping do not work well together.

IrrSetTextureCreationFlag( ETCF_CREATE_MIP_MAPS, IRR_OFF )

That is all there is to it. You can now save your image from UV/Image Editor 'image' menu and use this to texture your model. Someone that is experienced with the 3D package can bake in textures, radiosity and other features.

Shadow Decals

Shadow decals are small rectangles with a transparent texture that are usually attached just beneath the node and above the ground.they are best created as a darkened spot that simulates the loss of ambient lighting on the ground.

Although they are not a realistic shadow effect they are simple quick to render, they do have the appearence of a shadow and can dynamically move to track the object and the light. If your object is flying above the ground they can give the observer a perception of how high the object is from the ground too.

When associated with static objects these masks can even be batched into a single mesh making them a fast and memory efficient way to apply simple static shadows.

Stencil Shadows

Stencil Shadows are a very commonly used technique and have the advantage that most hardware supports them including older graphics cards and integrated graphics chips. They appear to be realistic and accuratly render the shadows of moving and animated objects.

They do have disadvantages though, they are expensive to render as the effect has to be calculated by the CPU and not the graphics card. The more polygons you have enabled for shadows the worse it gets. The shadows will always have a hard edge also.

However if you use them sensibly and sparingly the effect works extreamly well and you can be confident that the vast majority of your audience will be able to see the effect.

To enable the effect you must enable shadows in your IrrStart call, call IrrAddNodeShadow for each node you want to cast a shadow and then finally set the color of your shadows with a call to IrrSetShadowColor.

Shader Shadows

Shader shadows are the ultimate in dynamic shadows and cast true rendered shadows across the objects they affect. The effect is achieved by using modern shader programs that run on the graphics card.

The effect is striking and very realistic it can show shadows from multiple objects, simulate light shone from flashlights and cast moving shadows even from animated objects.

The effect can be expensive however, each light is a separate render pass that requires a separate and large texture to save the shadow into. It also requires shader support so although it will run on many graphics cards it is unlikely to run on any PC using an older graphics card or an integrated graphics chip. So it should only be supplied as an option.

Shader shadows in Irrlicht are achieved through Bitplanes XEffect Reloaded module and to enable the effect you must enable the XEffects system with an IrrXEffectsStart call, then for each node that you want to cast and receive a shadow you should call IrrXEffectsAddShadowToNode and then finally spot lights are added with a call to IrrXEffectsAddShadowLight. These set the color and quality of your shadows along with the position, target and angle of the spotlight. This can take some work to get right but the results can be quite striking.

The Art of Lighting

While this discussion has examined the lighting tools that are available to does not examine how to use them effectively, however it would be remiss of me to not at least mention it. Lighting is an artform in itself that I find similar to sound, it adds emotional content to a scene, it can add drama, tension or any number of feelings to your actors, props and sets.

You will find many good discussions on lighting by simply search for terms like "3D lighting 101", "stage lighting 101", "Portrait Lighting 101", etc ...

Just dont underestimate it and if you have an artist creating your models discuss the lighting with him too and work out how enchancing your lighting can make a good model into a great piece of art.