Skip to content

Custom Material Pack

App: apps/custom_material_pack/

Demonstrates the extensible custom-material set (engine PLM-234 / ADR 0073) — the linchpin that lets a content pack’s shader bind its own textures and parameters with no engine change. Before this, the material descriptor ABI was hardcoded (the fixed six-map PBR set), so a pack shader could not add a texture. Now the engine reserves set 5 for whatever a shader wants, and the pack drives it from Wren.

Terminal window
% ./plume3d custom_material_pack

A neutral grayscale gradient ramp renders as a warm-tinted gradient modulated by a scrolling flow map — the tint and scroll speed come from the pack’s custom params, the two textures from its custom slots. That a grayscale ramp comes out warm-tinted proves both custom textures and custom params reach the shader, with no engine code for any of it.

  • Builds an NDC quad with Graphics.newMesh and a pack shader loaded from shaders/custom.

  • Binds the pack’s own resources through the set-5 custom material:

    mesh.setCustomTexture(0, Texture.load("textures/ramp.png")) // slot 0: a gradient ramp
    mesh.setCustomTexture(1, Texture.load("textures/flow.png")) // slot 1: a scrolling flow map
    mesh.setCustomColor(0, 1.0, 0.55, 0.2, 1.0) // params[0] = warm tint
    mesh.setCustomParamFloat(16, 0.15) // params[1].x = scroll speed
  • The shader #include "plume3d.slang" and reads them with plume3d_customTex(slot, uv) / plume3d_customParam(index) — nothing water- or toon-specific ships in the engine; it only provided the slots.

The engine binds up to eight customTextures[8] (binding 0), one shared customSampler (binding 1) and a 256-byte CustomParams UBO (binding 2) at set 5, all bounds-checked engine-side (slot 0..7, params clamped to 256 bytes). See the set-5 binding contract. Screenshot-verified.