| name | vrm-mtoon-outline |
| description | Adjusting VRM MToon material outline thickness in three-vrm. Covers outline width modes, property access, and how to fix outlines that appear too thick when models are scaled. |
VRM MToon Outline Thickness Adjustment
This skill covers how to adjust outline thickness for VRM models using MToon materials in @pixiv/three-vrm.
Common Symptoms
- Outline too thick when model is scaled up or camera is close
- Outline thickness inconsistent at different zoom levels
- Need to adjust outline programmatically at runtime
Key Concepts
Outline Width Modes
MToon materials have two main outline width modes:
| Mode | Description | Behavior |
|---|
'worldCoordinates' | Outline width is a physical world-space size | Outline appears thicker when model is scaled up or camera is closer |
'screenCoordinates' | Outline width is relative to screen pixels | Outline stays consistent size regardless of zoom/scale |
Critical Properties
material.outlineWidthMode
material.outlineWidthFactor
material.isMToonMaterial
material.needsUpdate
Solution: Switch to Screen Coordinates
To make outlines stay consistent regardless of zoom/scale:
function adjustOutlineThickness(vrm, screenFactor = 0.005) {
vrm.scene.traverse((object) => {
if (object.isMesh || object.isSkinnedMesh) {
const materials = Array.isArray(object.material) ? object.material : [object.material];
materials.forEach(material => {
if (!material || !material.isMToonMaterial) return;
const hasOutline = material.outlineWidthFactor > 0 &&
material.outlineWidthMode !== 'none';
if (hasOutline) {
material.outlineWidthMode = 'screenCoordinates';
material.outlineWidthFactor = screenFactor;
material.needsUpdate = true;
}
});
}
});
}
Factor Value Guidelines
For screenCoordinates mode:
| Factor Value | Approximate Effect |
|---|
0.002 - 0.003 | Very thin outline (1 pixel) |
0.005 | Thin outline (1-2 pixels) |
0.01 | Medium outline (2-3 pixels) |
0.02+ | Thick outline |
Detection Pattern
To diagnose outline issues, log all materials:
function debugOutlineMaterials(vrm) {
let count = 0;
vrm.scene.traverse((object) => {
if (!object.isMesh && !object.isSkinnedMesh) return;
const materials = Array.isArray(object.material) ? object.material : [object.material];
materials.forEach(material => {
if (material?.isMToonMaterial || 'outlineWidthFactor' in material) {
count++;
console.log({
name: material.name || '未命名',
type: material.type,
isMToonMaterial: material.isMToonMaterial,
outlineWidthMode: material.outlineWidthMode,
outlineWidthFactor: material.outlineWidthFactor
});
}
});
});
console.log(`Found ${count} MToon/Outline materials`);
}
Important Notes
[!IMPORTANT]
Call timing matters! The function must be called AFTER currentModel is set. In vrm-core.js, the loadModel() function sets manager.currentModel near line 923. Any function that accesses currentModel must be called after this point.
[!NOTE]
Materials named "XXX (Outline)" are outline pass materials automatically created by three-vrm. They share properties with the main material but render the outline effect.
API Reference (three-vrm MToon)
The enum values for outlineWidthMode:
{
None: "none",
WorldCoordinates: "worldCoordinates",
ScreenCoordinates: "screenCoordinates"
}
| Property | Type | Description |
|---|
outlineWidthMode | string | Width calculation mode |
outlineWidthFactor | number | Width value (meaning depends on mode) |
outlineColorFactor | Color | Outline color |
outlineLightingMixFactor | number | How much lighting affects outline |
outlineWidthMultiplyTexture | Texture | Texture to modulate outline width |