平らな絵を重ねるだけで、3Dなしの奥行きが出た。効いたのは明るさの段差、速さは『重いはずの処理』と比べて確かめた

平らな絵を重ねるだけで、3Dなしの奥行きが出た。効いたのは明るさの段差、速さは『重いはずの処理』と比べて確かめた AI活用術

課題

Xで、背景の風景が何枚かの絵を重ねたような作りで、カメラが動くと立体のように見えるアニメーションを見かけた。

個人で作っているゲームアプリでは、本格的な3Dのゲームはまだ作れない。だから、平らな絵を重ねるだけで奥行きが出せるなら、試してみたかった。

試す前に気になったのは2つ。

  • 平らな絵を重ねただけで、本当に立体っぽく見えるのか。見せるには何が要るのか
  • 層を何枚も重ねて動かして、重くならないのか

そこで、AIにブラウザで動く試作を作ってもらい、見た目と速さの両方を確かめた。速さのほうは、AIが最初に出した数字が測り方のずれで、結論が一度ひっくり返っている。

解決できるようにすること

  • 平らな絵を重ねて奥行きを出す仕組みと、見え方を左右した工夫の優先順位がわかる
  • AIが出してきた速さの数字(自分で測った数字も同じ)が、本当に描画を測っているのかを確かめる方法を持ち帰れる

先に結論

  • 仕組みは、アニメの撮影で昔からある「マルチプレーン」、2Dゲームでいう「視差スクロール」。絵を奥から手前へ層に分けて、カメラが動いたら手前の層ほど大きくずらす
  • いちばん効いたのは層ごとの明るさの段差。奥ほど明るくしないと、白いふちの線だけが浮いて線画に見えた。紙らしさは、切り口の白いふちと、ぼかさずにずらすだけの影で出した
  • 奥行きはカメラが動いたときにしか見えない。止まった画面では、ほぼ効果が出ない
  • 速さは制約にならなかった。8層の背景を1回描くのに0.13ミリ秒。1秒60コマで1コマに使える16.7ミリ秒の0.8%
  • その数字は、確実に重いはずの処理(影をぼかす描き方)を同じ方法で一緒に測って確かめた。こちらがちゃんと重く出たので、測り方が描画を捉えていると判断できた
  • この確かめ方を入れる前、AIは測り方を4回ずらしていた。一度は「8層だと約20ミリ秒かかり、1秒60コマに届かない」と逆の結論を記録している

なお、測ったのはMacのChromeで動かしたブラウザの試作だけ。スマホや、アプリを作るときの開発環境では測っていない。

この記事でわかること

  • 平らな絵を重ねて奥行きを出す仕組み(どの層をどれだけずらすか)
  • 紙を重ねたように見せる工夫と、効いた順番
  • 速さの数字を「重いはずの処理」と比べて確かめる方法と、あわせてやりたい確認

ここで、こう思う人もいるかもしれない。

「層を8枚も重ねて毎コマ描き直したら、さすがに重くなるのでは?」

AIも最初はそう結論していた。でも、確かめ方を整えて測り直すと、8層でも1コマの予算の1%に届かなかった。気をつけるべきだったのは層の数ではなく、影をぼかす描き方のほう。こちらは8層の背景の16倍重かった。

仕組み: 平らな絵を重ねて、手前ほど大きくずらす

調べてみると、手法自体は新しいものではなかった。アニメの撮影で昔から使われている「マルチプレーン」と同じで、2Dゲームでいう「視差スクロール」の背景。元の投稿はあとから探しても特定できなかったので、ここでは手法だけを扱う。

試作では、夕暮れの海の景色を8枚の層に分けた。一番奥が空、一番手前が岩。どれも平らな絵で、3Dの計算は使っていない。外部のファイルを1つも読み込まない、HTMLファイル1つで描いている。

ブラウザで動く試作の画面。夕暮れの空と月、灯台、何重にも重なった海の波が、白いふちの付いた紙を重ねたような見た目で描かれている。

動かし方のルールは1つだけ。カメラが動いたら、層ごとに決めた倍率でずらす。奥の層は少し、手前の層は大きく。

8枚の層を奥から手前へ並べ、カメラが10動いたときに各層がずれる量を矢印で示した図。空は1.2、灯台と崖は8.4、手前の岩は16.2ずれ、手前の層ほど矢印が長い。

