flutter3d
Showcase Changelog 38 packages API reference

The six lighting models

since 0.1.0 Shading and materials

A lighting model decides how a surface answers light. The engine ships six, and a material picks one by name. This page puts the same orange colour under each of them so you can see what the choice changes.

Read the spheres in reading order: Unlit, Lambert and Blinn-Phong on the top row, then PBR, Toon and Normals below.

Step 1: Take one material per model #

LightingModel.builtIn lists the six in the order a picker would show them. The loop makes one Material for each, with the same colour and roughness, so the only thing that differs between the spheres is the model.

_materials = <Material>[
  for (final LightingModel model in LightingModel.builtIn)
    Material(
      name: model.label,
      lighting: model,
      baseColor: Vector4(0.85, 0.45, 0.3, 1.0),
      roughness: roughness,
    ),
];

Each model is a fragment shader compiled ahead of time. Choosing a model is choosing a shader, and the renderer keeps one pipeline for each.

Step 2: Lay them out in a grid #

One DeviceMesh is uploaded once and shared by six MeshNodes. Each node pairs it with its own material and moves to a cell of a three by two grid.

final DeviceMesh sphere = DeviceMesh.upload(
  context.device,
  const SphereShape(segments: 40, rings: 20).build(),
);
final Scene scene = Scene();
for (var i = 0; i < _materials.length; i++) {
  scene.add(
    MeshNode(sphere, _materials[i], name: _materials[i].name)
      ..setPosition((i % 3 - 1) * 1.35, i < 3 ? 0.7 : -0.7, 0.0),
  );
}

Step 3: Add a light #

Without a light a lit model is black. A single directional LightNode is enough here. Unlit ignores it and draws the flat colour, Normals ignores it and paints the direction each point faces, and the other four use it.

_sun = LightNode(name: 'sun', intensity: sunIntensity)
  ..setLocalForward(Vector3(-0.4, -0.6, -0.7));
scene.add(_sun);

Drag the view around. Unlit and Normals look the same from every side, while the lit spheres change as you move.

Step 4: Move the sliders #

Roughness is read by Blinn-Phong, PBR and Toon, and each reads it differently. Blinn-Phong turns it into the sharpness of the highlight, PBR spreads the highlight over more of the sphere, and Toon uses it to choose how many bands of shade to draw. Lambert has no highlight and does not read it, so its sphere stays put.

for (final Material material in _materials) {
  material.roughness = roughness;
}
_sun.intensity = sunIntensity;

Note. Setting a field is enough. The next frame draws with the new value and nothing is rebuilt.