Overview
Scenes are containers for all the objects, lights, and environmental settings in your game. Each scene inherits from the Scene base class and implements custom initialization and update logic.
Creating a Scene
To create a scene, inherit from the Scene class and implement the required methods:
class MainScene : public Scene {
CoreObject ground;
CoreObject ball;
DirectionalLight light;
Camera camera;
Text fpsText;
Model backpack;
RenderTarget frameBuffer;
Terrain terrain;
AreaLight areaLight;
ParticleEmitter emitter;
WaterPot waterPot;
Model sponza;
bool doesUpdate = true ;
bool fall = false ;
public:
void update ( Window & window ) override {
if ( ! doesUpdate)
return ;
camera . update (window);
if ( window . isKeyPressed ( Key ::Escape)) {
window . releaseMouse ();
doesUpdate = false ;
} else if ( window . isKeyClicked ( Key ::Q)) {
fall = ! fall;
}
if (fall) {
camera . position . y -= 10. f * window . getDeltaTime ();
}
}
void onMouseMove ( Window & window , Movement2d movement ) override {
if ( ! doesUpdate) {
return ;
}
camera . updateLook (window, movement);
}
void initialize ( Window & window ) override {
// Initialize scene objects
}
};
Required Method : initialize() is a pure virtual function that must be implemented in your scene class.
Scene Lifecycle
Scenes have three main lifecycle methods:
initialize(Window &window)
Called once when the scene is first set. Use this to set up objects, lights, and initial state:
void initialize ( Window & window ) override {
// Configure environment
Environment env;
env . fog . intensity = 0.0 ;
env . volumetricLighting . enabled = false ;
env . lightBloom . radius = 0.008 f ;
env . lightBloom . maxSamples = 5 ;
this -> setEnvironment (env);
// Set resource path
Workspace :: get (). setRootPath ( std :: string (TEST_PATH) + "/resources/" );
// Create camera
camera = Camera ();
camera . setPosition ({ - 5.0 f , 1.0 f , 0.0 f });
camera . lookAt ({ 0.0 f , 1.0 f , 0.0 f });
camera . farClip = 1000. f ;
window . setCamera ( & camera);
// Add lighting
areaLight = AreaLight ();
areaLight . position = { 0.0 f , 2. f , 0. f };
areaLight . setColor ( Color ( 1.0 f , 0.9 f , 0.4 f ));
areaLight . intensity = 1.0 f ;
areaLight . range = 5.0 f ;
this -> addAreaLight ( & areaLight);
// Create objects
ground = createBox ({ 2.0 f , 0.1 f , 2.0 f });
ground . material . albedo = Color :: white ();
ground . setPosition ({ 0.0 f , - 0.1 f , 0.0 f });
window . addObject ( & ground);
// Set ambient lighting
this -> setAmbientIntensity ( 0.0 f );
// Configure rendering
window . usesDeferred = true ;
window . enableSSR ( true );
}
update(Window &window)
Called every frame. Use this for game logic and input handling:
void update ( Window & window ) override {
// Update camera
camera . update (window);
// Handle input
if ( window . isKeyPressed ( Key ::W)) {
camera . moveForward ( window . getDeltaTime () * 5.0 f );
}
}
onMouseMove(Window &window, Movement2d movement)
Called when the mouse moves:
void onMouseMove ( Window & window , Movement2d movement ) override {
camera . updateLook (window, movement);
}
Called when the mouse wheel scrolls:
void onMouseScroll ( Window & window , Movement2d offset ) override {
// Handle scroll events
}
Environment Configuration
Scenes can configure environmental effects through the Environment class:
Environment Settings
Environment env;
// Fog
env . fog . color = Color :: white ();
env . fog . intensity = 0.02 f ;
// Volumetric lighting
env . volumetricLighting . enabled = true ;
env . volumetricLighting . density = 0.3 f ;
env . volumetricLighting . weight = 0.01 f ;
env . volumetricLighting . decay = 0.95 f ;
env . volumetricLighting . exposure = 0.6 f ;
// Bloom
env . lightBloom . radius = 0.008 f ;
env . lightBloom . maxSamples = 5 ;
// Rim lighting
env . rimLight . intensity = 0.5 f ;
env . rimLight . color = Color :: white ();
// Color grading LUT
env . lookupTexture = Texture :: fromResource ( "lut.png" , TextureType ::LUT);
this -> setEnvironment (env);
Environment Components
Fog
Volumetric Lighting
Bloom
Rim Light
Fog fog;
fog . color = Color ( 0.8 f , 0.9 f , 1.0 f , 1.0 f ); // Sky blue tint
fog . intensity = 0.015 f ; // Density
VolumetricLighting volumetric;
volumetric . enabled = true ;
volumetric . density = 0.3 f ; // Medium density
volumetric . weight = 0.01 f ; // Sample strength
volumetric . decay = 0.95 f ; // Distance falloff
volumetric . exposure = 0.6 f ; // Final brightness
LightBloom bloom;
bloom . radius = 0.008 f ; // Blur kernel size
bloom . maxSamples = 5 ; // Quality (passes)
RimLight rim;
rim . intensity = 0.8 f ;
rim . color = Color ( 0.3 f , 0.5 f , 1.0 f , 1.0 f ); // Blue edge glow
Lighting
Scenes manage all lights in the environment:
Directional Light
DirectionalLight sun;
sun . direction = { 0.3 f , - 1.0 f , 0.2 f };
sun . setColor ( Color :: white ());
sun . intensity = 1.0 f ;
sun . castShadows = true ;
this -> addDirectionalLight ( & sun);
Single Directional Light : Atlas currently supports only one directional light per scene. Adding a new one replaces the previous.
Point Lights
Light pointLight;
pointLight . position = { 0.0 f , 2.0 f , 0.0 f };
pointLight . setColor ( Color ( 1.0 f , 0.8 f , 0.6 f , 1.0 f ));
pointLight . intensity = 2.0 f ;
pointLight . range = 10.0 f ;
pointLight . castShadows = true ;
this -> addLight ( & pointLight);
Spotlights
Spotlight spot;
spot . position = { 0.0 f , 5.0 f , 0.0 f };
spot . direction = { 0.0 f , - 1.0 f , 0.0 f };
spot . setColor ( Color :: white ());
spot . intensity = 3.0 f ;
spot . cutOff = 12.5 f ; // Inner cone angle
spot . outerCutOff = 17.5 f ; // Outer cone angle
spot . castShadows = true ;
this -> addSpotlight ( & spot);
Area Lights
AreaLight areaLight;
areaLight . position = { 0.0 f , 3.0 f , 0.0 f };
areaLight . setColor ( Color ( 1.0 f , 0.9 f , 0.7 f , 1.0 f ));
areaLight . intensity = 1.5 f ;
areaLight . range = 8.0 f ;
areaLight . rotate ({ 90.0 f , 0.0 f , 0.0 f });
// Optional: visualize area light
areaLight . createDebugObject ();
areaLight . addDebugObject (window);
this -> addAreaLight ( & areaLight);
Ambient Lighting
Manual Ambient
// Set ambient light intensity
this -> setAmbientIntensity ( 0.5 f ); // Divided by 4 internally
Automatic Ambient from Skybox
// Enable automatic ambient color sampling from skybox
this -> setAutomaticAmbient ( true );
// Check if automatic ambient is enabled
if ( this -> isAutomaticAmbientEnabled ()) {
Color ambientColor = this -> getAutomaticAmbientColor ();
float ambientIntensity = this -> getAutomaticAmbientIntensity ();
}
Automatic Ambient : When enabled, the engine samples the skybox’s average color and luminance to determine ambient lighting automatically.
Skybox
Custom Skybox
Cubemap createCubemap () {
Resource right = Workspace :: get (). createResource (
"skybox/px.png" , "RightSkybox" , ResourceType ::Image);
Resource left = Workspace :: get (). createResource (
"skybox/nx.png" , "LeftSkybox" , ResourceType ::Image);
Resource top = Workspace :: get (). createResource (
"skybox/py.png" , "TopSkybox" , ResourceType ::Image);
Resource bottom = Workspace :: get (). createResource (
"skybox/ny.png" , "BottomSkybox" , ResourceType ::Image);
Resource front = Workspace :: get (). createResource (
"skybox/pz.png" , "FrontSkybox" , ResourceType ::Image);
Resource back = Workspace :: get (). createResource (
"skybox/nz.png" , "BackSkybox" , ResourceType ::Image);
ResourceGroup group = Workspace :: get (). createResourceGroup (
"Skybox" , {right, left, top, bottom, front, back});
return Cubemap :: fromResourceGroup (group);
}
auto cubemap = createCubemap ();
auto skybox = std :: make_shared < Skybox >(cubemap);
this -> setSkybox (skybox);
Atmosphere Skybox
// Use procedural atmosphere as skybox
this -> setUseAtmosphereSkybox ( true );
// Configure atmosphere
this -> atmosphere . sunDirection = { 0.3 f , - 0.5 f , 0.2 f };
// Check if using atmosphere skybox
if ( this -> isUsingAtmosphereSkybox ()) {
auto atmSkybox = this -> getAtmosphereSkybox ();
}
Scene Updates
The scene’s updateScene() method is called automatically by the engine:
void updateScene ( float dt ) {
// Internal update logic
// Called automatically by the engine
}
Attaching Scene to Window
MainScene scene;
window . setScene ( & scene);
Scene Lifetime : The scene must remain valid for the entire duration of the window’s lifetime. Declare scenes as class members or stack variables in main().
Example: Complete Scene
class GameScene : public Scene {
Camera camera;
DirectionalLight sun;
CoreObject floor;
Model player;
public:
void initialize ( Window & window ) override {
// Environment
Environment env;
env . fog . intensity = 0.01 f ;
env . volumetricLighting . enabled = true ;
this -> setEnvironment (env);
// Camera
camera = Camera ();
camera . setPosition ({ 0.0 f , 2.0 f , 5.0 f });
camera . lookAt ({ 0.0 f , 0.0 f , 0.0 f });
window . setCamera ( & camera);
// Lighting
sun . direction = { 0.3 f , - 1.0 f , 0.2 f };
sun . setColor ( Color :: white ());
sun . intensity = 1.0 f ;
this -> addDirectionalLight ( & sun);
this -> setAmbientIntensity ( 0.3 f );
// Objects
floor = createBox ({ 20.0 f , 0.1 f , 20.0 f });
floor . setPosition ({ 0.0 f , 0.0 f , 0.0 f });
window . addObject ( & floor);
// Load model
Resource playerRes = Workspace :: get (). createResource (
"models/player.obj" , "Player" , ResourceType ::Model);
player . fromResource (playerRes);
player . setPosition ({ 0.0 f , 1.0 f , 0.0 f });
window . addObject ( & player);
}
void update ( Window & window ) override {
camera . update (window);
// Player movement
if ( window . isKeyPressed ( Key ::W)) {
player . move ({ 0.0 f , 0.0 f , - 5.0 f * window . getDeltaTime ()});
}
if ( window . isKeyPressed ( Key ::S)) {
player . move ({ 0.0 f , 0.0 f , 5.0 f * window . getDeltaTime ()});
}
}
void onMouseMove ( Window & window , Movement2d movement ) override {
camera . updateLook (window, movement);
}
};
Next Steps
Objects & Components Learn how to create and manipulate objects
Lighting Explore lighting options in detail