MMD Player
A personal WebGPU viewer for checking source PMX models
Side Project · Three.js WebGPU · TSL Shader · JavaScript · tomlim2.github.io/mmd-anju
Motivation
I used the viewer myself to check source PMX models and distinguish their issues from problems introduced during conversion. I was its sole user.
Solution
I built checks for skinning, textures, and outline flags, along with skeleton and motion-compatibility analysis. On that validation foundation, I also explored WebGPU shading and lightweight effects driven by motion timing.
Automatic Motion Compatibility Analysis
Analyzes VMD motion files to calculate bone match rates against PMX models, and automatically detects IK conflicts and source model families. Game studio PMX models also follow these families — e.g., Honkai: Star Rail uses the DIVA family, Genshin Impact uses the ミリシタ family.
| Family | Characteristics |
|---|---|
| あにまさ式 (Animasa) | Default MMD model, minimal bone set (~30) |
| TDA式 | Includes semi-standard bones (上半身2, 腕捩, etc.) |
| YYB式 | TDA-based + extended auxiliary bones |
| にがもん式 | Compact bone set, non-Vocaloid characters |
| つみだんご式 | High-density custom bones (325), 50 expressions |
| ミリシタ | Romanized bone names, incompatible with standard VMD |
Motion-synced Effects — Precompute Experiment
I experimented with precomputing effect timing from VMD motion data on the CPU and combining it with light type, position, and color. The resulting motion-synced effects illustrated an R&D direction for track-based visual effects.
6 types: Foot Ripple, Spark Burst, Ground Reflect, Falling/Rising Light, Velocity Effect
Motion-synced bloom and particles
TSL Toon Shading — PMX Material Conversion
PMX matcap + additive overlay + alpha converted to TSL MeshBasicNodeMaterial. On this model, textureSample() was called 2–3 times per fragment for the same texture — cached the node once and reused it. Also pulled opacity out of Fn() to fix a bug where materials went invisible in the reflector pass.
Post-Process Pipeline — TSL Node Graph
Post-process stack on TSL nodes: bloom, ACES tone mapping, saturation, contrast, color temperature, film grain, vignette. Each effect has its own uniform so they can be toggled independently at runtime.
The pipeline builds two output chains that share the same uniforms but split at bloom. Turning bloom off swaps the output node — the GPU never runs the downsample+blur passes, not just at strength 0 but actually gone from the graph. When the whole PP is off, it falls back to the renderer's tone mapping directly.
Result
| Category | Result |
|---|---|
| Source Verification | A web viewer for checking source PMX models separately from converted results |
| Motion Verification | Supports 6 model families, automatic bone match rate/IK conflict detection |
| Effect Precompute | 6 types — Motion-synced effect experiments |
| Post-Process | Remove unused passes by swapping bloom nodes; fall back to the renderer when post-processing is off |
| Tech Validation | WebGPU + TSL shaders in a real project |
| Status | Active — next: physics bone simulation (rigid body + joint), gaussian splatting background |