Communitygithub.com

dotslashsimran/perspective-illusion

知覚をあやつるループする立体視ビデオを作成します。日本の錯覚アーティスト(例:@garments__)の手法を再現し、望遠レンズで平坦に圧縮されたシーンが遠近感のある奥行きへと変化する様子を表現します。

perspective-illusion とは?

このスキルは、三次元シーンを「望遠レンズで押しつぶされた平坦な視界」から「深い遠近感を持つ立体視」へと段階的にモーフィングするループ動画を作成するためのものです。日本の錯覚アーティストが手がけるような、視覚的なトリック(ドリーズーム効果やフラット→3D変換)を実現します。Three.jsを用いてシーンを構築し、Playwrightでレンダリング。キーフレーム間の補間は単調キュービックカーブで行われ、スムーズな速度変化を実現します。また、平坦な状態でのみオブジェクトの位置を変更することで、視聴者に気づかれずに配置を変える「チェイト」が可能です。テンプレートとして街並みやスーパーマーケットのシーンが用意されており、参照動画の解析結果をもとに数値パラメータを正確に合わせ込むこともサポートします。最終的な出力には、セルシェーディング風のカラー、インク線、陰影ハッチング、空・天井のベタ塗りを組み合わせたイラスト風の見た目が適用されます。

対応~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/dotslashsimran/simcraft/tree/HEAD/skills/perspective-illusion

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

遠近法錯覚(Perspective Illusion)

templates/ 以下のテンプレートは完全な動作シーンなので、こちらをベースに始めてください。

  • street.html:日本の街並み(ポール、コーン、横断歩道、赤い空)
  • market.html:日本のスーパーマーケット(通路、陳列棚、赤い買い物かご、照明列)

どちらもカメラリグ、タイムライン、イラストパスは共通です。異なるのはシーンセクションのみです。

セットアップ(プロジェクトフォルダごと)

mkdir -p ~/Movies/edits/<日付>-<名前>/stills && cd $_
printf '{"type":"module"}' > package.json && npm i [email protected] [email protected]
cp ~/simcraft/skills/perspective-illusion/templates/{street.html,render.mjs} .
node render.mjs street.html x --stills=0.2,1,2,4,6     # まずフレームを確認(stills/st_<t>.png)
node render.mjs street.html out.mp4                     # 7秒ループ、1920x1080、4サブフレームモーションブラー(約2.5分)

手法の4つのポイント

  1. シーンを一つの長い軸に沿って配置する(通りや通路を -z 方向に奥へ伸ばす)。ポールや柱は同じx座標に並べ、建物や背面の壁は終端に置く。400m先からの2°望遠でこれらはすべて一つの断面に圧縮される。並んだポールは重なって一本に見え、長い側壁はエッジだけになる。
  2. カメラを決して傾けたり回転させたりしない。 常に軸に沿って真正面を向き、水平を保つことで垂直線が垂直のままになる。「見下ろし」「見上げ」は、ティルトシフトレンズのようにレンズシフト(H、フレーム内の地平線位置)を使う。各ショットは {x, y(カメラの高さ), zf, W, fov, H, lay, cs} で定義される。
  3. ドリーズームとしてショット間をモーフィングする。 W は焦点面 zf でフレームに収まるよう固定され、fov が変化する。すべてのパラメータは全キーフレームを通じて単調なキュービックカーブで動作するため、速度が急変しない。
  4. 平坦な状態でこっそりと操作する。 コーンや買いかごなどのオブジェクトは、平坦なホールド中にのみカメラに向かって近づけたり遠ざけたりする。この動きは平坦な状態では目に見えない。これにより、一列に並んでいたものが斜めの配置(「前後が入れ替わる」)に変わる。また、平坦な状態ではオブジェクトを大きく描画することもできる(cs)。

参照動画に合わせる方法(目測ではなく測定を)

  • 各ショットのフレームを抽出する。その後、各ショットについて以下を測定する:
    • 消失点と地平線の位置(H が求まる)
    • 幅が既知の2つの物体の位置(x と W が求まる)
    • 横断歩道など、長さが既知の物体の手前側と奥側の位置(カメラの高さ y、距離、fov が求まる) 計算された数値はテンプレートのコメントに記載されている。
  • その動画のフレームからパレットをクラスタリングする(4フレームでk-means)。そして、その正確な色を使用する。
  • 変更のたびに、同一タイムスタンプでのフレームを参照動画と並べて比較する。

イラストパス(なぜレンダリングではなく描かれたように見えるか)

このページは3つのパスをレンダリングする:カラーパス(2トーンのセルシェーディング)、ビュー空間法線と深度、そして太陽光のみのシャドウマスク。最後のシェーダーが3つの処理を行う:

  • インク線:深度(2階差分。これにより、平坦な地面がエッジとして見えない)または法線が変化する場所に描画。線の太さはノイズで変化し、ルックアップ位置もわずかに揺れるため、定規で引いたような直線にはならない。深度しきい値は距離とともに大きくなる。
  • ハッチング:影の領域のみに適用。冷たい色調と細かい斜めストロークで、表面がエッジオンに近づくにつれて薄くなる。
  • 空(または天井):ジオメトリがない部分にベタ塗りで描画。

遭遇した問題と回避策

  • ワンライナー文に // コメントを追加すると scene.add(sun) が飲み込まれ、シャドウマスクが黒くなりすべてがハッチングされた。/* */ を使うか、新しい行に分けること。
  • 重なり合った同一平面の床が遠方でちらつく。床の部品は端と端で接するようにする。
  • 壁に対して浅い角度で当たる光は、斑点状の自己影を生じさせる。キーライトは正面から約45°に保ち、フルハイトの柱や天井の照明器具が影を落とさないようにする。
  • 生成画像や看板にテキストを入れてはいけない。看板は形状のみとする。
  • すべてのフルレンダリングの前にスチルを確認し、モーションチェック(vox-explainer の motion_check.py)を実行すること。

Individual skills in this repo

This repo contains 3 individual skills — each has its own dedicated page.

関連スキル