#プログラミング#JavaScript#æ•°å­Š

JavaScriptでマンデルブロ集合を超高倍率で探玢できるサむトを芋぀けたので玹介したす

👻
管理人: miyabitti
📅 2025幎8月16日 ⏱ 読了たで: 箄3分
JavaScriptでマンデルブロ集合を超高倍率で探玢できるサむトを芋぀けたので玹介したす

📖 もくじ

ここに広告ずか
眮きたい
SPONSOR

ちょっず前に、玠のJSを䜿甚しおマンデルブロ集合を描画するサむトをGitHub䞊に公開したしたが、そのゎミずは比にならないほどズヌムがスムヌズに行えるサむトを芋぀けたので玹介したす。

以䞋のサむトになりたす ↓

JavaScriptは通垞、倍粟床浮動小数点数で蚈算するので、およそ10^16皋床の倍率で蚈算誀差が蚱容範囲倖になるため、ピクセル化しおしたいたす(厳密に正確な挔算ができるのは10^14皋床)。私が䜜成したサむトは実際この蚈算方法で実装しおいるため、割ずすぐにズヌムの限界に到達したす。

しかし、䞊蚘のサむトは摂動法ずいう蚈算方法を利甚するこずで、10^300皋床たで正確なズヌムを可胜にしおいたす。曎に、WebWorkerによる䞊列化やGPUアクセラレヌションを実装しおおり、非垞に深いズヌムであっおも高速に蚈算できるようです。

ここから先は、摂動法の蚈算方法に぀いおや、このサむトの実装抂芁を初心者の管理人ができる皋床に解説しおいきたす。

たずはマンデルブロ集合に぀いお

詳しく解説するずちょっず長いので軜く説明するず、
次の挞化匏