試作のコードでは、倍率を「0.12+奥行き×1.5」で決めている。奥行きは、一番奥を0、一番手前を1とした値。空は×0.12、手前の岩は×1.62になる。

この差が、「近くのものほど速く流れて見える」という、電車の窓から外を見たときのような感覚を作る。

試作には「層を離して見る」というつまみがあって、上げると層がばらけて構造が見える。

試作の「層を離して見る」表示。8枚の層が斜めにずれて板のように並び、左上に層の名前と、奥行き(0.00〜1.00)、視差の倍率(×0.12〜×1.62)の一覧が表示されている。

こうして離してみると、1枚ずつは本当にただの平らな板。これがずれながら重なると、立体に見える。

大事な前提が1つある。奥行きは、カメラが動いたときにしか見えない。 ずれ方の差が奥行きの正体なので、カメラが止まった画面ではどの層もずれず、1枚の絵と変わらない。画面が止まったままのパズルゲームのような作りでは、ほぼ効果が出ない。

紙を重ねたように見せる工夫。いちばん効いたのは明るさの段差

紙を重ねた箱のように見せる決め手は、資料を読んだ段階では「切り口の白いふち」と「層の間に落ちる影」の2つ、とAIは整理していた。

ところが実際に作ると、その前に明るさでつまずいた。見た目は4回うまくいかなかった。

うまくいかなかったこと原因直し方
線画にしか見えない全部の層をほぼ同じ濃い紺にしていた。夜景だと明るさの差が作れない夕暮れに変えて、奥ほど明るくなるよう層ごとの明るさに段差をつけた
海が横線にしか見えないなだらかな起伏で描いていた半円を並べた形に変えた。切り絵の海は丸い山が並ぶ
影が見えない一番手前の層でも影のずれが約6px。1280×720の画面では小さすぎた手前の層ほど大きくずらし、一番手前で約13pxにした
層を離して見せても分からない海の層が画面幅いっぱいで、ずらしても端が画面の外に出ていた全体を縮めてからずらすようにした

いちばん効いたのは、1つ目の明るさの段差だった。どう違うのかを、同じ形の層で描き分けるとこうなる。

同じ形の層を2通りに塗り分けた模式図。左は全部の層がほぼ同じ暗い紺で、白いふちの線だけが目立って線画に見える。右は奥ほど明るく手前ほど暗い段差がついていて、層の前後がわかる。

左は、白いふちの線がいくら丁寧でも「線の絵」にしか見えない。右は同じ線が「紙の切り口」に見える。

記録にも、「いちばん効いたのは明度の階段」「層の分け方や影より先に、ここが決まらないと立体に見えない」「事前には分からなかった」と残っている。読んで分かることと、作って分かることは別、という典型だと思う。

残りの2つ、白いふちと影の効き方は、試作のつまみで切り替えて比べられる。下は、最初の画面から白いふちを0にして、影を消したもの。

同じ試作で、切り口の白いふちを0にして影を消した画面。層の境目の白い線と影がなくなり、色の違う平らな面が重なっているだけに見える。奥ほど明るい段差は残っている。
  • 切り口の白いふち: 層の形を太い白い線でふち取ってから塗る。線の外側半分が白く残って、紙を切った断面のように見える
  • 影: 同じ形を少しずらして、薄く塗るだけ。ぼかさない。試作のメモには「ぼかすと布のように見えて紙から離れる」とある。しかも後で測ると、ぼかした影は描くのが16倍重かった

最初の画面と見比べると、白いふちと影を消しても、層の前後は明るさの差でかなり読み取れる。白いふちと影が足しているのは「紙を切って重ねた」らしさのほう、というのが自分の見立て。順番としては、明るさの段差を先に決めて、ふちと影は後から足すのがよさそう。

ちなみに、紙の見せ方(ちぎれた縁・白いふち・ぼかさない影)は、AIがGitHubで公開されていた切り絵風の描き方のリポジトリを読んで確かめた。ただ、そのリポジトリにはライセンスの表示が無かった。ライセンスが無いコードは、公開されていても権利が全部留保されている扱いになる。なので、コードは流用せず、手法だけ読んで試作は一から書いた。AIに「これを参考にして」と渡す前に、ライセンスの表示は見ておきたいところ。

速さは制約にならなかった。8層で1コマの予算の0.8%

1秒60コマで動かすなら、1コマに使える時間は約16.7ミリ秒。ゲームなら、この中でキャラクターの動きや当たり判定もこなす必要がある。背景にはなるべく時間を使いたくない。

