Lighting System
The Lighting System in Raftel Engine provides a robust framework for illuminating your 3D scenes with various types of lights, including directional, point, spot, and ambient lights. The system also supports shadow mapping for creating realistic lighting effects.

Light Types
Raftel Engine supports multiple light types, each with specific behaviors and use cases:
Directional Light
Simulates light from a distant source like the sun. All light rays are parallel and have the same direction, casting shadows in the same direction regardless of object position.
Point Light
Emits light in all directions from a specific point in space. Ideal for light bulbs, torches, or other localized light sources with a defined range.
Spot Light
Creates a cone of light from a specific position and direction. Features inner and outer cone angles to control the light's falloff and focus.
Ambient Light
Provides a base level of illumination to all objects in the scene regardless of their position or orientation. Used to simulate indirect lighting.
Light Component
In Raftel Engine, lights are managed as components in the Entity Component System (ECS). The LightComponent
is the primary class that handles all lighting functionality.
#include "raftel/ecs.hpp"
#include "raftel/components.hpp"
// Create an entity
Raftel::EntityManager entityManager;
auto entity = entityManager.CreateEntity();
// Add a transform component
Raftel::TransformComponent transform(
glm::vec3(0.0f, 10.0f, 0.0f), // position
glm::vec3(0.0f, 0.0f, 0.0f), // rotation
glm::vec3(1.0f, 1.0f, 1.0f) // scale
);
entity.addTransformComp(std::move(transform));
// Add a directional light component
Raftel::LightComponent directionalLight(
Raftel::LightComponent::LightType::DIRECTIONAL, // light type
glm::vec3(1.0f, 1.0f, 1.0f), // color (white)
1.5f, // intensity
100.0f, // range
0.0f, // inner cone (not used for directional)
0.0f, // outer cone (not used for directional)
glm::ivec2(1024, 1024) // shadow map resolution
);
entity.addLightComp(std::move(directionalLight));
Light Properties
Each light type has specific properties that can be configured to achieve the desired lighting effect:
Property | Description | Applicable To |
---|---|---|
color | RGB color of the light | All light types |
intensity | Brightness multiplier for the light | All light types |
range | Maximum distance the light affects | Point, Spot |
innerCone | Inner angle of the spotlight cone in degrees | Spot |
outerCone | Outer angle of the spotlight cone in degrees | Spot |
near | Near plane distance for shadow mapping | All lights with shadows |
far | Far plane distance for shadow mapping | All lights with shadows |
Shadow Mapping
Raftel Engine supports shadow mapping for creating realistic shadows. When a light is created, you can enable shadow mapping by specifying the shadow map resolution.
Shadow Map Resolution
Higher shadow map resolutions provide more detailed shadows but require more GPU memory and processing power. For most applications, a resolution of 1024x1024 or 2048x2048 provides a good balance between quality and performance.
Shadow mapping works differently depending on the light type:
- Directional Light: Uses an orthographic projection and a single depth map for the entire visible scene.
- Spot Light: Uses a perspective projection and a single depth map from the light's point of view.
- Point Light: Uses a cubemap with six faces to capture depth information in all directions from the light source.
// In your rendering loop
void YourApplication::render() {
// Update the camera
camera.update();
// Render the scene with shadows
Raftel::RenderSystem::UpdateRenderSystem(
entityManager,
camera,
glm::ivec2(windowWidth, windowHeight),
true // Enable shadow rendering
);
}
Ambient Light
Unlike directional, point, and spot lights that are added as components to entities, ambient light is set globally through the Engine
singleton:
#include "raftel/engine.hpp"
// Enable ambient light
Raftel::Engine::Instance().has_ambient_light = true;
// Set ambient light color (RGB values between 0.0 and 1.0)
Raftel::Engine::Instance().ambient_light = glm::vec3(0.1f, 0.1f, 0.15f); // Slight blue tint
Ambient Light Intensity
Keep ambient light values relatively low (typically around 0.1 to 0.2) to maintain contrast and prevent your scene from looking flat. Ambient light should merely provide some illumination in areas not directly lit by other light sources.
Light Blending
Raftel Engine supports multiple lights affecting the same objects through an additive blending mechanism. This is handled automatically by the RenderSystem
:
- The first light is rendered normally, overwriting the framebuffer.
- Subsequent lights are blended additively, enhancing the illumination where multiple lights overlap.
- Depth writing is disabled after the first light to prevent occlusion issues.
Performance Considerations
Lighting and shadows can be computationally expensive. Here are some tips to optimize performance:
- Use the minimum number of lights necessary for your scene.
- For distant or less important lights, disable shadow mapping.
- Adjust the shadow map resolution based on the importance of the light.
- Use the appropriate light types - point lights with shadows are particularly expensive as they require six shadow map passes.
- Limit the range of point and spot lights to affect only necessary parts of the scene.
Shadow Rendering Toggle
If your application experiences performance issues, you can disable shadow rendering by setting the shadow
parameter to false
when calling UpdateRenderSystem
. This allows you to implement quality settings or dynamic LOD systems.
Complete Example
The following example demonstrates setting up a scene with multiple light types:
#include "raftel/ecs.hpp"
#include "raftel/components.hpp"
#include "raftel/engine.hpp"
#include "raftel/camera.hpp"
// Set up global ambient light
void setupAmbientLight() {
auto& engine = Raftel::Engine::Instance();
engine.has_ambient_light = true;
engine.ambient_light = glm::vec3(0.1f, 0.1f, 0.12f); // Slight blue tint
}
// Create a directional light (like the sun)
Raftel::Entity createDirectionalLight(Raftel::EntityManager& entityManager) {
auto entity = entityManager.CreateEntity();
// Position and orient the light
Raftel::TransformComponent transform(
glm::vec3(0.0f, 50.0f, 0.0f), // High position
glm::vec3(-45.0f, 30.0f, 0.0f), // Angled downward
glm::vec3(1.0f, 1.0f, 1.0f)
);
entity.addTransformComp(std::move(transform));
// Create the light component
Raftel::LightComponent light(
Raftel::LightComponent::LightType::DIRECTIONAL,
glm::vec3(1.0f, 0.95f, 0.8f), // Warm sunlight color
1.2f, // Intensity
0.0f, // Range (not used)
0.0f, // Inner cone (not used)
0.0f, // Outer cone (not used)
glm::ivec2(2048, 2048) // Shadow resolution
);
entity.addLightComp(std::move(light));
return entity;
}
// Create a point light (like a lamp)
Raftel::Entity createPointLight(Raftel::EntityManager& entityManager,
const glm::vec3& position,
const glm::vec3& color) {
auto entity = entityManager.CreateEntity();
// Position the light
Raftel::TransformComponent transform(
position,
glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(1.0f, 1.0f, 1.0f)
);
entity.addTransformComp(std::move(transform));
// Create the light component
Raftel::LightComponent light(
Raftel::LightComponent::LightType::POINT,
color,
2.0f, // Intensity
15.0f, // Range
0.0f, // Inner cone (not used)
0.0f, // Outer cone (not used)
glm::ivec2(1024, 1024) // Shadow resolution
);
entity.addLightComp(std::move(light));
return entity;
}
// Create a spotlight (like a flashlight)
Raftel::Entity createSpotlight(Raftel::EntityManager& entityManager,
const glm::vec3& position,
const glm::vec3& direction) {
auto entity = entityManager.CreateEntity();
// Position and orient the light
Raftel::TransformComponent transform(
position,
direction,
glm::vec3(1.0f, 1.0f, 1.0f)
);
entity.addTransformComp(std::move(transform));
// Create the light component
Raftel::LightComponent light(
Raftel::LightComponent::LightType::SPOT,
glm::vec3(1.0f, 1.0f, 0.9f), // Slightly yellow
2.5f, // Intensity
30.0f, // Range
15.0f, // Inner cone angle
30.0f, // Outer cone angle
glm::ivec2(1024, 1024) // Shadow resolution
);
entity.addLightComp(std::move(light));
return entity;
}
// In your application's initialization
void initializeScene() {
Raftel::EntityManager entityManager;
// Set up ambient light
setupAmbientLight();
// Create directional light (sun)
auto sunLight = createDirectionalLight(entityManager);
// Create some point lights
auto redLight = createPointLight(entityManager,
glm::vec3(-5.0f, 1.0f, 2.0f),
glm::vec3(1.0f, 0.2f, 0.2f)); // Red
auto blueLight = createPointLight(entityManager,
glm::vec3(5.0f, 1.0f, -2.0f),
glm::vec3(0.2f, 0.4f, 1.0f)); // Blue
// Create a spotlight
auto spotlight = createSpotlight(entityManager,
glm::vec3(0.0f, 5.0f, 0.0f),
glm::vec3(-45.0f, 0.0f, 0.0f)); // Pointing downward
// Create a camera
// In your render loop
while (isRunning) {
// Update entities, handle input, etc.
// Render the scene with shadows
Raftel::RenderSystem::UpdateRenderSystem(
entityManager,
...,
...,
true // Enable shadows
);
}
}
Next Steps
Now that you understand how to work with the lighting system in Raftel Engine, you might want to explore:
Lighting Tutorial
A step-by-step guide to creating and configuring lights in your scenes.
Materials
Learn how materials interact with lights in Raftel Engine.
Shaders
Understand how to create custom shaders that work with the lighting system.
Render System
Dive deeper into the rendering pipeline and how it handles lighting.