Skip to content

Lights constructed before any Scene get worldLightDir=(0,0,0) because initializeTrigTables() runs inside Scene::Scene() #7

@jetpax

Description

@jetpax

Summary

DirectionalLight's constructor calls calculateLightDirection(), which reads sin_table[]. That table is only populated by initializeTrigTables(), which lives inside Scene::Scene(). Any DirectionalLight constructed before a Scene exists silently caches worldLightDir = (0, 0, 0) from the still-zeroed table. The cached value never refreshes on its own — subsequent updateViewSpaceDirection() calls also produce zero vectors, all N·L clamp to zero, and the light has no effect.

Upstream Sample.cpp doesn't trip this because it constructs the Scene first and lights second. Code that organizes lighting state into a host struct (lights as value members alongside a Scene*) hits it.

Repro

struct DemoScene {
    DirectionalLight sun{Vector3{300, 35, 0}, Color{255, 245, 220}, 240};
    Scene *scene = nullptr;
};

int main() {
    DemoScene demo;                       // sun's ctor runs against sin_table[]==0
    demo.scene = new Scene(fb, ...);      // initializeTrigTables() runs here — too late
    demo.scene->setDirectionalLight(&demo.sun);
    // worldLightDir is cached as (0,0,0); no light reaches any object.
}

External workaround:

demo.sun.updateDirection(demo.sun.direction);   // force recompute after Scene exists

Suggested fixes

A few options, ordered cleanest → easiest:

  1. Move initializeTrigTables() out of Scene::Scene() and into a static / namespace-level constructor, or expose a Renderer::init() function the host must call before any other Jet API. Cleanest; mildly breaking for users who relied on Scene's ctor running it.

  2. Have DirectionalLight defer the world-direction calc to first read rather than caching in its constructor (lazy getWorldLightDir()).

  3. At minimum: document the ordering requirement prominently on DirectionalLight's class comment. "Construct AFTER a Scene exists" is currently invisible.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions