Skip to content

[FEATURE] Photoreal lighting seams: environment source, punctual lights, shadow flags on imported models, LUT grade, graphics profile #1680

Description

@Noisemaker111

Problem: a photoreal or night scene cannot be lit. Verified on main: LightingConfig in packages/core/src/game/playableGame.ts (search interface LightingConfig) has ambient, directional, hemisphere only; packages/shell/src/render/EnvironmentLighting.tsx PMREMs a two-color gradient sphere, no RGBELoader; look is "cinematic" | "flat" in packages/core/src/render/lookPreset.ts:15 with cinematic as the silent default at :53; the grade defaults in packages/shell/src/postfx/gradeShader.ts:6-12 are a fixed film look; quality is three DPR numbers in packages/core/src/settings/settingsModel.ts:110-114; packages/shell/src/render/modelLoad.ts registers only MeshoptDecoder; packages/shell/src/materialOverride.ts:42 returns early for anything but MeshStandardMaterial; ModelMaterialMaps has color, normal, roughness, ao only.

Done: shadow flags on cloned models (#1695).

Tasks, one PR each, in order. Every task with a rendered change needs before/after bun run shoot the-robots --mode play shots in the PR.

  1. Loaders. In modelLoad.ts add configureModelLoaders({ dracoDecoderPath?, ktx2TranscoderPath? }) that sets DRACOLoader and KTX2Loader (from three/examples/jsm/loaders/) on sharedGltfLoader; default paths to the jsdelivr CDN copies for the pinned three version, and call KTX2Loader.detectSupport(renderer) from Shell3dPresentation.tsx once the renderer exists. Add .ktx2 to MATERIAL_MAP_FILES in packages/assets/src/materials.ts. Test: a unit test that configureModelLoaders is idempotent and stores the paths. CHANGELOG Added.

  2. Material maps and physical materials. Widen ModelMaterialMaps with metalness, emissive, height; in materialOverride.ts handle MeshPhysicalMaterial (it extends Standard, so replace the instanceof MeshStandardMaterial early return with an isMeshStandardMaterial check that also passes physical) and apply the new maps. Test in materialOverride.test.ts. Shots: a catalog model with a metalness map.

  3. Environment source. New packages/core/src/render/environment.ts: export type EnvironmentSource = { kind: "gradient"; sky: string; ground: string; sun?: string; intensity?: number } | { kind: "hdri"; url: string; rotation?: number; intensity?: number } | { kind: "cube"; urls: [string, string, string, string, string, string]; intensity?: number } with JSDoc. Add environment?: EnvironmentSource to the game presentation config next to lighting in playableGame.ts, and to the editor document environment block in packages/core/src/editor/types.ts (optional field, decode/encode in document.ts). EnvironmentLighting.tsx loads hdri with RGBELoader (.hdr) or EXRLoader (.exr) into a PMREM, cube with CubeTextureLoader; keep the gradient path as the default. Add an inspector field in packages/editor/src/LightingPanel.tsx. Shots: the same scene under a free CC0 HDRI from Poly Haven (record it in CREDITS.md).

  4. Punctual lights. Add to LightingConfig: point?: readonly { position: [number, number, number]; color?: string; intensity?: number; range?: number; decay?: number; castShadow?: boolean }[], spot?: readonly { position; target; color?; intensity?; range?; angle?; penumbra?; castShadow? }[], maxDynamicLights?: number (default 8; extra lights beyond the budget are skipped with one dev warning). Render them in packages/shell/src/render/SceneLighting.tsx. Add an editor kind light via registerSceneKind in packages/core/src/scene/builtinSceneKinds.ts with params type/color/intensity/range/castShadow, and a runtime consumer that turns light markers into LightingConfig.point/spot entries. Shots: a night scene with two point lights.

  5. Looks and LUT. In lookPreset.ts add "neutral" (no grade, ACES, no bloom, no AO), "photoreal" (ACES, exposure 1, SMAA, AO 0.8, no grain, no vignette), "toon" (no tonemapping, no AO, no bloom, saturation 1.0). Change the default when look is unset from cinematic to neutral and write a CHANGELOG Migrate bullet telling games to set look: "cinematic" to keep the old output. Add lut?: { url: string; size: 16 | 32 | 64; intensity?: number } to GradeConfig in packages/core/src/render/postProcessing.ts; implement in gradeShader.ts as a 3D texture sampled after the existing grade (accept a .cube file parsed on load, or a strip PNG). Shots: one scene under each look.

  6. Graphics profile. New packages/core/src/settings/graphicsProfile.ts: export interface GraphicsProfile { renderScale: number; shadowMapSize: 512 | 1024 | 2048 | 4096; cascades: 1 | 2 | 3 | 4; drawDistance: number; particleCap: number; postStages: { ao: boolean; bloom: boolean; dof: boolean; smaa: boolean } } plus DEFAULT_GRAPHICS_PROFILES: Record<"low" | "medium" | "high", GraphicsProfile> and resolveGraphicsProfile(quality, overrides?). Games override per tier through defineGame({ graphics: Partial<Record<tier, Partial<GraphicsProfile>>> }). Wire: Shell3dPresentation.tsx dpr from renderScale, SceneLighting.tsx map size and cascades, CullingProvider.tsx draw distance, PostProcessing.tsx stage toggles (degrade AO and DoF instead of dropping them at non-high). Tests for resolveGraphicsProfile. Shots: low vs high.

Acceptance: tasks 1 to 6 merged. Closes #1680 on task 6. Overlaps with #1558 (material registry, post graph) are fine; this issue only adds data and defaults.

Rules: wait for bun run agent:bootstrap --check; branch claude/<slug> off origin/main; claim comment first; one task per PR with Refs #1680; bun run gen after export changes (JSDoc on every new export); CHANGELOG bullet; check-types and test on core and shell plus check-stateful-ratchet, check-doc-symbols, check-orphan-ratchet; merge origin/main before pushing; shots via bun run games:clone, bun run shoot daemon start, bun run shoot <game> --mode play --size half --out shots/x.png, before shot from stashed origin/main shell code, bun run pr-shots --dir <branch> shots/*.png; squash auto-merge; fix CI on the same branch.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions