Files
wsg/docs/user/lights/emissive-exposure.md
T
Jérôme Bousquié d4c2d93fc5 eng doc
2026-09-25 20:06:10 +02:00

3.5 KiB
Raw Blame History

Emissive + Exposure

Principle

Two complementary features (Step 22):

Feature Effect Cost
Exposure (6.1) Multiplies luminance before the tone-mapping curve Zero when HDR is inactive
Emissive (6.2) Adds an emitted color (independent of the lights) Zero when emissive = [0,0,0,0]

Exposure

API

// Initialization (optional, default = 1.0)
let app = AppBuilder::new()
    .with_hdr(ToneMapper::Aces)
    .with_exposure(1.5)  // start brighter
    .build().await?;

// Runtime (in update())
app.set_exposure(app.exposure() * 1.1);  // +1 "stop"
app.set_exposure(1.0);                   // reset

Behavior

  • Exposure is a multiplier applied to the HDR texture before the tone-mapping curve.
  • exposure = 2.0 → the image is 2× brighter (like opening a camera's aperture).
  • exposure = 0.5 → the image is 2× darker.
  • Clamped to [0.01, 10.0] to avoid degenerate values.
  • Only has an effect when HDR is active (with_hdr(...)). In LDR the value is ignored.

Keyboard (demo)

Key Effect
+ ×1.1 (brighter)
- ÷1.1 (darker)
0 Reset to 1.0

Emissive

API

use wsg_lib::resources::Material;

// Create a material with emissivity
let mut mat = /* ... */;
mat.emissive = [1.0, 0.3, 0.1, 1.5];  // orange, intensity 1.5 (> 1.0 = HDR glow)

Format

emissive = [r, g, b, intensity]:

  • rgb: the emission color (same space as the vertex base color)
  • a (intensity): the multiplier. 1.0 = normal color, > 1.0 = highlight (only visible in HDR)

Shader formula

final_color = lit + base_color * emissive.rgb * emissive.a
  • The emission is additive: visible even in total darkness (no light needed).
  • It is independent of shadows: an emissive object casts no shadow and is not shadowed.
  • emissive = [0,0,0,0] (default) → no change (non-regression guaranteed).

Use cases

Use Value
LED / indicator [0, 1, 0, 1.0] (green, normal intensity)
Flame / sun [1, 0.8, 0.2, 3.0] (orange, HDR glow)
Neon [0, 0.5, 1, 2.5] (cyan, glow)
Inactive [0, 0, 0, 0] (default)

Keyboard (demo)

Key Effect
E Toggle orange glow on the sphere/cylinder

Interactions

Combination Result
Emissive + HDR + ACES Soft glow, highlights roll off (the nicest)
Emissive + LDR Clamped to 1.0 (no glow, but the color is visible in the dark)
Emissive + shadows The emissive object is NOT shadowed (emission bypasses the shadow term)
Exposure + Emissive Exposure also amplifies the emission (consistent: everything is in the HDR texture)

Non-regression

  • Emissive: [0,0,0,0] by default → the shader adds base * 0 * 0 = 0 → no change.
  • Exposure: 1.0 by default → pow(color, 1/1) = color → no change.
  • Both are opt-in: without with_hdr(...) and emissive != 0, the pipeline is identical to the previous state.

Limitations (MVP)

  • Emissive is per material, not per vertex (no emission gradient within a mesh).
  • Emissive is static at material creation (changing mat.emissive requires re-registering the material via add_material).
  • No bloom (Step 23): the HDR glow is visible but not "blurred" / spread.