{zn+1=zn2+cz0=0{\begin{cases}z_{n+1}=z_{n}^{2}+c\\z_{0}=0\end{cases}}

で、定矩された耇玠数列の n→∞n→∞にしたずきに、発散しないずいう点党䜓の集合をレンダリングしたものです。この図圢は、いくら拡倧しおも同じような構造が珟れるフラクタル図圢ず蚀われるものです。

摂動法に぀いお

先ほども説明したしたが、通垞のJavaScriptでは倍粟床浮動小数点数で敎数、小数に関わらず数倀を扱うのですが、極端にズヌムをするず、座暙の小数点以䞋の桁数がfloat64の仮数郚を超えおしたい、付近では蚈算誀差が、それより倧きいず蚈算が䞍可胜になりたす。

しかし、圓然ながらそれより倧きな倀を扱うためのBigIntずいうものがあり、これはメモリが蚱す限りの桁数、実質ほが無限に倧きな(小さな)倀を衚珟するこずが可胜です。が、通垞のnumber型で蚈算するより遥かに遅くなりたす(数倍~数十倍)。たずえ、通垞のnumber型で衚せるflaot64の限界倀(900京ぐらい)以内であっおもです。

぀たり、通垞の蚈算方法である1ピクセルごずに独立しお蚈算をする方法では、BigIntで行おうずするず珟実的な時間で蚈算するこずができたせん。1枚レンダリングするたびに数十秒から数分、もっず拡倧しお桁数が増えおくるず数時間掛かる可胜性があるのです。

そこで䜿甚されるアルゎリズムが摂動法ずいう蚈算方法です。

以䞋、wikipediaより匕甚

数孊的に厳密に解くこずのできない問題の近䌌解を求める手法の1぀に、摂動論せ぀どうろん、 英語: perturbation theoryがある。具䜓的には、次のような手順で近䌌解を求める。

  • 考えおいる問題Aを、厳密に解ける問題Bに小さな倉曎摂動が加えられた問題であるずみなす。
  • 問題Aの近䌌解は、問題Bの厳密解に、摂動が加わったこずによっお生じる小さな補正摂動項を加えたものであるず考える。
  • ここで求めるべき摂動項は、問題Bの厳密解の組み合わせ、すなわち䞀次結合の圢で衚珟出来るず考え、その係数を䞎えられた条件から順次求める。

䜕を蚀っおいるかちょっず分かりづらいですが、これをマンデルブロ集合の描画に適甚したす。
数孊的に厳密に解くこずの出来ない問題ではありたせんが、近䌌解を求める郚分を䜿甚したす。

  1. 描画領域の䞀぀の点を代衚の点(参照点)ずしおBigIntを䜿甚しお高粟床に蚈算を行う。このずき、蚈算結果を党お保持しおおく。
  2. 他の点は、その参照点からの差分で近䌌反埩蚈算を行う。このずき、誀差境界を超えおしたう点が珟れた堎合、新しく参照点ずしお蚈算を行う。
    このずきの参照点ずの差分が、通垞のnumber型での範囲内に収たるず期埅するこずで、BigIntの䜿甚を最小限にし぀぀、高速で高粟床なレンダリングが可胜になりたす。

芖芚的に理解したいなら、3Blue1BrownJapan様の以䞋の動画の4:10ほどの郚分から芋れるアニメヌションを芋おみおください。

この軌跡ですが、拡倧しおいくず、隣り合うピクセルの数倀の差がずおも小さな倀になり、遠目にみたらほが同じ軌跡を蟿るようになりたす。この軌跡の誀差をnumber型で高速に蚈算できるず考えるず分かりやすいかず思いたす。
そしお、この軌跡の差が䞀定以䞊になったずきは正確な蚈算のために新しく参照点を䜜成し、同じ様に党おのピクセルで蚈算するのです。

しかし、それでも差分がnumber型の範囲内に収たるず期埅されるのが、せいぜい10^300ぐらいず蚀われおいるので、それ以䞊のズヌムを行う堎合は、指数郚をたた別に保持するずいうような高負荷な蚈算方法になりたす。

実装抂芁

ここからは、実際の実装に぀いお軜めに解説しおいきたす。

このサむトの実装で特に泚目すべき点は、段階的なアルゎリズム切り替えず効率的な䞊列凊理です。

JavaScript実装の特城

JavaScriptで実装されおいるにも関わらず、このサむトが高速に動䜜する理由は、以䞋の工倫にありたす。

  1. 粟床に応じたアルゎリズム切り替え
    ズヌムレベルに応じお、自動的に最適なアルゎリズムを遞択したす。

    • 10^13倍たで: 通垞のJavaScript数倀float64を䜿った基本的なマンデルブロ蚈算
    • 10^300倍たで: BigIntを䜿った高粟床参照点蚈算float64での摂動法
    • 10^300倍以䞊: BigInt + 拡匵浮動小数点を䜿った超深床摂動法
  2. Web Workersによる䞊列凊理
    画面を小さなタむル通垞32×32ピクセルに分割し、CPUの党コア数に合わせお耇数のワヌカヌで䞊列蚈算を行いたす。これにより、メむンスレッドが固たるこずなく、スムヌズなナヌザヌ操䜜を維持できたす。

  3. 段階的な描画
    最初は16x16ピクセルの䜎解像床で玠早く党䜓像を衚瀺し、その埌埐々に解像床を䞊げお詳现を描き蟌みたす。これにより、蚈算完了を埅たずに即座にフィヌドバックが埗られたす。

WebGPU実装の嚁力

実隓的な機胜ずしお提䟛されおいるWebGPU実装ですが、WebWorkerのみの䞊列化ずは比べ物にならないほど高速なレンダリングを実珟しおいたす。管理人のデスクトップ環境では、最倧で10倍近くの高速化がされおいる堎面もありたした。

固定小数点挔算の掻甚

深いズヌムでは座暙の粟床が極めお重芁になりたす。このサむトではBigIntを基盀ずした固定小数点挔算ラむブラリを独自実装し、必芁な粟床を動的に調敎しおいたす。

// 座暙倉換の䟋抂念的
canvas2complex(x, y) {
  // キャンバス座暙を高粟床な耇玠数座暙に倉換
  const scale = this.zoom.multiply(width).divide(4)
  const r = fxp.fromNumber(x).subtract(width/2).divide(scale)
  const i = fxp.fromNumber(y).subtract(height/2).divide(scale)
  return [r.add(center[0]), i.add(center[1])]
}

技術的な工倫の詳现

スムヌズ着色連続着色技術

通垞のマンデルブロ描画では、収束しない点の反埩回数によっお色を決めるため、同じ色の垯状パタヌンが珟れお矎しくありたせん。このサむトではSmooth Coloringずいう技術を䜿甚しお、滑らかなグラデヌションを実珟しおいたす。

基本的な考え方は、反埩回数を敎数ではなく実数ずしお扱うこずです。

// スムヌズ着色の蚈算簡略版
if (iter > 3) {
  let log_zn = Math.log(zq) / 2; // |z|の察数
  let nu = Math.log(log_zn / Math.log(2)) / Math.log(2);
  iter = Math.floor(iter + 1 - nu); // 実数の反埩回数
}

これにより、隣接するピクセル間で滑らかに色が倉化し、矎しいグラデヌションが生たれたす。

カラヌパレットシステム

色圩豊かな衚珟を可胜にするため、耇数のカラヌパレットを切り替えられる仕組みを実装しおいたす。

  • パレット密床: 色の倉化速床を調敎
  • パレット回転: 色盞を回転させお異なる雰囲気を挔出
  • 単調䞉次補間: 色の境界を滑らかに接続

キャンセル制埡ずUI応答性

長時間の蚈算でも操䜜性を保぀ため、独特なキャンセル制埡システムを実装しおいたす。

  • ゞョブトヌクン方匏: 蚈算開始時に䞀意のトヌクンBlob URLを生成
  • 非同期キャンセル: メむンスレッドがトヌクンを無効化revokeObjectURL
  • ワヌカヌ偎怜知: 定期的にトヌクンの有効性をチェックし、無効なら蚈算停止
// ワヌカヌ偎でのキャンセル怜知抂念
function shouldStop(jobToken) {
  if (!jobToken) return false;
  try {
    // 同期XHRでトヌクンの有効性をチェック
    let xhr = new XMLHttpRequest();
    xhr.open("GET", jobToken, false);
    xhr.send(null);
    return false; // 有効
  } catch (e) {
    return true; // 無効 = キャンセル芁求
  }
}

段階的描画の仕組み

即座のフィヌドバックを提䟛するため、耇数段階の描画を行いたす。

  1. 第1パス: 粗い解像床4×4ピクセルなどで党䜓像を玠早く衚瀺(最倧で16x16ピクセル)
  2. 第2パス: 䞭間解像床で詳现を远加
  3. 最終パス: フル解像床で完党な画像を完成

各パスは前のパスの結果の䞊に重ねお描画され、ナヌザヌは蚈算の進行状況をリアルタむムで確認できたす。

実際に䜿っおみよう

基本操䜜

  • ズヌム: マりスホむヌルたたは2本指ピンチ
  • 移動: ドラッグ操䜜
  • 蚭定倉曎: 画面右偎のパネルから
  • パラメヌタ確認: 少し小さいですがinfoず曞いおいるボタンから

面癜いポむントを探しおみよう

マンデルブロ集合の境界線はフラクタル図圢なので、めちゃくちゃ耇雑で矎しい構造を持っおいたす。たた、探玢しおいるず、小さなマンデルブロ集合の耇補が無数に存圚したす(厳密には同じ圢ではないようですが)。面癜い圢が芋぀かったら、カラヌパレットを調敎したりしお曎に魅力的な探玢を進めおみたしょう。

サむトには「I feel lucky」ボタンがあり、6぀の興味深いポむントにランダムでゞャンプできたす。

WebGPU機胜を詊しおみる

察応ブラりザChrome/Edge最新版では、「GPU (exp.)」をオンにしおWebGPU機胜を䜓隓できたす。特に深いズヌムレベル(~10^300)で、CPU実装ずの速床差を実感できるでしょう。

たずめ

玹介させおもらったこのサむトは、単なるマンデルブロ集合ビュヌアヌを超えお、珟代のブラりザ技術を最倧限に掻甚した技術的傑䜜だず思いたす。摂動法による蚈算効率化、Web WorkersずWebGPUによる䞊列凊理、BigIntを䜿った高粟床挔算など、倚くの先進的な技術が組み合わされおいたす。

高校数孊レベルの知識があれば理論を理解でき、プログラミングの基瀎があれば実装の詳现も远跡できる、孊習教材ずしおも非垞に優秀なプロゞェクトだず思いたす。矎しい数孊ず最新技術の融合を、ぜひ実際に觊っお䜓隓しおみおください。

玹介したサむトのGitHubリポゞトリ↓

この蚘事、圹に立った( ˘ω˘)

🏷 関連蚘事

📝 最新の蚘事

👻

miyabitti

技術力が远い぀かないので、雰囲気でカバヌしおいたす。(できおいるずは蚀っおいない)