Skip to main content

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:
test/main.cpp:134-250
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:
test/main.cpp:199-249
void initialize(Window &window) override {
    // Configure environment
    Environment env;
    env.fog.intensity = 0.0;
    env.volumetricLighting.enabled = false;
    env.lightBloom.radius = 0.008f;
    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.0f, 1.0f, 0.0f});
    camera.lookAt({0.0f, 1.0f, 0.0f});
    camera.farClip = 1000.f;
    window.setCamera(&camera);

    // Add lighting
    areaLight = AreaLight();
    areaLight.position = {0.0f, 2.f, 0.f};
    areaLight.setColor(Color(1.0f, 0.9f, 0.4f));
    areaLight.intensity = 1.0f;
    areaLight.range = 5.0f;
    this->addAreaLight(&areaLight);

    // Create objects
    ground = createBox({2.0f, 0.1f, 2.0f});
    ground.material.albedo = Color::white();
    ground.setPosition({0.0f, -0.1f, 0.0f});
    window.addObject(&ground);

    // Set ambient lighting
    this->setAmbientIntensity(0.0f);

    // Configure rendering
    window.usesDeferred = true;
    window.enableSSR(true);
}

update(Window &window)

Called every frame. Use this for game logic and input handling:
scene.h:152
void update(Window &window) override {
    // Update camera
    camera.update(window);
    
    // Handle input
    if (window.isKeyPressed(Key::W)) {
        camera.moveForward(window.getDeltaTime() * 5.0f);
    }
}

onMouseMove(Window &window, Movement2d movement)

Called when the mouse moves:
scene.h:166-167
void onMouseMove(Window &window, Movement2d movement) override {
    camera.updateLook(window, movement);
}

onMouseScroll(Window &window, Movement2d offset)

Called when the mouse wheel scrolls:
scene.h:174-175
void onMouseScroll(Window &window, Movement2d offset) override {
    // Handle scroll events
}

Environment Configuration

Scenes can configure environmental effects through the Environment class:

Environment Settings

scene.h:96-118
Environment env;

// Fog
env.fog.color = Color::white();
env.fog.intensity = 0.02f;

// Volumetric lighting
env.volumetricLighting.enabled = true;
env.volumetricLighting.density = 0.3f;
env.volumetricLighting.weight = 0.01f;
env.volumetricLighting.decay = 0.95f;
env.volumetricLighting.exposure = 0.6f;

// Bloom
env.lightBloom.radius = 0.008f;
env.lightBloom.maxSamples = 5;

// Rim lighting
env.rimLight.intensity = 0.5f;
env.rimLight.color = Color::white();

// Color grading LUT
env.lookupTexture = Texture::fromResource("lut.png", TextureType::LUT);

this->setEnvironment(env);

Environment Components

scene.h:29-39
Fog fog;
fog.color = Color(0.8f, 0.9f, 1.0f, 1.0f);  // Sky blue tint
fog.intensity = 0.015f;  // Density

Lighting

Scenes manage all lights in the environment:

Directional Light

scene.h:236-239
DirectionalLight sun;
sun.direction = {0.3f, -1.0f, 0.2f};
sun.setColor(Color::white());
sun.intensity = 1.0f;
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

scene.h:247-248
Light pointLight;
pointLight.position = {0.0f, 2.0f, 0.0f};
pointLight.setColor(Color(1.0f, 0.8f, 0.6f, 1.0f));
pointLight.intensity = 2.0f;
pointLight.range = 10.0f;
pointLight.castShadows = true;

this->addLight(&pointLight);

Spotlights

scene.h:256
Spotlight spot;
spot.position = {0.0f, 5.0f, 0.0f};
spot.direction = {0.0f, -1.0f, 0.0f};
spot.setColor(Color::white());
spot.intensity = 3.0f;
spot.cutOff = 12.5f;      // Inner cone angle
spot.outerCutOff = 17.5f; // Outer cone angle
spot.castShadows = true;

this->addSpotlight(&spot);

Area Lights

scene.h:261
AreaLight areaLight;
areaLight.position = {0.0f, 3.0f, 0.0f};
areaLight.setColor(Color(1.0f, 0.9f, 0.7f, 1.0f));
areaLight.intensity = 1.5f;
areaLight.range = 8.0f;
areaLight.rotate({90.0f, 0.0f, 0.0f});

// Optional: visualize area light
areaLight.createDebugObject();
areaLight.addDebugObject(window);

this->addAreaLight(&areaLight);

Ambient Lighting

Manual Ambient

scene.h:183-188
// Set ambient light intensity
this->setAmbientIntensity(0.5f);  // Divided by 4 internally

Automatic Ambient from Skybox

scene.h:194-199
// 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

test/main.cpp:178-194
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

scene.h:288-294
// Use procedural atmosphere as skybox
this->setUseAtmosphereSkybox(true);

// Configure atmosphere
this->atmosphere.sunDirection = {0.3f, -0.5f, 0.2f};

// 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:
scene.h:330
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.01f;
        env.volumetricLighting.enabled = true;
        this->setEnvironment(env);
        
        // Camera
        camera = Camera();
        camera.setPosition({0.0f, 2.0f, 5.0f});
        camera.lookAt({0.0f, 0.0f, 0.0f});
        window.setCamera(&camera);
        
        // Lighting
        sun.direction = {0.3f, -1.0f, 0.2f};
        sun.setColor(Color::white());
        sun.intensity = 1.0f;
        this->addDirectionalLight(&sun);
        this->setAmbientIntensity(0.3f);
        
        // Objects
        floor = createBox({20.0f, 0.1f, 20.0f});
        floor.setPosition({0.0f, 0.0f, 0.0f});
        window.addObject(&floor);
        
        // Load model
        Resource playerRes = Workspace::get().createResource(
            "models/player.obj", "Player", ResourceType::Model);
        player.fromResource(playerRes);
        player.setPosition({0.0f, 1.0f, 0.0f});
        window.addObject(&player);
    }
    
    void update(Window &window) override {
        camera.update(window);
        
        // Player movement
        if (window.isKeyPressed(Key::W)) {
            player.move({0.0f, 0.0f, -5.0f * window.getDeltaTime()});
        }
        if (window.isKeyPressed(Key::S)) {
            player.move({0.0f, 0.0f, 5.0f * 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

Build docs developers (and LLMs) love