diff --git a/.claude/skills/art-dev/references/blender-cookbook.md b/.claude/skills/art-dev/references/blender-cookbook.md index 9d9fa45e4..bcf954729 100644 --- a/.claude/skills/art-dev/references/blender-cookbook.md +++ b/.claude/skills/art-dev/references/blender-cookbook.md @@ -223,4 +223,30 @@ bpy.ops.export_scene.gltf(filepath=SRC + r"\SM_.glb", export_format='GLB', use_selection=True, export_apply=True, export_yup=True) ``` Skinned/animation export → the per-action FBX recipe in [[blender-mcp-and-unity-mcp-v10]] (`bake_anim_use_all_bones`, `bake_anim_force_startend_keying`, `apply_scale_options='FBX_SCALE_UNITS'`, `add_leaf_bones=False`; Unity import `CreateFromThisModel`). **Never export into `Assets/` while a Unity session may be live** — write to `ArtSource/`, bake in later. + +## 11. In-engine verification (Unity URP render harness) — the REAL A0 check + +Blender previews are a proxy; the gate is the asset in **URP** under murk + bloom + the game camera. Import + render via UnityMCP (only when the editor is free / operator granted it — else stay read-only): +1. **Import** the glb: `import_model_file(source_path=, output_folder="Assets/_Project/Art/Models", name=...)` — needs the leading `Assets/`; glTFast handles glb + scale. +2. **Confirm the shared material samples the atlas** — the palette ShaderGraphs expose it as **`_BaseColorMap`** (NOT `_BaseMap`/`mainTexture`, so `mat.mainTexture` reads null — that's fine): `ShaderUtil` enumerate or `mat.GetTexture("_BaseColorMap")`. +3. **Render harness** (`execute_code`, C#): load the `Mesh` from the imported glb, spawn a temp GO (mesh + shared material) on an **isolated layer**, warm-key + cold-fill directional lights (`cullingMask` = that layer), murk ambient (save+restore `RenderSettings.ambientMode/ambientLight`), a temp `Camera` (SolidColor murk bg, `cullingMask` = that layer, **FOV 55**) positioned at the **game angle** and framed by `MeshRenderer.bounds`, then **`RenderPipeline.SubmitRenderRequest(cam, new StandardRequest{destination=rt})`** (URP — `Camera.Render()` is unreliable) → `ReadPixels` → `EncodeToPNG` to OS temp → `Read` the PNG. `DestroyImmediate` all temp objects; never save the open scene. + - ⚠ **Layer sign-bit:** `1<<31` is NEGATIVE → a broken culling mask that renders NOTHING (all-black). Use **layer ≤ 30**. + - ⚠ Set `cam.cullingMask` to ONLY the temp layer so the open scene's geometry doesn't leak into the shot (`~0` renders the whole scene). + - Game-cam offset from target: `(horiz*cos(pitch) + up*sin(pitch))*dist`, `horiz=(sin(yaw),0,-cos(yaw))`, pitch 45°, then `cam.transform.LookAt(center)`. +```csharp +// core render call (URP) +var rt=new UnityEngine.RenderTexture(1000,1000,24); rt.Create(); +var req=new UnityEngine.Rendering.RenderPipeline.StandardRequest(); req.destination=rt; +UnityEngine.Rendering.RenderPipeline.SubmitRenderRequest(cam, req); +UnityEngine.RenderTexture.active=rt; var tex=new UnityEngine.Texture2D(1000,1000,UnityEngine.TextureFormat.RGBA32,false); +tex.ReadPixels(new UnityEngine.Rect(0,0,1000,1000),0,0); tex.Apply(); +System.IO.File.WriteAllBytes(path, UnityEngine.ImageConversion.EncodeToPNG(tex)); +``` +**Findings from the first bake (crate):** the palette single-material pipeline works in URP; a pure-murk render reads *dark* (in-game URP bloom + scene fill lift it); grey under a warm key reads brownish (expected, not a bug). Skinned assets (suit/creatures) need the Rukhanka path + `Skinned-Palette` — hand to `/dots-dev`. + +## 12. The persistent staging scene (`Assets/Scenes/ArtStaging.unity`) — the operator's in-engine view +A committed dev scene set up in the **correct A0 conditions** so the operator can OPEN it and inspect assets live (Scene-view orbit) at the gameplay angle: murk env (cold flat ambient + `ExponentialSquared` fog, no skybox), **warm-key + cold-gloam directional lights + a warm point pool**, a **Main Camera at the game angle** (pitch ~42–45°, FOV 55, `UniversalAdditionalCameraData.renderPostProcessing=true`), and a **global Volume** (profile `Assets/_Project/Art/Materials/Staging/StagingVolume.asset`: **Bloom** thr~0.85/int~1.1 — makes Emissive-Gloam glow — + **Tonemapping ACES** + **ColorAdjustments** postExposure/saturation = the capture grade), on a dark faceted pedestal. Contains labeled `SLOT_*` empties for pending assets. +- **To verify a newly-baked asset:** `import_model_file` the glb → assign the shared material (`M_Lit_Palette` statics; emissive bulbs → an HDR-emission material so bloom triggers) → `PrefabUtility.InstantiatePrefab(asset, scene)` into ArtStaging at a slot → `SaveScene` → tell the operator to open it, OR render `Camera.main` via §11. +- ⚠ Opening ArtStaging `Single` closes the active scene — only do it when the editor is free / operator-authorized (a parallel agent's scene would be swapped out). Check `editor/state` first; the scene must be clean before swapping. +- Beginner view steps to hand over: open the scene (double-click in Project ▸ Assets/Scenes), **orbit** = middle-mouse drag, **zoom** = scroll, **frame a selected object** = `F`, **Game tab** shows the gameplay-angle camera. ```