Lighting a scene in Chilli Source is done in the, hopefully, now familiar way of entities and components.
Chilli Source currently supports the following lighting types:
- Ambient: Simulates global illumination by giving everything a base lighting colour.
- Directional: Simulates directional lighting from the sun.
- Point: Omni-directional light from a point source.
Lighting is rendered using a multi-pass system. This allows a scene to have multiple lights but the scene will need to be rendered again for each light source so be careful with the number of lights you use.
Here is how to create a light in CS. First include the lighting module:
#include
Then, as is usual with render components, grab the render component factory:
auto renderFactory = Application::Get()->GetSystem();
We then use the factory to create the light components and create the entities that are used to add the lights to the scene:
CSRendering::AmbientLightComponentSPtr ambientLightComponent = renderFactory->CreateAmbientLightComponent();
ambientLightComponent->SetColour(Colour(0.3f, 0.3f, 0.3f, 1.0f));
EntitySPtr ambientLightEnt = Entity::Create();
ambientLightEnt->AddComponent(ambientLightComponent);
GetScene()->AddEntity(ambientLightEnt);
Ambient lights require no position as they are applied uniformly across the scene.
CSRendering::DirectionalLightComponentSPtr directionalLightComponent = renderFactory->CreateDirectionalLightComponent();
directionalLightComponent->SetColour(Colour(0.5f, 0.2f, 0.2f, 1.0f));
EntitySPtr directionalLightEnt = Entity::Create();
directionalLightEnt->AddComponent(directionalLightComponent);
directionalLightEnt->GetTransform().SetLookAt(Vector3(-22.5f, 22.5f, -22.5f), Vector3::k_zero, Vector3::k_unitPositiveY);
GetScene()->AddEntity(directionalLightEnt);
The direction of a directional light is obtained from its rotation. In the above example the direction is set by pointing the light towards a target from a position. Unlike directional lights; point lights simply use the transforms position. Point lights also have an attenuation radius but beyond that are created the same way as the other two.
The final step is to make sure that your meshes are using the correct material type. The example shows how to set this in a material file but if you are creating materials via the material factory just use the equivalent create method:
…
The following material types are used for lighting:
- StaticAmbient: Uses only ambient lighting for static meshes.
- AnimatedAmbient: Uses only ambient lighting for skeletally animated meshes.
- StaticBlinnPerVertex: Blinn-phong lighting for static meshes lit per-vertex.
- StaticBlinn: Blinn-phong lighting for static meshes lit per-pixel.
- AnimatedBlinnPerVertex: Blinn-phong lighting for skeletally animated meshes lit per-vertex.
- AnimatedBlinn: Blinn-phong lighting for skeletally animated meshes lit per-pixel.
The lighting values set in the material are multiplied with the colour set on the light. Often it is best just to set the colours to white and use only the colour from the light. It is important to set the emissive value to zero otherwise the object will appear saturated.
Shadows
Chilli Source also supports hard shadows for directional lighting using shadow maps.
Only a few changes are required to add shadows to directional lighting:
1
CSRendering::DirectionalLightComponentSPtr directionalLightComponent = renderFactory->CreateDirectionalLightComponent(2048);
When you create the light component you specify the shadow map resolution; in the above example that is 2048×2048.
directionalLightComponent->SetShadowVolume(70.0f, 70.0f, 1.0f, 70.0f);
directionalLightComponent->SetShadowTolerance(0.005f);
The shadow volume is an orthogonal box extending from the position of the light. Any objects inside the box will cast and receive shadows. The smaller the volume the better the shadow quality.
The shadow tolerance can fix noisy shadow artefacts and needs to be tweaked on a case by case basis.
The only thing left to do is change the material type by appending “Shadowed” to the end of the above material types (e.g. “StaticBlinnShadowed”). This allows the object to receive shadows.
Note: We are planning on refining this soon to remove the need for the shadow volume.
Another helpful tip is to prevent objects from casting shadows:
staticMeshComponent->SetShadowCastingEnabled(false);
That’s all you need to start lighting your scenes.