"For runtime per-surface color, bake a texture — don't rely on complex.shader vertex color"
▸ SYMPTOM
You want to color a mesh per-surface at runtime — per-chunk terrain tints, team colors, a procedurally colored generated mesh — and reach for per-vertex color painting through the stock complex.shader, expecting it to read a vertex color stream as albedo. It doesn't do what you hoped, and there is no source to check why.
▸ CAUSE
complex.shader ships compiled-only and shows no vertex-color-as-albedo feature. On the installed build (engine 26.07), complex.shader exists only as core/shaders/complex.shader_c — there is no .shader source under addons/base/assets/shaders/ to inspect. A scan of its embedded identifiers shows no vertex-color/paint feature names.
Vertex color plumbing does exist in the engine (vVertexColor on TEXCOORD4, declared in common/pixelinput.hlsl), but shaders that use it — blendable.shader, for example — consume it as a layer mask, not as an albedo multiply. So "paint albedo per vertex through complex.shader" has no path.
▸ FIX
Use a baked texture + a per-instance material copy. Sandbox.Engine.xml documents the full runtime override path:
Material.CreateCopy(string)— "Create a copy of this material"Material.Set(string, Texture)— "Override/Sets texture parameter (Color, Normal, etc)"Material.Create(name, shader, anonymous)— from-scratch material creation
For per-chunk or per-instance surface coloring, bake a small texture and bind it as the color map:
// Build a tiny per-region color texture (the proven minimap recipe)
var tex = Texture.Create( width, height )
.WithDynamicUsage()
.Finish();
tex.Update( colors ); // Color32[] laid out per cell/region
var mat = baseMaterial.CreateCopy();
mat.Set( "Color", tex ); // "Color" is the albedo texture parameter
renderer.MaterialOverride = mat;The "Color" parameter name does take in-editor on this build (verified: per-chunk blend colors render as their real values, not magenta/white), so the older "g_tColor" fallback is not needed here.
▸ WHY IT WORKS
complex.shader is a closed, general-purpose surface shader — you cannot add an albedo-from-vertex-color feature to something whose source you don't have. The documented, supported lane is the material override API: CreateCopy gives you a per-instance material, and Set("Color", tex) swaps its albedo texture for a small baked one you fill from a Color32[]. This whole path (CreateCopy + Set + Texture.Create/WithDynamicUsage) passes the in-editor code whitelist and compiles green, and it does not leak: creating many same-named material copies per regeneration fluctuates the working set with GC but fully reclaims — no unbounded climb across repeated regenerations.
- Published