Materials
A material is the shading half of a Mesh. It decides how a surface responds to light and what color it ends up. Flutter Scene ships two built-in materials, PhysicallyBasedMaterial and UnlitMaterial, and lets you write your own with ShaderMaterial.
Physically based shading
Section titled “Physically based shading”PhysicallyBasedMaterial (PBR) is the default choice for realistic surfaces. It models a surface with a base color plus two scalars, metallic and roughness, and lights it with the scene’s environment.
Drag the sliders to see how those two values reshape the same sphere. Metallic moves the surface from a plastic-like dielectric to a mirror-like metal, and roughness blurs its reflections from sharp to matte.
The material is just a few fields.
final material = PhysicallyBasedMaterial() ..baseColorFactor = vm.Vector4(0.85, 0.30, 0.25, 1.0) // linear RGBA ..metallicFactor = 1.0 // 0 = dielectric, 1 = metal ..roughnessFactor = 0.25; // 0 = mirror, 1 = fully diffuse
final mesh = Mesh(SphereGeometry(radius: 1.0), material);scene.add(Node(mesh: mesh));PBR surfaces need light to look like anything. A new Scene already comes with a procedural studio environment, so a material shows up the moment you add it. The sphere above goes a step further and loads an imported equirectangular environment map, which both lights it and appears in its reflections (most visible when it is metallic and smooth). See Lighting and environment for loading environments, drawing one as a skybox, and adding a directional light.
Textures
Section titled “Textures”Every factor has a matching texture that modulates it across the surface. Assign a gpu.Texture (see Assets and loading for getting one) to any of these.
final material = PhysicallyBasedMaterial() ..baseColorTexture = albedo // multiplied by baseColorFactor ..metallicRoughnessTexture = metalRough // blue = metallic, green = roughness ..normalTexture = normal // tangent-space normals ..occlusionTexture = ao ..emissiveTexture = emissive;The base color texture is multiplied by baseColorFactor, so leave the factor white to use the texture unchanged, or tint it. normalScale, occlusionStrength, and emissiveFactor scale their respective inputs.
Emission
Section titled “Emission”emissiveFactor adds light-independent color on top of the shaded result, for surfaces that should appear to glow (screens, lava, neon). It is linear HDR, so values above 1.0 read as bright and feed into bloom when it is enabled.
material.emissiveFactor = vm.Vector4(2.0, 0.4, 0.1, 1.0);Transparency
Section titled “Transparency”alphaMode controls how the material’s alpha is used.
AlphaMode.opaque(the default) ignores alpha.AlphaMode.blendroutes the mesh through the depth-sorted translucent pass and alpha-blends it.AlphaMode.maskdiscards fragments belowalphaCutoff, for cutout surfaces like foliage.
Unlit shading
Section titled “Unlit shading”UnlitMaterial ignores scene lighting and draws a flat color or texture. Use it for UI overlays, debug visualization, billboards, or a deliberately stylized look. It is also the cheapest material to draw.
final material = UnlitMaterial() ..baseColorFactor = vm.Vector4(0.1, 0.6, 0.9, 1.0);
// Or texture it:final textured = UnlitMaterial(colorTexture: myTexture);Like PBR, it supports alphaMode for transparency and vertexColorWeight for mixing in per-vertex colors.
Custom materials
Section titled “Custom materials”When the built-ins are not enough, you write your own shader. The supported way is the .fmat format, where you declare typed parameters and a small Surface() function (plus an optional Vertex() function to displace and animate geometry) and a build hook compiles it. Your shader follows the same output contract as the built-ins, linear HDR premultiplied by alpha, so exposure and tone mapping work the same. See Custom materials for the full workflow, unlit and lit shading, vertex customization, and live demos.
Key API
Section titled “Key API”Material, PhysicallyBasedMaterial, UnlitMaterial, and PreprocessedMaterial (see Custom materials).