結果はこうなった(1280×720、10コアのMac、Chrome)。

構成1回描くのにかかった時間1コマに収まった回数
8層・毎コマ描き直す0.13ミリ秒256回
8層・層を画像として取っておく(キャッシュ)0.20ミリ秒128回
3層・毎コマ描き直す0.03ミリ秒未満512回
層ゼロ(仕上げの処理だけ)0.03ミリ秒未満512回
対照(影をぼかす)2.08ミリ秒4回

「1コマに収まった回数」は、1コマの間に背景を何回描いても、画面の書き換えが遅れなかったかを表す。

1コマの予算16.7ミリ秒を点線で示した横棒グラフ。8層の背景0.13ミリ秒とキャッシュありの0.20ミリ秒はほとんど見えないほど短く、影をぼかす対照は2.08ミリ秒。最初に誤って記録した約20ミリ秒は予算の線を超えている。

グラフにすると、8層の背景はほぼ線にしか見えない。層の数は気にしなくていい、という結果になった。

  • 層の数も、層が画面全体を覆う構図も、性能上の制約にならなかった
  • 避けるべきは影のぼかしだけ。8層の背景の16倍重い
  • 層を画像として取っておく工夫(キャッシュ)は、むしろ遅かった(0.20と0.13で約1.5倍)。試作の段階でAIは「ゲームに入れるなら必須」と書いていたけど、これは測る前に書いた見込みだった
  • 画面全体にかける紙の粒子の模様も、入れても外しても8層は0.13ミリ秒で、ほぼ費用ゼロ

ただ、この0.13ミリ秒にたどり着くまでに、数字は一度逆を向いていた。決め手になったのは、次の確かめ方。

数字を確かめる方法: 重いはずの処理を、同じ測り方で一緒に測る

ブラウザで絵を描く仕組み(Canvas)は、「描いて」という命令を受け取るとすぐ戻ってきて、実際に描くのは後回しにする。だから、描く処理の前後で時刻を取るだけでは、描画の時間は測れない。

最終的に使った測り方はこう。

  1. 何も描かないときの、画面の書き換えの間隔を測る(この環境では16.70ミリ秒)
  2. 1コマの間に背景をK回描く。Kは1、4、16、64、128、256、512と増やしていく
  3. 間隔が明らかに延びたところ(何も描かないときの1.6倍を超えたところ)で、そのときの間隔をKで割って、1回あたりの時間とする

画面の書き換えに合わせて処理を呼ぶ仕組み(requestAnimationFrame)を使っていて、描いた結果を読み出す処理は使っていない。

そして、対照を入れた。対照は、確実に重いと分かっている処理のこと。今回は、影をぼかす描き方(shadowBlurという設定)を使う構成にした。これは画像処理用の部品(GPU)で描いても確実に重い。

対照を使った測り方の図。上段は、何も描かないときの間隔を測る、1コマにK回描く、間隔が延びたKから1回あたりを出す、の3ステップ。下段左は実測で、対照が2.08ミリ秒と重く出たので測り方は信頼できる。下段右は想定で、対照もほぼ0と出たら測り方が壊れていると判断する。

考え方はシンプル。

  • 対照がちゃんと重く出る → 測り方は描画を捉えている。本番の構成の数字も信じていい
  • 対照も軽く出る → 測り方のほうが壊れている。本番の構成の数字も信じない

今回の対照は、16回描いたところで1コマに収まらなくなり、1回あたり2.08ミリ秒。ずらすだけの影を使う8層(0.13ミリ秒)の16倍になった。だから、8層の0.13ミリ秒も信じていい、と判断できた。

記録には、このあと「性能や副作用の有無を測るときは、壊れるはずのものを一緒に測る」と残っている。速さに限らず、「副作用が無いことを確かめた」のような報告にも使える考え方だと思う。

対照とあわせてやりたい4つの確認

  • 「何もしない」構成も測る: 何も描かないほうが遅いなら、中身ではなく測る順番や方法の問題
  • 負荷を何倍かにして、時間も同じくらい増えるかを見る: 比例しないなら、待つべきものを待っていない
  • タブが画面に表示されているかを確かめる: requestAnimationFrameは、表示されていないタブでは動かない。AIがブラウザを操作して測る場合は特に注意。最後は自分の画面で実行する
  • Canvasは前後の時刻だけでは測れない: 描き終わりを待たせるために、描いた結果の画素を読み出すと、描画の方式そのものが変わることがある

