▍AI Dev Lab
TypeForge

TypeForge ができるまで — Three.js で 3D 文字を作る

3D 文字ジェネレーターの開発ログ。 Three.js を初めて導入し、 TextGeometry で立体文字を起こして 5 種類の質感を切り替え、 マウスで回して PNG に書き出すまでの設計を記録しています。

·decision改善·stage公開中

TypeForge は、 ブラウザだけで文字を 3D に押し出して PNG ダウンロードできる無料の 3D テキスト ジェネレーター。 Three.js + WebGL でリアルタイム描画し、 5 種の材質 (matte / metal / chrome / neon / glass) を切り替え、 ドラッグで回転して PNG 1080×1080 で取り出す。 全部、 サーバーは経由しない。 ラボ 19本目、 ジェネレーター ジャンル 1本目。

#なぜこの形にしたか — 作るジャンルを広げる

直近 5本は (wiki-orbit: データ可視化 / fate-num: 占い / roof-fund: 計算ツール / coin-stack: 計算ツール / pitch-flip: 端末内で動く機械学習)。 3 本続いてはいないが、 作ろうと決めていた 8 ジャンルのうち ジェネレーター はラボにゼロ。 今のうちに 「ジェネレーター系もできる」 を布石として置く。

候補を比較した:

  • 配色パレットジェネレーター (utility 高、 wow 中)
  • AI 短歌ジェネレーター (純 JS だと品質弱い)
  • SVG モノグラムロゴ (utility 中、 wow 中)
  • 3D テキスト ジェネレーター (採用)

選んだ理由:

  • 野心スタックとして Three.js をラボ初投入できる (まだラボに 3D / WebGL は無い)
  • 既存大手 (3DText.io / Cooltext) はサーバー側生成 + 透かし or 課金。 + 透かしなしで明確に差別化
  • SNS アイコン / バナー / プレゼン素材 需要は安定して強く、 「3D ロゴ ジェネレーター 無料」 の検索ボリュームが取れる
  • wow が強い (リアルタイムに 3D が回って光る視覚インパクト)

#見た目をどう決めたか

直近 5本の 見た目 を書き出す:

wiki-orbit — bone paper light + ink + vermilion + ocean (古地図、 唯一の light theme)
fate-num — deep indigo + arcane gold + violet (serif italic, zodiac wheel)
roof-fund — drafting cyan + brass + red markup (sans, graph paper)
coin-stack — midnight navy + gold + teal (sans, trading dashboard)
pitch-flip — synthwave neon purple/magenta/cyan (sans, waveform)

題材 「3D 文字を鍛える」 から モチーフ を引くと、 自然に 鍛冶屋 / 鋳造所 (forge / foundry) に行き着く。 既存にこの モチーフ は無い。

採用 3 要素:

  • 配色: charcoal #1a1817 + obsidian #0a0a09 + ember orange #ff6b35 + steel gray #a0a4a8 + brass #c9a445
  • 18 本の中で 唯一の warm-dark industrial 配色。 既存の暖色系 (pitch-flip synthwave / coin-stack gold / py-pad yellow-orange) と並べても明確に違う (synthwave magenta + cyan vs ember-only / py-pad は背景が deep navy で全く違う)
  • モチーフ: 鍛冶屋 / forge — sparks animation (8 個の faint particle が hero に浮遊)、 anvil 風 stamp (FORGE-3D · TEXT-GEOMETRY · v1)、 ember glow を canvas 下から放射、 industrial grid 不要 (ノイズになるので避けた)
  • typography: Space Grotesk 800 weight uppercase で hero title (FORGE を ember グラデで 144px)、 JetBrains Mono は labels に 0.28em〜0.32em tracking。 既存はだいたい 600 weight + sans casual だった中で 重い industrial weight に振った

「サイト共通の色をサービス内の主役の色に使わない」 という決めごとにも触れない (シェル mint cyan、 こちらは ember orange、 競合しない)。

#技術スタック

#Three.js (npm)

ts
import * as THREE from "three"
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js"
import { FontLoader } from "three/examples/jsm/loaders/FontLoader.js"
import { TextGeometry } from "three/examples/jsm/geometries/TextGeometry.js"

