arkavo-org / arkavo-org/VRMMetalKit

Silhouette: add restore/snapshot mechanism for round-trip toggle

Open
#164 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Swift
Stars
6
Forks
2
Avg merge
18h 51m
Merged PRs (30d)
26

Description

## Summary

\`VRMRenderer.applySilhouetteMode(model:config:)\` is a one-way mutation: it sets renderer flags, reconfigures lights, and rewrites every material's albedo/emissive/outline state. There is no counterpart \`restoreFromSilhouette(model:)\` and the doc comment on \`applySilhouetteMode\` notes the limitation:

> Idempotent — safe to call before or after \`loadModel\`. Any subsequent gameplay-style scene reset would need to undo each step manually.

For host apps that want to toggle silhouette mode on/off in the same renderer instance (menu host transitions, accent shots), this is user-hostile — they have to reload the model.

## Suggested approach

Two parts, can ship together or separately:

**1. Renderer-side restore (cheap):**
- Snapshot the four renderer flags affected (\`disableAutoMaterialOverrides\`, \`additiveDirectionalRimEnabled\`, \`additiveDirectionalRimPower\`, plus the three light slots and ambient color) before mutating in \`applySilhouetteMode\`.
- Store the snapshot in a private \`silhouetteSnapshot\` property.
- Add \`restoreFromSilhouette()\` that reverts those.

**2. Material-side restore (heavier):**
- Snapshot per-material \`baseColorFactor\`, \`baseColorTexture\`, \`emissiveTexture\`, \`emissiveFactor\`, plus the MToon fields zeroed by silhouette (\`shadeColorFactor\`, \`matcapFactor\`, \`parametricRimColorFactor\`, \`giIntensityFactor\`, the four outline fields).
- Memory: ~80 bytes/material × ~15 materials = ~1.2 KB per model. Trivial.
- Reset via deep copy back into \`model.materials[i]\`.

Alternative: have the host maintain its own snapshot before calling \`applySilhouetteMode\` and restore via a fresh model load. This puts the burden on the caller but avoids API surface area inside the renderer.

## Discovered during

PR #137 review. Added unit-test coverage for \`applySilhouetteMode\` mutation invariants in \`8c2de51\`; a future restore mechanism would need the same coverage symmetrically (round-trip identity).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Contributor guide

Open the contributing guide

Research direction

Start by reading VRMRenderer.applySilhouetteMode(model:config:) and the unit-test coverage added in commit 8c2de51 for its mutation invariants. Define the snapshot boundary between renderer and material state, then add symmetric round-trip tests showing that restoring after silhouette mode returns the model and renderer to their original state.

Written by the indexing model from the issue text.

Assessment

Tech stack
swift
Domain
computer-graphics
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.