なぜ対照が要るのか。AIは測り方を4回ずらしていた

対照を入れる前、AIは測り方を4回ずらしていた。どれも描画が遅かったのではなく、測り方が描画を捉えていなかった。

回測り方何がずれていたか気付いたきっかけ
1描く処理の前後で時刻を取る描く命令を受け付けた時間しか測れず、0.00ミリ秒(1秒に無限のコマを描ける計算)値がありえない
2描いた結果の画素を読み出して、描き終わりを待たせる読み出しのせいで、描く方式がGPUから普通の計算部品(CPU)へ切り替わっていた。最初のひとまとまり以外は、全部CPUの数字層ゼロ(6.40ミリ秒)のほうが8層(0.32ミリ秒)より遅い、という順番でしか説明できない値
3画素を読み出さない、別の待たせ方描き終わりを待っていなかった負荷を8倍にすると時間は14.8倍。重いはずのぼかしのほうが速く出て、層ゼロは0.003ミリ秒
4実際の再生で測る(requestAnimationFrame)AIが操作していたブラウザのタブが画面に表示されておらず、測定が進まなかった進み具合を表示させて判明

いちばん危なかったのは2回目。値そのものがそれらしく見えていた。

AIはこの数字から、「キャッシュすると2〜3倍遅くなる」「8層で約20ミリ秒、720pで1秒60コマには届かない」と結論を出し、記録に残していた。層を減らす、層が画面全体を覆わない構図にする、といった制約の候補まで並べていた。

しかも2回目は、「毎コマ待つ」と「120コマまとめて描いて最後に1回だけ待つ」の2通りで測り、数字がそろっていた(層を画像として取っておく方式の1つで、19.40と19.30ミリ秒)。

ここで、こう思う人もいるかもしれない。

「2通りの方法で測って数字がそろっていたなら、それで十分なのでは?」

後から整理すると、2つの測り方は「読み出す回数」が違うだけで、どちらも画素の読み出しで待つ仕組みに頼っていた。同じずれの上に立っている2つの数字は、そろっても正しさの裏付けにならない。この整理は記録をもとにした自分なりの解釈だけど、対照が要る理由もここにある。

間違いに気付いたきっかけは、アプリ側に渡す制約を数字で決めるために、自分が「層を減らした場合」と「層が画面全体を覆わない構図の場合」も測るよう頼んだこと。その測定の中で、AIが表の2回目の行にある「層ゼロのほうが遅い」矛盾を拾った。

記録の時刻で見ると、最初の試作から、誤った結論の記録、測り直しまでは一晩のうち(約2時間半)。アプリ側への依頼は測り直しの後に出していて、誤った制約は渡らずに済んだ。

記録には、AI自身の振り返りとして「3回目までは対照を置いていなかった。置いていれば、1回目で気付けた」と残っている。1回目の測り方なら、重いはずの対照も0.00ミリ秒と出るので、その場でおかしいと分かる、という理屈になる。

一方で、表の右の列を見ると、4つのずれはそれぞれ別の手がかりで見つかっている。対照1つで全部を防げるとは限らないので、前の節の4つの確認とセットで使うのがいいと思う。

間違った結論の記録は、消していない。冒頭に「この数字は誤り。測り直した記録を正とする」という断りを付けて、「測り方を4回間違えた記録」として残してある。

絵を描く前に、分かったことを渡した

性能が問題にならないと分かったので、残る疑問は「手描きの絵でも立体に見えるか」になった。これはコードでは確かめられない。

そこで、アプリを開発している側のAI(以下、アプリ側のAI)に、層に分けた背景の絵を頼んだ。自分からは「この技術が最大限活きるゲームの案を先に考えて、そのゲームで使う絵にしてほしい」と注文を足した。見本用の絵ではなく、実際に使う画面として描いてもらうため。

依頼には、試作で分かったことを、絵を描く前に渡す形で入れた。

  • 奥行きは、カメラが動いたときにしか見えない
  • 層ごとの明るさに段差をつける。全部同じ明るさだと線画になる
  • 層の間の影にぼかしを使わない(実測で16倍重い)
  • 層の数と、層が画面全体を覆うかどうかは、性能上の制約にならない

