ShaderMaterial class Materials

A Material backed by a caller-supplied fragment shader.

ShaderMaterial is the foundation for writing custom materials in flutter_scene. Use it when UnlitMaterial and PhysicallyBasedMaterial don't cover what you need: stylized shading, custom alpha modes, screen-space effects, vertex-painted looks, and so on.

Authoring a custom material

  1. Write a fragment shader. It should consume the engine's standard vertex outputs and declare its own uniform blocks / samplers for any parameters. See MATERIALS.md for the full contract.
  2. Compile the shader through the flutter_gpu_shaders build hook with ShaderBundleAssetMode.dataAssetsRequired. The generated .shaderbundle is a managed DataAsset, not a source file.
  3. Load the bundle at runtime with await gpu.loadShaderLibraryAsync('packages/<package>/flutter_gpu_shaders/shaderbundles/<name>.shaderbundle') and pull out the fragment shader entry.
  4. Construct a ShaderMaterial pointing at the shader, populate its uniform blocks and textures by name, and attach it to a MeshPrimitive.

Engine-bound resources available to your fragment shader

These vertex outputs are written by the engine's standard vertex shader and are always available as in declarations in your fragment shader (the names are part of the engine contract):

in vec3 v_position;        // world space
in vec3 v_normal;          // world space (not necessarily unit)
in vec3 v_viewvector;      // camera_position - vertex_position, world space
in vec2 v_texture_coords;
in vec2 v_texture_coords_1;
in vec4 v_color;           // per-vertex color, white when absent

Setting useEnvironment to true makes the engine bind the active environment's IBL textures by their standard names when your fragment shader declares them: prefiltered_radiance (the PMREM-style roughness-band atlas; sample it with SamplePrefilteredRadiance from texture.glsl) and brdf_lut (both as sampler2D). The diffuse irradiance SH coefficients are not bound generically; declare them in your own uniform block if you need them. Useful when a custom shader still wants the engine's image-based lighting.

Uniform block packing

Flutter GPU resolves uniform blocks by name (via gpu.Shader.getUniformSlot) but the block's contents are a flat byte buffer that your code packs and the GPU interprets according to the shader's std140 layout. Common rules:

  • float, int, bool occupy 4 bytes.
  • vec2 occupies 8 bytes aligned to 8.
  • vec3, vec4 occupy 16 bytes aligned to 16.
  • mat4 occupies 64 bytes; mat3 occupies 48 bytes laid out as three vec4 columns (12 bytes of padding).
  • Array elements stride to the next 16 bytes.

Put a Float32List together that matches the block's declared member order (including padding) and pass it via setUniformBlock.

TODO(fmat-codegen): generate this packing from the shader's reflection at build time so callers don't write it by hand, the way PreprocessedMaterial packs a .fmat.

Inheritance

Constructors

ShaderMaterial({Shader? fragmentShader, Shader? radianceCubeFragmentShader, Shader? vertexShader, Shader? skinnedVertexShader, Shader? depthVertexShader, bool useEnvironment = false, CullMode cullingMode = gpu.CullMode.backFace, WindingOrder windingOrder = gpu.WindingOrder.counterClockwise, bool isOpaqueOverride = true})
Creates a ShaderMaterial wrapping fragmentShader.

Properties

