Clear coat: the source
Open the live demo · Read the guide · View on GitHub
Regions the guide quotes: paint (line 28), spheres (line 45), live (line 62).
1/// Red paint twice: bare on the left, under a clear coat on the right.
2///
3/// Quoted by `clear_coat.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 ClearCoatDemo extends ShowcaseDemo {
11 double coat = 1.0;
12 double coatRoughness = 0.15;
13 double paintRoughness = 0.6;
15 late final Material _bare;
16 late final Material _coated;
19 void configureView(DemoContext context) {
20 context.orbit
21 ..distance = 3.4
22 ..yaw = 0.0
23 ..pitch = 0.1;
24 }
27 Scene build(DemoContext context) {
28 _bare = Material(
29 name: 'bare paint',
30 lighting: LightingModel.pbrLayered,
31 baseColor: Vector4(0.8, 0.05, 0.05, 1.0),
32 roughness: paintRoughness,
33 );
34 _coated = Material(
35 name: 'coated paint',
36 lighting: LightingModel.pbrLayered,
37 baseColor: Vector4(0.8, 0.05, 0.05, 1.0),
38 roughness: paintRoughness,
39 extensions: MaterialExtensions(
40 clearcoat: coat,
41 clearcoatRoughness: coatRoughness,
42 ),
43 );
45 final DeviceMesh ball = DeviceMesh.upload(
46 context.device,
47 SphereShape(radius: 0.5, segments: 48, rings: 24).build(),
48 );
49 final Scene scene = Scene()
50 ..ambientIntensity = 0.15
51 ..add(MeshNode(ball, _bare, name: 'bare')..setPosition(-0.6, 0.0, 0.0))
52 ..add(MeshNode(ball, _coated, name: 'coated')..setPosition(0.6, 0.0, 0.0))
53 ..add(
54 LightNode(name: 'key', intensity: 3.0)
55 ..setLocalForward(Vector3(-0.35, -0.45, -1.0).normalized()),
56 );
57 return scene;
58 }
61 void update(DemoContext context, double dt) {
62 _bare.roughness = paintRoughness;
63 _coated
64 ..roughness = paintRoughness
65 ..extensions = MaterialExtensions(
66 clearcoat: coat,
67 clearcoatRoughness: coatRoughness,
68 );
69 }
72 List<DemoControl> controls(DemoContext context) => <DemoControl>[
73 SliderControl(
74 'Coat',
75 min: 0,
76 max: 1,
77 value: () => coat,
78 onChanged: (double v) => coat = v,
79 ),
80 SliderControl(
81 'Coat roughness',
82 min: 0,
83 max: 1,
84 value: () => coatRoughness,
85 onChanged: (double v) => coatRoughness = v,
86 ),
87 SliderControl(
88 'Paint roughness',
89 min: 0.05,
90 max: 1,
91 value: () => paintRoughness,
92 onChanged: (double v) => paintRoughness = v,
93 ),
94 ];
97 void verify(Scene scene, FrameResult frame) {
98 final MeshNode coated = scene.meshes.firstWhere(
99 (MeshNode m) => m.name == 'coated',
100 );
101 if (!identical(coated.material.lighting, LightingModel.pbrLayered)) {
102 throw StateError('the coated paint is not on the layered model');
103 }
104 if ((coated.material.extensions?.clearcoat ?? 0.0) <= 0.0) {
105 throw StateError('the coated paint has no clear coat');
106 }
107 if (frame.drawCalls < 2) {
108 throw StateError('the two spheres were not both drawn');
109 }
110 }
111}