アプリ側のAIは、試作の説明にあった「視差はカメラが動くときしか見えない」という制約から、出した3案ともカメラが流れ続ける横スクロールの画面にしていた。そこから自分が2つを選んだ。絵は、元になる1枚の絵を自分が画像生成AIで作り、アプリ側のAIが、色や明るさの違いを手がかりに、コードで7〜8枚の層に切り分けた。

試作に差し込んで確かめると、2つとも立体に見えた。「層を離して見る」表示でも、層がそれぞれ別の板として並んだ。

特に良かったのは、霧で奥ほど白くなる絵のほう。霧がかかると奥ほど明るくなるので、明るさの段差が絵の中で自然にできる。アプリ側のAIも案の段階でそう書いていた。渡した制約(層ごとの明るさの段差、切り口の白いふち、影やぼかしを描き込まないこと)は、画像生成への注文文(プロンプト)に織り込んでいた。

手描きの絵は、使うかどうかをまだ決めていない段階なので、この記事には載せていない。

まだ確かめていないこと

結論が逆になった分、範囲ははっきりさせておきたい。

  • 測ったのは、Mac(10コア)のChromeで動かしたブラウザの試作だけ。スマホでは測っていない
  • アプリを作るときの開発環境(Flutter)でも測っていない。必要な描画の機能はそろっているけど、数字は無い
  • 記録には「0.8%という余裕があるので、10〜30倍遅い端末でも成り立つ見込み」とあるけど、これは計算で、実測ではない
  • 手描きの絵のほうは、左右に余白が無いので大きくずらすと端が見える、隠れていた部分が単色で平らに見える、という課題が残っている
  • この背景を使ったゲームを作るかどうかは決めていない。今回はあくまで検証

こんな人に向いている

AIと一緒に、ゲームやWebの見た目を作っている個人開発者に向いている。

特に、3Dに手を出す前に、平らな絵で奥行きを出せないか試したい人。それから、AIが「測りました。〇〇ミリ秒です」と数字を出してきたとき、その数字をどこまで信じていいか迷う人には、確かめ方の1つとして使えるはず。

まとめ

平らな絵を層に分けて、カメラが動いたら手前ほど大きくずらす。これだけで、3Dなしでも奥行きは出た。見え方を決めたのは、層の分け方や影より先に、層ごとの明るさの段差だった。

速さは、8層でも1コマの予算の0.8%。この数字を信じていいと言えたのは、確実に重い処理を同じ測り方で一緒に測って、そちらがちゃんと重く出たから。対照が重く出れば、その測り方は信じていい。対照も軽く出るなら、測り方のほうが壊れている。

項目内容
結論平らな絵を重ねて手前ほど大きくずらすと、3Dなしでも奥行きが出た。いちばん効いたのは明るさの段差。速さは8層で0.13ミリ秒(1コマの予算の0.8%)で、制約にならなかった
教訓速さの数字が出たら、確実に重いはずの処理も同じ測り方で測る。重く出なければ、測り方を疑う。2つの測り方がそろっても、同じ仕組みに頼っていれば裏付けにならない
対象読者AIと一緒にゲームやWebの見た目を作っている個人開発者

同じ状況に陥ったときの回避策

  • 層は奥ほど明るくする。全部同じ明るさだと線画に見える
  • 影はぼかさず、同じ形をずらして薄く塗る。見た目も紙らしく、速さも保てる
  • カメラが動く画面で使う。止まった画面では奥行きが出ない
  • 速さを測るときは、確実に重い処理(今回なら影のぼかし)を同じ測り方で一緒に測る
  • 「何もしない」構成と、負荷を何倍かにした構成も測る
  • AIがブラウザを操作して測るときは、タブが画面に表示されているかを確かめる。最後は自分の画面で実行する
  • 公開されているコードを参考にするときは、先にライセンスの表示を見る
  • 間違った結論の記録は消さず、訂正の断りを付けて残す。後から同じ測り方をしそうになったときの目印になる

次に読むなら

AIが出してきた数字を確かめる考え方が分かったら、数字以外も含めて、AIの答えを使う前に確認する場所を一通り押さえておくと、同じ型の見落としを減らしやすい。


この記事は、筆者が個人で進めているゲームアプリ向けの技術検証の作業記録(2026年10月9日〜11日)を基に、独自調整したAIが下書きを作成し、筆者が事実確認・編集を行った上で公開しています。背景の層の元になった1枚の絵は画像生成AIで作成し、本文の説明図は記録をもとにAIが作成しています。

トップへ戻る
タイトルとURLをコピーしました