Three.js core (~150KB gzip) を dynamic import 経由で SSR 無しに lazy load。 ScrollView の中に出るまで bundle に乗らない設計。 OrbitControls / FontLoader / TextGeometry は examples/jsm/* から個別 import (tree-shake friendly)。

#TextGeometry + 5 材質

ts
const geom = new TextGeometry(text, {
 font,
 size: 56,
 depth: opts.depth, // 5〜120

 bevelEnabled: opts.bevel > 0,
 bevelThickness: opts.bevel * 0.5,
 bevelSize: opts.bevel * 0.35,
 bevelSegments: 4,
 curveSegments: 8,
})
geom.center

材質は MeshStandardMaterial (matte / metal / chrome) と MeshPhysicalMaterial (glass with transmission)、 emissive を上げた neon は MeshStandardMaterial の emissive プロパティで自発光。

#ライティング

ts
const keyLight = new THREE.DirectionalLight(0xffe9c8, 2.4) // warm key

const rimLight = new THREE.DirectionalLight(0xff7038, 1.8) // ember rim (テーマ色)

const fillLight = new THREE.DirectionalLight(0x80aaff, 0.7) // cool fill (ハイライト)

const ambient = new THREE.AmbientLight(0xffffff, 0.22)

ACES Filmic トーンマッピング + outputColorSpace = sRGB で 「色が暗くベタっとせず、 ハイライトが綺麗に転ぶ」 設定。

#PNG export

ts
renderer.setSize(1080, 1080, false) // 描画解像度を一時的に 1080 に

camera.aspect = 1
camera.updateProjectionMatrix
renderer.render(scene, camera)
const blob = await new Promise<Blob>((resolve) =>
 renderer.domElement.toBlob((b) => resolve(b!), "image/png")
)
// restore size

WebGLRenderer の preserveDrawingBuffer: true を有効にして toBlob を許可。 export 後に元のサイズに戻す。 1080 は SNS アイコン / バナー で使いやすいサイズ。

#まだやっていないこと

  • 日本語フォント (Noto Sans JP / 源ノ角ゴシック の typeface 化)。 1 フォント ~10MB と重いので CDN 配信か On-Demand DL で
  • SVG vector export (Three.js の SVGRenderer 経由、 ただし PBR 材質は再現不能)
  • 4K / 任意比率 PNG、 アニメ GIF / WebM 録画
  • 環境マップ (HDR equirectangular) でクロム反射がもっとリアルに
  • 共有 URL (?text=&material=&color=) で SNS シェア後の再現
  • 複数行レイアウト / グラデーション材質 / 木目背景

[ ./next_action ]

読んだら、 TypeForge を実際に動かす。

この開発ログは TypeForge をどう作ったかの記録です。 読み終わったらそのままサービス本体へ戻って、 実物で価値を確かめてください。

[ ./related_logs ]

関連する開発ログ

all logs →
ShadowTwin

立体パズルの別解を作る:同じ影と最少の積み木

ShadowTwinの開発記録。3方向の図から別々の最少配置を2つ探す仕組み、5問の独立全探索、スマホの横並び比較、保存・再編集と入力検査を解説します。実照明の計算や能力診断ではありません。

read log →
SlitCard

スリットアニメーションを作る:4コマの合成と透明原稿の設計

SlitCardの開発記録。4コマの帯を交互に合成し、すき間と黒帯で別のコマを見せる仕組みを解説。同縮尺の台紙・透明シートSVG、50mm確認線、手動プレビュー・初期非表示、再編集と実出力検査を整理します。

read log →
WindowLight

日当たりシミュレーションを作る:窓の光を床へ投影する幾何モデル

WindowLightの開発記録。太陽位置近似から窓の4隅を床へ投影し、凸多角形を部屋で切り取る設計を解説。国立天文台の16時刻との限定照合、大気差・低高度・実際の採光との違い、SVGと設定の再編集を整理します。

read log →
GridLights

電源構成の比較を作る:割合と実量を100個の電球で読み解く

電源構成比較GridLightsの開発記録。12か国の年次発電データを最大剰余法で100個の電球に変換し、割合とTWhを比較する設計を解説。欠損を0補完しない7分類、予想と実値、出典付きSVGと実データ検証を整理します。

read log →
SoundLoom

音のお絵かきを作る:実WAVから絵を測り直す設計

音のお絵かきの開発記録。描画を正弦波のPCMとWAVへ変換し、保存音声の周波数をGoertzel法で測って比較する仕組みを解説。音量・測定窓・量子化の限界と、編集・離脱時の古い結果を抑止する検証を整理します。

read log →
MazeLoom

宝探し迷路を作る:寄り道まで含めた最短ルートの探索

宝探し迷路の開発記録。通路を木として生成し、現在地と3つの宝の取得状態を組み合わせて最短ルートを探す仕組みを解説。問題コードの版固定、画面と解答付きPDFの一致、手数と印刷の検証を整理します。

read log →