Forge — Texture Baking & Procedural Textures
The texture layer produces the full PBR map set every downstream consumer expects: Albedo, Normal, Roughness, Metallic, AO, Height, Curvature. Maps are baked in Blender with Cycles (CPU fallback, never EEVEE-Next headless on Windows), then verified pixel-statistically and visually by rendering a preview sphere and reading the PNG.
Project memory: if
FORGE.mdexists at the project root, read it first — it carries the PBR workflow (metallic-roughness vs specular-gloss), texel density (px/m), max texture resolution, normal-map convention (OpenGL/DirectX target engine), and output paths. IfATELIER.mdalso exists, extract the primary OKLCH hue and aesthetic to inform procedural palette choices.
Suite map — relevant skills:
- forge — router/entry point; dispatches here for bake + texture tasks
- forge-uv — UV unwrapping and non-overlapping layout: a valid UV map is required before any bake; run forge-uv first if the mesh has no UVs or overlapping islands
- forge-material — PBR shading and Principled→glTF mapping; forge-texture produces the maps, forge-material wires them into the final material. Boundary: the green-channel flip / DX↔GL conversion of the baked normal PNG (pixel level) lives HERE; wiring that normal map into a Principled BSDF / glTF material is forge-material.
- forge-render — headless Cycles render for visual QA; the preview-sphere render in step 8 delegates to forge-render
- forge-validate — the mandatory gate after all maps are produced; runs pixel stats, UV overlap, and glTF-Validator; invoke before handing off to forge-export
- forge-export — packages the map set into glTF/GLB/FBX with correct texture slots and color spaces; consumes this skill's output paths
- forge-optimize — KTX2/Meshopt/Draco compression and the atelier-webgl handoff; compress the PNGs produced here before web delivery
- atelier-webgl — receives the final GLB + poster for Three.js/R3F scenes
- codex-imagegen — generates bespoke matcap/gradient/seamless textures via local Codex; call
Skill("codex-imagegen")when the procedural approach cannot produce the required aesthetic
Decide first: bake type and tool availability
Before writing any bake script, answer these four questions from FORGE.md (or ask):
- Source type — high-poly→low-poly (Selected-to-Active), Multires sculpt, or procedural shader?
- Map types required — Normal / AO / Curvature / Displacement / Diffuse / Roughness / Metallic?
- Target engine — Blender/Unity HDRP (OpenGL, G=+Y) vs Unreal/DirectX (G=−Y)?
- Resolution and sample budget — 1K/2K/4K? GPU available (OptiX/CUDA) or CPU-only?
Then verify Blender is on PATH:
# PowerShell — preflight
& blender --version
If Blender is not found, check C:\Program Files\Blender Foundation\ for the versioned folder and
use the absolute path. Full reference: references/headless-invocation.md.
The flow
Read FORGE.md (if present) → extract PBR workflow, texel density, normal convention, output paths.
Decide bake type — answer the four gate questions above; consult
references/bake-types-samples.mdfor sample counts, color spaces, and file formats per map type.Verify prerequisites — UV map is non-overlapping on the low-poly (run
Skill("forge-uv")if missing); transforms are applied (scale=True, rotation=True); any Multires or Subdivision modifier is at the correct level.Write the bake Python script — use the patterns in
references/bake-scripts.md(all canonical bpy snippets for hi→lo, Multires, AO, curvature, UDIM tile-shift workaround, and the Roughness/Metallic-via-Emission trick). The UDIM tile-shift workaround, the complete headless PowerShell bake pipeline, thesys.argv-after---parsing pattern, and the full G1–G15 bake gotcha → fix table (black bake, green/mustard splotches, seams, inverted normals, GPU-not-activated, native ROUGHNESS/METALLIC black, Musgrave removal) live inreferences/bake-advanced.md. Key invariants every script must enforce:scene.render.engine = 'CYCLES'prefs.refresh_devices()called after settingcompute_device_type- Image Texture node set as both
select = TrueANDnodes.activebeforebpy.ops.object.bake() img.colorspace_settings.name = 'Non-Color'for all data maps;'sRGB'for Albedo onlyimg.filepath_raw = "C:/absolute/forward/slash/path.png"(forward slashes; never raw backslashes)img.save()called explicitly after baking — Blender does not auto-save baked images
Invoke Blender headlessly — the canonical form on Windows (mandatory
--separator):& blender --background "C:/path/to/scene.blend" ` --python "C:/path/to/bake_script.py" ` --python-exit-code 1 ` -- --lowpoly "Hero_LP" --highpoly "Hero_HP" --out "C:/out" --res 2048Full PowerShell pipeline script:
references/headless-invocation.md §3.Procedural textures (when no high-poly source exists) — build Noise/Voronoi/Wave networks via bpy, bake to PNG on a unit plane, then apply seam-removal if tileability is required. Patterns, node property tables, and the Roughness/Metallic-via-Emission bake trick:
references/procedural-nodes.md. For AI-generated textures (matcap, gradient ramp, bespoke seamless), callSkill("codex-imagegen")then post-process for tileability.Pixel-level validation — after every bake, run the per-type stat checks from
references/validation.md: normal-map B-channel mean >= 160, AO max > 0.5, roughness std > 10, tileability edge-diff < 5.0. A failed check means rerun with corrected settings. When a check fails (or a bake comes back black, splotchy, seamed, or inverted), consult the G1–G15 gotcha → fix table inreferences/bake-advanced.md §4for the exact cause and remedy.Visual QA render — apply the baked maps to a UV sphere, render to PNG via Cycles (32 samples), then call
Readon the PNG to inspect visually. If the sphere shows uniform grey or black, the material wiring is wrong — fix and re-bake. RunSkill("forge-render")for the full turntable QA.Green-channel flip for DirectX targets — if FORGE.md says Unreal or DirectX target, flip the G channel. One-liner:
n[:,:,1] = 255 - n[:,:,1](cv2 BGR, index 1 = G). Pattern inreferences/validation.md §normal-convention.Compression — compress PNG outputs to KTX2 (ETC1S for albedo/AO, UASTC for normals) or WebP. The
ktxCLI commands, encode-quality guide, WebP conversion, and the POT-resize guard live inreferences/headless-invocation.md §§4–6. For web delivery, callSkill("forge-optimize")— it owns KTX2 and runs the full gltf-transform + KTX2 pipeline. Degrade gracefully: if thektxCLI is absent, ship WebP instead and note the missing-KTX2 gap in FORGE.md under## Texture mapsso forge-optimize can finish the compression later.Hand off — write final map paths back to FORGE.md under
## Texture maps; callSkill("forge-validate")as the mandatory gate; thenSkill("forge-export")to package the GLB.
Run = call the Skill tool with the exact name. Writing "next, run forge-validate" in prose runs nothing. Every cross-skill handoff is a
Skill("forge-validate")call.
Operating principles
- UV first, bake second. A missing or overlapping UV map produces a black bake with no error. Confirm non-overlapping UVs and applied transforms before touching any bake operator.
- Image Texture node must be active.
node.select = TrueANDnodes.active = nodeare both required — one without the other silently writes to the wrong image or raises a poll error. - Data maps are Non-Color; albedo is sRGB. Setting the wrong color space on a normal or roughness map corrupts engine shading with gamma de-correction artifacts that are invisible in Blender but catastrophic in game engines.
- Roughness and Metallic bake via Emission. The native
ROUGHNESSandMETALLICbake types are unreliable in Blender 4.x. Route the socket through an Emission node and bake asEMIT. - Verify, then ship. Every map gets pixel-stat validation (step 7) and a preview-sphere render (step 8) before being handed to forge-export. A bake that looks correct in Blender can still have wrong color space, wrong green channel, or undetected seams — the validation catches all three.
- Know the gotcha table. Every recurring bake failure — black bake, green/mustard splotches,
edge seams, inverted normals, GPU-falls-back-to-CPU, native ROUGHNESS/METALLIC black, missing
Musgrave node — has a one-line fix in the G1–G15 table at
references/bake-advanced.md §4. Reach for it the instant a bake looks wrong instead of re-deriving the cause.