diff options
| author | Yasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com> | 2026-10-06 09:56:21 +0900 |
|---|---|---|
| committer | Yasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com> | 2026-10-06 09:56:21 +0900 |
| commit | 8f39a174d6c4415c7a4df418187090fb5e061983 (patch) | |
| tree | dbd3cf1e4f67393f029a455c4226479fbefe4804 /public/bluebey-studio/src/styles.js | |
| parent | 63c1a9dfa8b04ab9725a9a49ef34cd3fc6ade56c (diff) | |
bluebey-studio: ボーンのたて回転・縦書きと吹き出しの形・線画の帽子小物・光の色
ボーンのたてスライダーが±180°で暴れる問題を修正。セリフの縦書きを禁則込みで直し、「ささやき」「思考」の吹き出しを追加。帽子・小物の輪郭線を線画のみにし、線画で帯や芯の境目が読めるよう調整。眼鏡の左右レンズ間隔、光と環境光の色を追加。ハートの下まぶた、レンズが濃いときのまばたきを修正。口メニューの項目名を整理。「顔/すべてをランダム」に眼鏡・Oの口・ひげの大きさ・目の左右位置などを追加。
Diffstat (limited to 'public/bluebey-studio/src/styles.js')
| -rw-r--r-- | public/bluebey-studio/src/styles.js | 60 |
1 files changed, 48 insertions, 12 deletions
diff --git a/public/bluebey-studio/src/styles.js b/public/bluebey-studio/src/styles.js index 8efdf71..2e4f62d 100644 --- a/public/bluebey-studio/src/styles.js +++ b/public/bluebey-studio/src/styles.js @@ -112,9 +112,13 @@ export class Styles { this.paperMaterial = new THREE.MeshBasicMaterial({ color: paper, toneMapped: false }); // A hat is not flat: in a line drawing a white hat on a white head merges // into one shape, so hats get a light tone instead of paper (see addMesh). - this.toneMaterial = new THREE.MeshBasicMaterial({ color: toneOf(paper), toneMapped: false }); - /** Runtime meshes that want the tone fill rather than paper in 線画. */ - this.toneMeshes = new Set(); + // The tone is per-mesh (`toneMeshes`, mesh -> material) and the amount it + // steps from the paper towards the ink is cached by strength in + // `toneMaterials`, so a part on a same-coloured neighbour (a hat band, a + // pencil's lead) can ask for a darker fill and its seam then reads. + this.toneMaterials = new Map(); + /** Runtime meshes that want a tone fill rather than paper in 線画. */ + this.toneMeshes = new Map(); this.invisibleMaterial = new THREE.MeshBasicMaterial({ colorWrite: false, depthWrite: true }); this.outlineWidth = outlineWidth; @@ -159,6 +163,25 @@ export class Styles { return entry.material; } + /** + * The flat fill a runtime mesh wears instead of paper in 線画, cached by how far + * it steps from the paper towards the ink. `userData.tone` on the mesh (set by + * the builder) carries the amount; the hat default comes from `options.tone`. + */ + toneMaterialFor(strength = DEFAULT_TONE) { + const key = String(strength); + let material = this.toneMaterials.get(key); + if (!material) { + material = new THREE.MeshBasicMaterial({ + color: toneOf(this.paper, strength), + toneMapped: false, + }); + material.userData.tone = strength; + this.toneMaterials.set(key, material); + } + return material; + } + createOutlines() { const hulls = []; for (const mesh of this.meshes) { @@ -193,13 +216,20 @@ export class Styles { * styles and gets an outline hull like the GLB parts. `removeMesh` undoes it. * * `options.tone` gives the mesh the light tone fill in 線画 instead of paper, - * for parts whose shape would otherwise merge with the body (the hats). + * for parts whose shape would otherwise merge with the body (the hats). A + * number instead of `true` picks how far to step towards the ink, and the + * builder can override it per mesh with `userData.tone` - which is how a part + * draws its seam against a same-coloured neighbour. + * + * `options.lineOnly` keeps the hull to the line-art styles, so a runtime mesh + * (a hat, a prop) gets its ink outline in 線画 but none in リアル / フラット. */ addMesh(mesh, options = {}) { if (!mesh || this.originals.has(mesh)) return; this.originals.set(mesh, mesh.material); this.meshes.push(mesh); - if (options.tone) this.toneMeshes.add(mesh); + const tone = mesh.userData.tone ?? options.tone; + if (tone) this.toneMeshes.set(mesh, this.toneMaterialFor(tone === true ? DEFAULT_TONE : tone)); const kind = this.kindOf(mesh); if (!OUTLINE_SKIP.has(kind)) { const overlay = OUTLINE_SILHOUETTE_ONLY.has(kind); @@ -214,7 +244,7 @@ export class Styles { if (overlay) hull.renderOrder = -1; hull.userData.kind = kind; hull.userData.source = mesh; - hull.userData.lineOnly = OUTLINE_LINE_ONLY.has(kind); + hull.userData.lineOnly = options.lineOnly === true || OUTLINE_LINE_ONLY.has(kind); hull.userData.shadedOnly = OUTLINE_SHADED_ONLY.has(kind); mesh.parent?.add(hull); this.outlineMeshes.push(hull); @@ -264,7 +294,7 @@ export class Styles { // the leaves - is drawn by the screen-space outline, so no part needs a // material trick of its own any more. material = value === 'lineart' - ? (this.toneMeshes.has(mesh) ? this.toneMaterial : this.paperMaterial) + ? (this.toneMeshes.get(mesh) ?? this.paperMaterial) : this.invisibleMaterial; } else if (value === 'flat') { material = this.toonFor(original); @@ -325,7 +355,9 @@ export class Styles { setPaper(color) { this.paper = color; this.paperMaterial.color.set(color); - this.toneMaterial.color.copy(toneOf(color)); + for (const material of this.toneMaterials.values()) { + material.color.copy(toneOf(color, material.userData.tone)); + } } setOutlineVisible(visible) { @@ -379,7 +411,8 @@ export class Styles { for (const entry of this.hullMaterials.values()) entry.material.dispose(); this.hullMaterials.clear(); this.paperMaterial.dispose(); - this.toneMaterial.dispose(); + for (const material of this.toneMaterials.values()) material.dispose(); + this.toneMaterials.clear(); this.invisibleMaterial.dispose(); this.gradientMap.dispose(); for (const material of this.toonMaterials.values()) material.dispose(); @@ -387,9 +420,12 @@ export class Styles { } } -/** A step towards the ink, for the light fill a hat gets in 線画. */ -function toneOf(paper) { - return new THREE.Color(paper).lerp(new THREE.Color('#2a1e33'), 0.14); +/** How far the hat default steps from the paper towards the ink in 線画. */ +const DEFAULT_TONE = 0.14; + +/** A step towards the ink, for the flat fill a runtime mesh gets in 線画. */ +function toneOf(paper, strength = DEFAULT_TONE) { + return new THREE.Color(paper).lerp(new THREE.Color('#2a1e33'), strength); } /** A 3-step ramp gives crisper cartoon bands than the shader's default. */ |