cullingMode ↔ CullMode
Backface culling mode applied before drawing. Defaults to gpu.CullMode.backFace to match the standard materials.
getter/setter pair
depthBias double
World-space offset toward the camera used for coplanar surface details. Positive values keep an overlay in front of its supporting surface without modifying its node transform. Zero and negative values leave the draw position unchanged. A fixed world offset provides fewer depth-buffer units as camera distance grows, so distant coplanar surfaces may need a larger value.
getter/setter pairinherited
doubleSided bool
Whether to render both faces of triangles drawn with this material (glTF's material.doubleSided). When true, bind disables back-face culling so the geometry is visible from both sides; otherwise back faces are culled. Defaults to false. The runtime importer sets it from the glTF material.
getter/setter pairinherited
fragmentShader Shader
The fragment shader used when rendering geometry with this material.
no setterinherited
hashCode int
The hash code for this object.
no setterinherited
isOpaqueOverride bool
Whether this material participates in the opaque pass.
getter/setter pair
name String
The name of this material, used for identification.
getter/setter pairinherited
runtimeType Type
A representation of the runtime type of the object.
no setterinherited
sceneInputs Set<RenderInput>
Per-frame engine inputs this material samples, produced only when a visible material asks for them: RenderInput.depth binds the linear scene depth of the opaque geometry (forcing the depth prepass), and RenderInput.opaqueSceneColor binds the accumulated scene color behind the current draw, and RenderInput.filteredSceneColor adds its roughness-filtered atlas. Together they enable refraction, depth-fade absorption, shoreline foam, and soft-particle style effects on translucent surfaces. The base material requests nothing; a .fmat material declares these with engine_inputs:.
no setterinherited
textureNames Iterable<String>
All currently-bound fragment sampler names, in insertion order.
no setter
uniformBlockNames Iterable<String>
All currently-bound fragment uniform block names, in insertion order.
no setter
useEnvironment bool
Whether the engine should bind the active environment's IBL textures (prefiltered_radiance, brdf_lut) when the fragment shader declares them. Defaults to false.
getter/setter pair
vertexTextureNames Iterable<String>
All currently-bound vertex sampler names, in insertion order.
no setter
vertexUniformBlockNames Iterable<String>
All currently-bound vertex uniform block names, in insertion order.
no setter
windingOrder ↔ WindingOrder
Triangle winding order. Defaults to gpu.WindingOrder.counterClockwise to match the glTF convention and the standard materials.
getter/setter pair

Methods

bind(RenderPass pass, TransientWriter transientsBuffer, Lighting lighting) → void
Binds this material's render-pass state, uniforms, and textures.
override
bindVertexStage(RenderPass pass, Shader vertexShader, TransientWriter transientsBuffer) → void
Binds this material's vertex-stage uniforms to vertexShader, called by the encoder only when it used a material-supplied vertex shader (see materialVertexShader). The base implementation is a no-op; a material with vertex-stage parameters binds them here.
getTexture(String name, {ShaderStage stage = ShaderStage.fragment}) Texture?
Read back a previously-set texture binding, or null when none has been set.
getUniformBlock(String name, {ShaderStage stage = ShaderStage.fragment}) ByteData?
Read back a previously-set uniform block, or null when none has been set.
isOpaque() bool
Whether geometry rendered with this material is fully opaque.
override
materialVertexShader(String variant) Shader?
The vertex shader this material supplies for a geometry's variant ('unskinned' / 'skinned' for the color pass, 'depth' for the position-only depth/shadow pass; see Geometry.materialVertexVariant), or null to use the engine's standard vertex shader for the geometry.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
setFragmentShader(Shader shader) → void
Assigns the fragment shader used when this material is drawn.
inherited
setFragmentShaderName(String name, {String? cubeName}) → void
Assigns the fragment shader by name from baseShaderLibrary.
inherited
setRadianceCubeFragmentShader(Shader? shader) → void
Assigns the already-loaded variant built with FLUTTER_SCENE_RADIANCE_CUBE, the counterpart of setFragmentShader for a material that samples the environment.
inherited
setTexture(String name, Object? texture, {SamplerOptions? sampler, ShaderStage stage = ShaderStage.fragment}) → void
Assign a texture to a sampler uniform by name.
setUniformBlock(String name, ByteData? bytes, {ShaderStage stage = ShaderStage.fragment}) → void
Assign the byte contents of a uniform block by name.
setUniformBlockFromFloats(String name, List<double> floats, {ShaderStage stage = ShaderStage.fragment}) → void
Convenience wrapper around setUniformBlock that packs a list of float values. The caller is still responsible for std140 padding; see the class doc.
setVertexShader(Shader? shader, {MeshVariant variant = MeshVariant.unskinned}) → void
Assigns the vertex shader this material draws variant meshes with, or clears it when shader is null.
toString() String
A string representation of this object.
inherited
vertexShaderFor(MeshVariant variant) Shader?
The vertex shader assigned for variant, or null when the engine's standard one runs.

Operators

operator ==(Object other) bool
The equality operator.
inherited