flutter3d
Showcase Changelog 38 packages API reference

Manual exposure

since 0.1.0 or earlier Shading and materials

RenderSettings.exposure is the linear multiplier the composite pass applies to a frame before the tone curve rolls it off. It is what a photographer's exposure dial would be if the scene were a camera: the light in the scene does not change, only how much of it reaches the picture.

This is the manual knob. RenderSettings.autoExposure is a separate meter that reads the frame's own brightness and moves this same number for you; this page turns it by hand instead, so the effect is direct and repeatable.

Step 1: A scene with something bright in it #

An emissive box under a modest sun gives the exposure slider something to work with: raise it and the box's own light grows past what an ordinary material would show.

final Material lantern = Material(
  name: 'lantern',
  baseColor: Vector4(0.9, 0.85, 0.6, 1.0),
  emissive: Vector3(2.0, 1.7, 0.9),
);
final MeshNode box = MeshNode(
  DeviceMesh.upload(
    context.device,
    CuboidShape(size: Vector3(1.4, 1.4, 1.4)).build(),
  ),
  lantern,
  name: 'lantern',
);
return Scene()
  ..add(box)
  ..add(
    LightNode(name: 'sun', intensity: 1.5)
      ..setLocalForward(Vector3(-0.3, -0.6, -0.7)),
  );

Step 2: The knob #

Exposure is read fresh every frame, straight out of the settings.

exposure: exposure,

Step 3: What the frame reports back #

FrameResult.exposure says what the composite actually used. With auto exposure off, that number is exactly the one this page set, and the page's own test reads it back to make sure the two never drift apart.

if ((frame.exposure - exposure).abs() > 1e-6) {
  throw StateError(
    'the frame was composited at ${frame.exposure}, not the '
    '$exposure this page asked for',
  );
}
if (frame.drawCalls < 1) {
  throw StateError('the lantern was not drawn');
}