build-wireframe-scan-reveal について
一時的なワイヤーフレームスキャンで、3Dオブジェクトの実体表面を表示するデザインスキルです。シーンの導入演出向けに、ワールド空間の波面でワイヤーケージとソリッドメッシュを連動させます。
主な機能
- 01単一のスキャンでワイヤーと実体を連動
- 02両方の表現をワールド空間に配置
- 03遅延を伴う不均一なスキャン前線をアニメーション
- 04一時的なケージを除去してリソース解放
- 05リプレイと視差軽減状態に対応
活用シーン
- 01ワイヤーフレームを先行させて3D形状を表示
- 02スケールされたシーングループ間でスキャンを同期
- 03リプレイを設けつつ視差軽減用の静止画を維持
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ mengto/ skills --skill build-wireframe-scan-revealインストール後、Claude Code で/build-wireframe-scan-revealを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
agents/openai.yamldemo/index.htmlPROMPT.md詳細
ワイヤーフレームのスキャンリビールを作成する
1 つのワールド空間の波面で、2 つの表現を制御します。先端ではトポロジーを描画し、その後ろではソリッドを維持し、最後に一時的なケージを取り除きます。ワイヤーフレームがページの恒久的なビジュアル表現なら technical-wireframe-info-layout を、制御するのが 3D の波ではなく DOM のスクロールなら animation-on-scroll を使います。
inner-green-3d.html から抽出した手法です。カードやテキストを通り抜けながら、プロシージャルな苔の根が成長するサーベイパルスを、円形のマスクに見えないようにする必要がありました。
2 つの表現を組み合わせる
同じソースジオメトリから、ソリッドメッシュと一時的な LineSegments ケージを作成します。両方のマテリアルで uScanOrigin、uScanRadius、時間を共有します。両方をワールド空間に保ちます。グループをスケーリングまたはネストするとローカル空間での距離が変わり、2 つの波面がずれてしまいます。
先端より遅れてソリッドを破棄し、ケージが先に見えるようにします。
uniform vec3 uScanOrigin;
uniform float uScanRadius;
uniform float uScanEnabled;
bool unscanned(vec3 worldPosition, float lag) {
if (uScanEnabled < 0.5) return false;
float wobble =
sin(worldPosition.y * 0.011 + worldPosition.x * 0.007) * 36.0
+ sin(worldPosition.z * 0.021 + worldPosition.y * 0.013) * 17.0;
return distance(worldPosition, uScanOrigin)
> uScanRadius - lag + wobble;
}
// In the solid fragment shader:
if (unscanned(vWorldPosition, 520.0)) discard;
シルエットの外側、通常は左下に 1 つの原点を置きます。中央に置くとローディングリングのように見えます。2 つの長いサイン項は維持します。完全な円形の波面はクリップパスのように見え、高周波ノイズはエッジをきらつかせます。
ケージを波面に追従させる
各ラインフラグメントと同じ半径との距離を測定します。
float distanceFromOrigin = distance(vWorldPosition, uScanOrigin);
float rim = exp(-pow((distanceFromOrigin - uScanRadius) / 135.0, 2.0));
float trail = smoothstep(uScanRadius, uScanRadius - 950.0, distanceFromOrigin);
float alpha = (rim * 1.60 + trail * 0.34) * uWireOpacity;
加算ブレンディング、transparent: true、depthWrite: false、シーンのアクセントカラーを淡くした色を使います。オブジェクト越しにケージを見せる必要がない限り、深度テストは有効にしておきます。深度テストを無効にすると、密なトポロジーの背面が露出し、明るく判読しにくい球体になります。
1 つの制御役をアニメーションさせる
実装済みのタイミングを出発点として使います。
| パラメーター | デフォルト | 防止できる問題 |
|---|---|---|
| duration | 3.4 s | リビールが速すぎるとフラッシュのように見えます |
| 半径のイージング | 1 - (1 - t)^1.35 | 線形の移動では、視覚的に遠い角の手前で停滞します |
| ソリッドの遅延 | 520 ワールド単位 | 遅延がないと、ワイヤーと塗りつぶしが一度にワイプされます |
| リムの幅 | 135 単位 | リムが狭いとエイリアスが発生し、広いと霧のようになります |
| ワイヤーの軌跡 | 950 単位 | 軌跡がないと、トポロジーを読み取る前に隠れてしまいます |
| ワイヤーのフェード | smoothstep(.72, 1, t) | ケージが残り続けると、完成した表面と競合します |
| 半径の到達距離 | シーンの対角線 × 1.3 + 900 | 完了後も遠い角がクリップされたままになります |
タイムラインの最初の 6% でケージを表示し、最後の 28% でフェードさせます。
const e = Math.min(1, elapsed / 3.4);
scanRadius.value = easeOutPow(e) * maxRadius;
wireOpacity.value = Math.min(1, e / 0.06) * (1 - smoothstep(0.72, 1, e));
完了時には破棄処理の分岐を無効にし、ケージを取り除いて、そのジオメトリとマテリアルを破棄します。透明度で隠すだけでは、ページの残りの表示期間中も重複したジオメトリとシェーダー処理が動き続けます。
スキャンを配置してサイズを調整する
レイアウトが確定し、親の行列が更新された後に maxRadius を計算します。ResizeObserver を使い、ルートのサイズが 0 の場合を処理し、カメラの投影を更新してから、原点と最遠到達距離を再計算します。フォントやレイアウトが確定する前に一度だけ測定すると、最後の角が表示されないままになります。
デモでは、見覚えのあるシーンを維持します。グレーグリーンの背景、下部の光だまり、白いエディトリアル風のテキスト、淡いカード、根の形をしたフォームを使います。こうした演出はデモに属します。再利用できる手法は、2 つの表現と共有する制御役だけです。
モーションとライフサイクルに配慮する
prefers-reduced-motion: reduceの場合は、ケージとソリッドの両方を表示した、半径約 62% のデザイン済み診断用静止画をレンダリングします。リプレイコントロールで静止画を再構成し、状態を通知します。シーンを隠してはいけません。dtを 1/30 秒に制限します。非表示タブや画面外のセクションが再開したら、時間の基準をリセットします。document.hiddenの場合や、IntersectionObserverでセクションが画面外と判定された場合は一時停止します。- デバイスのピクセル比を 2 以下に制限します。
- リプレイは、フォーカスが見える実際のボタンと
aria-liveステータスで提供します。キャンバスが装飾目的の場合は、aria-hiddenを設定します。 - ティアダウン時には、フレームをキャンセルし、オブザーバーを切断し、リスナーを削除して、ジオメトリ、マテリアル、テクスチャ、レンダラーを破棄します。
コストを正直に伝える
一時的な第2の表現と、その線が覆う範囲が実際のコストです。半径の計算より、トポロジーの密度とオーバードローのほうが重要です。ワイヤーケージは導入時にのみ作成し、シルエットを保てる最も粗いエッジグラフを使い、スキャンが終わったらすぐに破棄してください。ケージの描画パスの前後で GPU のフレーム時間を計測せずに、パフォーマンスが向上すると主張しないでください。
検証
- 1440×900 で、開始時、中間時、完了時の状態を元のものと比較します。
- スケーリングされた子グループも含め、あらゆる場所でケージがソリッドより先行することを確認します。
- 完了まで早送りし、クリッピングされた島状の部分が残っていないことを確認します。
- 2 回再生し、フレームループとケージがそれぞれ 1 つだけ残ることを確認します。
- スキャン中に 390×844 と 1440×900 へサイズ変更します。
- Tab キーで再生ボタンに移動し、フォーカスが表示され、ステータスが更新されることを確認します。
?reduced=1またはシステムの視差効果を減らす設定をテストします。合成済みの静止画が表示され、半径が進まないことを確認します。- タブを非表示にしてから再表示し、ビューポートから出て再び入ります。時間が飛ばないことを確認します。
- コンソールに問題がなく、完了後にケージのリソースが破棄されていることを確認します。
動作確認には demo/index.html を使い、再作成またはリミックスするには demo/PROMPT.md を使ってください。