Color.Material (Color v0.12.1)

Copy Markdown

A physically-based-rendering (PBR) material wrapper around a base colour.

%Color.SRGB{} describes a colour stimulus. %Color.Material{} describes a surface — a colour plus the appearance parameters (metallic, roughness, clearcoat) that determine whether the surface reads as plastic, painted metal, glossy varnish, or matte ceramic. Two materials can share the same base colour yet look entirely different because of how light interacts with them.

The parameter set deliberately matches the Disney Principled BSDF / glTF 2.0 pbrMetallicRoughness convention so values from those sources can be imported directly.

Why this exists

When you sort a palette that mixes plastic swatches with polished-metal swatches, any single-axis colour sort puts identical base colours next to each other regardless of finish — a red plastic and a red-anodized aluminium end up visually adjacent even though users file them into different mental categories. Color.Palette.Sort's :material_pbr strategy consumes this struct and produces an ordering that respects the metallic-vs-dielectric cliff first, then colour, then gloss.

Parameters

  • :base_color — a %Color.SRGB{} struct. The "albedo" for dielectrics or the "specular colour" for metals.

  • :metallic0.01.0. 0.0 is a pure dielectric (plastic, paint, wood, skin); 1.0 is a pure conductor (gold, copper, aluminium). Values in between model partial metallic coatings such as metallic automotive paint.

  • :roughness0.01.0. 0.0 is a perfect mirror; 1.0 is a fully diffuse (Lambertian) surface.

  • :clearcoat0.01.0. Strength of an optional dielectric varnish layer on top. Defaults to 0.0 (no clearcoat).

  • :clearcoat_roughness0.01.0. Roughness of the clearcoat layer. Ignored when :clearcoat is 0.0. Defaults to 0.03 (near-mirror, matching automotive paint).

  • :name — optional string label stored with the material.

Example

iex> {:ok, red} = Color.new("#ff0000")
iex> mat = Color.Material.new(red, metallic: 0.0, roughness: 0.85, name: "Matte Red PC")
iex> mat.name
"Matte Red PC"
iex> mat.metallic
0.0

Summary

Functions

Returns the underlying base colour.

Builds a %Color.Material{} struct.

Returns a tuple suitable for tuple-based sorting.

Types

t()

@type t() :: %Color.Material{
  base_color: Color.SRGB.t(),
  clearcoat: float(),
  clearcoat_roughness: float(),
  metallic: float(),
  name: binary() | nil,
  roughness: float()
}

Functions

base_color(material)

@spec base_color(t()) :: Color.SRGB.t()

Returns the underlying base colour.

Arguments

  • material is a %Color.Material{} struct.

Returns

  • A %Color.SRGB{} struct.

Examples

iex> mat = Color.Material.new("#ff0000")
iex> Color.to_hex(Color.Material.base_color(mat))
"#ff0000"

new(color_input, options \\ [])

@spec new(
  Color.input(),
  keyword()
) :: t()

Builds a %Color.Material{} struct.

Arguments

  • color_input is anything accepted by Color.new/1 — a hex string, a CSS named colour, an %Color.SRGB{} struct, an Oklch struct, etc. The input is normalised to %Color.SRGB{} and stored in :base_color.

Options

  • :metallic is the metallic parameter in [0.0, 1.0]. Default 0.0 (dielectric).

  • :roughness is the roughness parameter in [0.0, 1.0]. Default 0.5.

  • :clearcoat is the clearcoat strength in [0.0, 1.0]. Default 0.0.

  • :clearcoat_roughness is the clearcoat roughness in [0.0, 1.0]. Default 0.03.

  • :name is an optional string label.

Returns

  • A %Color.Material{} struct.

Examples

iex> mat = Color.Material.new("#c0c0c0", metallic: 1.0, roughness: 0.2)
iex> mat.metallic
1.0
iex> mat.roughness
0.2

iex> mat = Color.Material.new("red")
iex> Color.to_hex(mat.base_color)
"#ff0000"
iex> mat.metallic
0.0

to_pbr_tuple(material, options \\ [])

@spec to_pbr_tuple(
  t(),
  keyword()
) :: {non_neg_integer(), float(), float(), float()}

Returns a tuple suitable for tuple-based sorting.

The tuple is {metallic_bucket, hue, lightness, roughness} where metallic_bucket is 0 for dielectrics and 1 for metals, computed from metallic >= threshold.

Used by Color.Palette.Sort's :material_pbr strategy and exposed so third parties can compose their own sort keys.

Arguments

  • material is a %Color.Material{} struct.

Options

  • :metallic_threshold is the cutoff between dielectric and metallic buckets, in (0.0, 1.0]. Default 0.5.

Returns

  • A {integer, float, float, float} tuple.

Examples

iex> mat = Color.Material.new("#c0c0c0", metallic: 1.0, roughness: 0.2)
iex> {bucket, _h, _l, rough} = Color.Material.to_pbr_tuple(mat)
iex> bucket
1
iex> rough
0.2