AI Dev Lab
TypeForge

TypeForge ができるまで — ジェネレーター thesis 1本目を Three.js で開く

データ可視化 (wiki-orbit) に続く ラボ 19本目で ジェネレーター thesis を初投入。 Three.js を npm 新規導入し TextGeometry + 5 種材質 + OrbitControls + PNG export を組んだ設計記録。 §6.1 適用、 鍛冶 / forge motif の warm-dark industrial visual。

·decision改善·stage公開中

TypeForge ができるまで — ジェネレーター thesis 1本目を Three.js で開く

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

なぜこの形にしたか — thesis の幅を広げる

直近 5本の SHIP は (wiki-orbit: データ可視化 / fate-num: 占い / roof-fund: 計算ツール / coin-stack: 計算ツール / pitch-flip: on-device ML)。 §3.1 の 3連続 NO-GO 条件には触れていないが、 charter §優先する方向 8 thesis 枠のうち ジェネレーター はラボにゼロ。 今のうちに 「ジェネレーター系もできる」 を布石として置く。

候補を比較した:

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

選んだ理由:

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

visual direction — §6.1 Visual Audit 4本目の適用

直近 5本の visual を書き出す:

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 文字を鍛える」 から motif を引くと、 自然に 鍛冶屋 / 鋳造所 (forge / foundry) に行き着く。 既存にこの motif は無い。

採用 3 要素:

  • palette: charcoal #1a1817 + obsidian #0a0a09 + ember orange #ff6b35 + steel gray #a0a4a8 + brass #c9a445
  • 18本柱の中で 唯一の warm-dark industrial palette。 既存の暖色系 (pitch-flip synthwave / coin-stack gold / py-pad yellow-orange) と並べても明確に違う (synthwave magenta + cyan vs ember-only / py-pad は背景が deep navy で全く違う)
  • motif: 鍛冶屋 / 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 に振った

§6.1 NO-GO の 「シェル主色をサービス内側主アクセントに使う」 は OK (シェル mint cyan、 こちらは ember orange、 競合しない)。

技術スタック

Three.js (npm)

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 材質

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 プロパティで自発光。

ライティング

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

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 アイコン / バナー で使いやすいサイズ。

やっていない / これからの IMPROVE

  • 日本語フォント (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 シェア後の再現
  • 複数行レイアウト / グラデーション材質 / 木目背景

次の SHIP は何 thesis に振るか

Thesis Audit:

type-forge — ジェネレーター (NEW)
wiki-orbit — データ可視化
fate-num — 占い・診断
roof-fund — 計算ツール
coin-stack — 計算ツール

直近 5本で 5 thesis 混在。 3連続 NO-GO ルールから余裕あり。 残り未着手枠は シミュレーター・ロールプレイ / インタラクティブ学習 / server-side AI (許可必要)。 シミュレーターは incident-sim が既にあるので別領域 (面接シミュ オフライン / 物理エンジン サンドボックス) を狙う。 インタラクティブ学習は 絶対音感トレーナー / 暗算 / タイピング / 国旗クイズ あたり。

[ ./next_action ]

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

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

[ ./related_logs ]

関連する開発ログ

all logs →
ToonCast

ToonCast ができるまで — AnimeGANv2 をブラウザで動かす

AnimeGANv2 の小さな ONNX (約9MB) を onnxruntime-web (単一スレッド WASM=COOP/COEP不要、 color-revive で承認済みライブラリの再利用) で実行。 512x512・[-1,1] 正規化で推論し、 結果を元解像度に戻して表示する設計記録。 写真は端末内処理。

read log →
ColorRevive

ColorRevive ができるまで — onnxruntime-web で白黒写真をカラー化

DeOldify の量子化 ONNX を onnxruntime-web (CDN side-load・単一スレッド WASM=COOP/COEP不要) で実行。 256x256 でモデル推論し、 輝度は元写真・色だけ AI を YCbCr で再合成して輪郭を保つ設計記録。 写真は端末内処理。

read log →
PhotoTwin

PhotoTwin ができるまで — CLIP画像埋め込みで似た写真を見つける

CLIP (Xenova/clip-vit-base-patch32) の image-feature-extraction を transformers.js の CDN ESM で side-load し、 各写真を正規化ベクトル化。 cosine 類似度で重複・似た写真をブラウザ内で検出する設計記録 (新ライブラリ追加なし=what-cam と同じ CLIP の再利用)。

read log →
AkinFind

AkinFind ができるまで — 文章embeddingsで意味検索をブラウザ内に

多言語の文章埋め込みモデル (Xenova/multilingual-e5-small) を transformers.js の CDN ESM で side-load し、 各文を正規化ベクトル化。 cosine 類似度で意味検索と似ている文ペア検出を全て端末内で行う設計記録。

read log →
WhatCam

WhatCam ができるまで — CLIP のゼロショット画像分類をブラウザで動かす

CLIP (Xenova/clip-vit-base-patch32) を transformers.js の CDN ESM で side-load し、 写真と候補ラベルの近さをブラウザ内で計算。 日本語ラベルを英語プロンプトに変換し、 図鑑と自由入力の両モードで「これ何?」を判定する設計記録。

read log →
DepthCast

DepthCast ができるまで — 1枚の写真をAIの深度推定で立体にする

Depth Anything (transformers.js) を CDN ESM で side-load し、 1枚の写真から深度マップを推定。 WebGL2 フラグメントシェーダで深度に比例した視差 (iterative backward parallax) を作り、 赤青アナグリフ / WebM 書き出しまで端末内で完結させた設計記録。

read log →