Skip to content

Getting Started

This guide walks through setting up a basic scene with objects, a camera, and a light.

1. Register Resources

Before loading GPU resources, register descriptors with ResourceManager. Descriptors are CPU-side metadata; the actual GPU upload happens when load_from_descriptors is called.

cpp
auto res = ResourceManager::get();

// Shaders
res->register_shader(Shader::create(
    "my_shader",
    "shaders/fragment/pbr.axsl"_engine,
    "shaders/vertex/pbr.axsl"_engine
));

// Textures
res->register_texture(Texture2DDescriptor::create("albedo", "textures/albedo.png"_engine));

// Models
res->register_model(ModelDescriptor::create("cube", "models/cube.obj"_engine));

// Upload everything to the GPU for the OpenGL backend
res->load_from_descriptors<ShaderDescriptor, Texture2DDescriptor, ModelDescriptor>(
    RendererBackend::OpenGL
);

2. Create a Scene

Subclass Scene and override start() and update():

cpp
class MyScene : public Scene {
public:
    MyScene() : Scene("MyScene") {}

    void start() override {
        // Add a camera
        auto* cam = add_entity<Camera>("MainCamera");
        cam->add_component<CameraComponent>(/* fov */ 60.0f);

        // Add an object
        auto* obj = add_entity<Object>("Cube", glm::vec3(0, 0, -5));
        obj->add_component<TransformComponent>();
        obj->add_component<MeshComponent>()->attach_model("cube");
        obj->add_component<ResourceComponent>()->attach_shader("my_shader");
        obj->add_component<MaterialComponent>();
    }

    void update() override {}
};

3. Register the Scene

cpp
auto scene_mgr = SceneManager::get();
scene_mgr->add_scene<MyScene>();

4. Configure the RenderSystem

The RenderSystem drives the render graph each frame. Construct it with a RenderSystemConfig:

cpp
RenderSystemConfig config;
config.backend = RendererBackend::OpenGL;
config.window_id = window.id();
config.msaa = { .samples = 4, .is_enabled = true };

auto render_system = RenderSystem(config);
render_system.start();

5. Frame Loop

Each frame, call the system update methods:

cpp
while (!window.should_close()) {
    double dt = timer.delta();

    render_system.pre_update(dt);
    render_system.update(dt);
    render_system.fixed_update(fixed_dt);
}

Adding a Skybox

cpp
// In Scene::start()
auto* skybox = add_entity<Skybox>("Sky");
skybox->cubemap_id = "sky_cubemap";
skybox->shader_id  = "skybox_shader";
skybox->add_component<MeshComponent>();
skybox->add_component<ResourceComponent>();

Adding Post-Processing

Post-processing is handled automatically by PostProcessPass, which creates an HDR tone-mapping quad. Custom effects can be added by subclassing RenderPass and declaring them in the render graph.

See Render Graph for details on custom passes.