Sheen: the source
Open the live demo · Read the guide · View on GitHub
Regions the guide quotes: colours (line 26), cloth (line 35), live (line 68).
1/// Red cloth twice: bare on the left, with a sheen at its rim on the right.
2///
3/// Quoted by `sheen.md` and shown whole in the Source tab.
4library;
6import 'package:flutter3d/flutter3d.dart';
7import 'package:flutter3d_showcase/src/demo/demo.dart';
8import 'package:vector_math/vector_math.dart';
10final class SheenDemo extends ShowcaseDemo {
11 int colour = 0;
12 double sheenRoughness = 0.5;
14 static const List<String> _colourNames = <String>['Blue', 'White', 'Gold'];
16 late final Material _cloth;
19 void configureView(DemoContext context) {
20 context.orbit
21 ..distance = 3.4
22 ..yaw = 0.0
23 ..pitch = 0.1;
24 }
26 /// Linear colours: the sheen is not painted, so it is not sRGB.
27 Vector3 _sheenColour() => switch (colour) {
28 0 => Vector3(0.2, 0.4, 1.0),
29 1 => Vector3(1.0, 1.0, 1.0),
30 _ => Vector3(1.0, 0.75, 0.3),
31 };
34 Scene build(DemoContext context) {
35 final Material bare = Material(
36 name: 'bare cloth',
37 lighting: LightingModel.pbrLayered,
38 baseColor: Vector4(0.8, 0.05, 0.05, 1.0),
39 roughness: 0.6,
40 );
41 _cloth = Material(
42 name: 'cloth with sheen',
43 lighting: LightingModel.pbrLayered,
44 baseColor: Vector4(0.8, 0.05, 0.05, 1.0),
45 roughness: 0.6,
46 extensions: MaterialExtensions(
47 sheenColor: _sheenColour(),
48 sheenRoughness: sheenRoughness,
49 ),
50 );
52 final DeviceMesh ball = DeviceMesh.upload(
53 context.device,
54 SphereShape(radius: 0.5, segments: 48, rings: 24).build(),
55 );
56 return Scene()
57 ..ambientIntensity = 0.15
58 ..add(MeshNode(ball, bare, name: 'bare')..setPosition(-0.6, 0.0, 0.0))
59 ..add(MeshNode(ball, _cloth, name: 'sheen')..setPosition(0.6, 0.0, 0.0))
60 ..add(
61 LightNode(name: 'key', intensity: 3.0)
62 ..setLocalForward(Vector3(-0.35, -0.45, -1.0).normalized()),
63 );
64 }
67 void update(DemoContext context, double dt) {
68 _cloth.extensions = MaterialExtensions(
69 sheenColor: _sheenColour(),
70 sheenRoughness: sheenRoughness,
71 );
72 }
75 List<DemoControl> controls(DemoContext context) => <DemoControl>[
76 ChoiceControl(
77 'Sheen colour',
78 options: _colourNames,
79 index: () => colour,
80 onChanged: (int i) => colour = i,
81 ),
82 SliderControl(
83 'Sheen roughness',
84 // The shader floors sheen roughness at 0.07; below it nothing changes.
85 min: 0.07,
86 max: 1,
87 value: () => sheenRoughness,
88 onChanged: (double v) => sheenRoughness = v,
89 ),
90 ];
93 void verify(Scene scene, FrameResult frame) {
94 final MeshNode cloth = scene.meshes.firstWhere(
95 (MeshNode m) => m.name == 'sheen',
96 );
97 if (cloth.material.extensions?.shades != true) {
98 throw StateError('the cloth has no layer that changes its shading');
99 }
100 if (frame.drawCalls < 2) {
101 throw StateError('the two spheres were not both drawn');
102 }
103 }
104}