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.
Run from root
Section titled “Run from root”% ./plume3d custom_material_packA 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.
What it does
Section titled “What it does”-
Builds an NDC quad with
Graphics.newMeshand a pack shader loaded fromshaders/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 rampmesh.setCustomTexture(1, Texture.load("textures/flow.png")) // slot 1: a scrolling flow mapmesh.setCustomColor(0, 1.0, 0.55, 0.2, 1.0) // params[0] = warm tintmesh.setCustomParamFloat(16, 0.15) // params[1].x = scroll speed -
The shader
#include "plume3d.slang"and reads them withplume3d_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.