pbr
stablePhysically-based rendering utilities including a PbrMaterial class, Cook-Torrance BRDF functions, Fresnel-Schlick, GGX distribution, geometry Smith, and light descriptor helpers.
use plugin pbr Plugin snippets can be edited in the Playground, but native capabilities are executed locally with the Zolo CLI.
Functions (24)
- PbrMaterial.new Create a PBR material with default values
- set_albedo Set base colour (r, g, b)
- set_metallic Set metallic factor 0–1
- set_roughness Set roughness factor 0–1
- set_normal_strength Set normal-map intensity
- set_emissive Set emissive colour (r, g, b)
- set_ao Set ambient occlusion factor 0–1
- get_albedo Read back albedo as a table
- get_metallic Read back metallic value
- get_roughness Read back roughness value
- get_emissive Read back emissive colour as a table
- get_ao Read back ambient occlusion value
- get_normal_strength Read back normal-map intensity
- clone Duplicate a material handle
- to_table Serialise all material properties to a table
- fresnel_schlick Schlick Fresnel reflectance (scalar)
- fresnel_schlick_vec3 Schlick Fresnel reflectance (RGB)
- distribution_ggx GGX normal distribution function
- geometry_schlick_ggx Schlick-GGX geometry term
- geometry_smith Smith geometry term
- cook_torrance_brdf Full Cook-Torrance specular BRDF
- point_light Build a point light descriptor table
- directional_light Build a directional light descriptor table
- lerp_material Linearly interpolate between two materials
From import to result
- 01Import only what you use
- 02Copy the smallest example
- 03Run it with the Zolo CLI
Create a PBR material with default values
Creates a new PBR material with physically sensible defaults: white albedo (1,1,1), metallic 0, roughness 0.5, normal strength 1, no emissive, AO 1.
use plugin pbr::{PbrMaterial}
let mat = PbrMaterial.new()
mat.set_albedo(0.8, 0.2, 0.1)
mat.set_roughness(0.3)
mat.set_metallic(0.0)
let props = mat.to_table()
print("Albedo R: {props["albedo_r"]}")Set base colour (r, g, b)
Sets the base (diffuse) colour of the material. Values are in linear 0.0–1.0 range.
use plugin pbr::{PbrMaterial}
let mat = PbrMaterial.new()
mat.set_albedo(0.2, 0.6, 1.0)Set metallic factor 0–1
Sets the metallic factor. 0.0 is fully dielectric (plastic/stone), 1.0 is fully metallic (copper/gold). Most real materials are either 0 or 1.
use plugin pbr::{PbrMaterial}
let mat = PbrMaterial.new()
mat.set_metallic(1.0)
mat.set_albedo(0.95, 0.64, 0.54)Set roughness factor 0–1
Sets the microsurface roughness. 0.0 produces a mirror-like surface; 1.0 is fully diffuse. Roughness is perceptually linear.
use plugin pbr::{PbrMaterial}
let mat = PbrMaterial.new()
mat.set_roughness(0.1)Set normal-map intensity
Sets the normal-map perturbation strength. 1.0 applies the normal map at full strength; 0.0 effectively ignores it.
use plugin pbr::{PbrMaterial}
let mat = PbrMaterial.new()
mat.set_normal_strength(0.5)Set emissive colour (r, g, b)
Sets the self-emission colour. Emissive pixels add light on top of the lighting calculation regardless of scene illumination. Values above 1.0 are valid for HDR bloom workflows.
use plugin pbr::{PbrMaterial}
let mat = PbrMaterial.new()
mat.set_emissive(2.0, 1.0, 0.0)Set ambient occlusion factor 0–1
Sets the ambient occlusion factor. 1.0 means no occlusion (full ambient); 0.0 means fully occluded. Typically sourced from a baked AO texture.
use plugin pbr::{PbrMaterial}
let mat = PbrMaterial.new()
mat.set_ao(0.8)Read back albedo as a table
Returns the albedo colour as a table with r, g, b float fields.
use plugin pbr::{PbrMaterial}
let mat = PbrMaterial.new()
mat.set_albedo(0.4, 0.7, 0.9)
let col = mat.get_albedo()
print("R={col["r"]} G={col["g"]} B={col["b"]}")Read back metallic value
Returns the current metallic factor.
use plugin pbr::{PbrMaterial}
let mat = PbrMaterial.new()
mat.set_metallic(0.9)
print("Metallic: {mat.get_metallic()}")Read back roughness value
Returns the current roughness value.
use plugin pbr::{PbrMaterial}
let mat = PbrMaterial.new()
mat.set_roughness(0.4)
print("Roughness: {mat.get_roughness()}")Read back emissive colour as a table
Returns the emissive colour as a table with r, g, b float fields.
use plugin pbr::{PbrMaterial}
let mat = PbrMaterial.new()
mat.set_emissive(1.0, 0.5, 0.0)
let e = mat.get_emissive()
print("Emissive R: {e["r"]}")Read back ambient occlusion value
Returns the current ambient occlusion factor.
use plugin pbr::{PbrMaterial}
let mat = PbrMaterial.new()
print("AO: {mat.get_ao()}")Read back normal-map intensity
Returns the current normal-map intensity.
use plugin pbr::{PbrMaterial}
let mat = PbrMaterial.new()
mat.set_normal_strength(0.75)
print("Normal strength: {mat.get_normal_strength()}")Duplicate a material handle
Creates an independent copy of the material as a new handle. Mutations to the clone do not affect the original.
use plugin pbr::{PbrMaterial}
let base = PbrMaterial.new()
base.set_albedo(1.0, 0.0, 0.0)
let copy = base.clone()
copy.set_albedo(0.0, 1.0, 0.0)
print("Base albedo R: {base.get_albedo()["r"]}")Serialise all material properties to a table
Serialises all material properties into a plain table with keys: albedo_r, albedo_g, albedo_b, metallic, roughness, normal_strength, emissive_r, emissive_g, emissive_b, ao.
use plugin pbr::{PbrMaterial}
let mat = PbrMaterial.new()
mat.set_albedo(0.3, 0.5, 0.8)
mat.set_roughness(0.2)
let t = mat.to_table()
print("Roughness: {t["roughness"]}")Schlick Fresnel reflectance (scalar)
Computes the Schlick Fresnel approximation for a single reflectance value F0. Returns the fraction of light reflected at the given view angle.
use plugin pbr::{fresnel_schlick}
let f = fresnel_schlick(0.0, 0.04)
print("Fresnel at grazing: {f}")Schlick Fresnel reflectance (RGB)
Per-channel Fresnel-Schlick for metallic workflows with a coloured F0. Returns a table with r, g, b reflectance values.
use plugin pbr::{fresnel_schlick_vec3}
let f = fresnel_schlick_vec3(0.0, 0.95, 0.64, 0.54)
print("Fresnel R: {f["r"]}")GGX normal distribution function
GGX (Trowbridge-Reitz) normal distribution function. Returns the statistical density of microfacets aligned with the halfway vector. Higher roughness spreads the highlight.
use plugin pbr::{distribution_ggx}
let d = distribution_ggx(0.9, 0.3)
print("GGX D: {d}")Schlick-GGX geometry term
Schlick-GGX geometry term for a single direction (view or light). Accounts for microfacet self-shadowing at a surface.
use plugin pbr::{geometry_schlick_ggx}
let g = geometry_schlick_ggx(0.8, 0.4)
print("G1: {g}")Smith geometry term
Smith geometry term combining two Schlick-GGX terms — one for the view direction and one for the light direction.
use plugin pbr::{geometry_smith}
let g = geometry_smith(0.8, 0.9, 0.4)
print("G Smith: {g}")Full Cook-Torrance specular BRDF
Evaluates the full Cook-Torrance specular BRDF: D * G * F / (4 * NdotV * NdotL). Returns the specular radiance multiplier for a single light.
use plugin pbr::{cook_torrance_brdf}
let spec = cook_torrance_brdf(0.9, 0.8, 0.7, 0.3, 0.04)
print("Specular: {spec}")Build a point light descriptor table
Creates a point light descriptor table with type, position (px, py, pz), colour (r, g, b), and intensity. This is a data helper — connect it to your renderer manually.
use plugin pbr::{point_light}
let light = point_light(0.0, 5.0, 0.0, 1.0, 0.95, 0.8, 10.0)
print("Light type: {light["type"]}")
print("Intensity: {light["intensity"]}")Build a directional light descriptor table
Creates a directional light descriptor table with type, direction (dx, dy, dz), colour, and intensity.
use plugin pbr::{directional_light}
let sun = directional_light(-0.5, -1.0, -0.3, 1.0, 0.98, 0.9, 3.0)
print("Sun direction y: {sun["dy"]}")Linearly interpolate between two materials
Linearly interpolates all properties between material a and material b at blend factor t (0.0 = full a, 1.0 = full b). Returns a new material handle.
use plugin pbr::{PbrMaterial, lerp_material}
let dry = PbrMaterial.new()
dry.set_roughness(0.9)
dry.set_metallic(0.0)
let wet = PbrMaterial.new()
wet.set_roughness(0.1)
wet.set_metallic(0.0)
wet.set_albedo(0.3, 0.35, 0.4)
let damp = lerp_material(dry, wet, 0.6)
print("Damp roughness: {damp.get_roughness()}")