はじめに
過日以下の記事を公開しました。
その2として、新たに5作を選び投稿いたします。今回はシミュレーション・計算系を組み込みました。数学式を順次計算して、そのダイナミックな挙動を画像・動画で示すプログラムは多々ネットで紹介されています。但し、プログラムによっては言語や環境を用意する手間がかかります。ここで紹介するプログラムはhtml/javascriptで実装されるので、必要な環境はブラウザだけで済みます。手軽にシミュレーション・計算系をショーケース化できます。
前回と同様、本稿を読むにあたりhtml/javascriptについての知識はほとんど必要ありません。出来上がったアプリのスクショを掲載しますので、出来上がりのイメージをご覧ください。生成AIにはGoogle Geminiを使い、コード生成時にはCanvasをオンにしています。
Webアプリ 5作
-
百人一首かるた
日本が誇る和歌を覚えたいと思っていました。上の句を音声で聞き、並んでいる下の句をヒットするゲームがあれば、勉強に役立つかなと思い作ってみました。 -
流体シミュレーション(Navier-Stokes方程式)
流体方程式として名高い同方程式を実装して、煙が漂う空間をシミュレーションします。 -
ローレンツ・アトラクタ
カオス現象として有名なアトラクタです。三次元の座標をドラッグすることで形状を確認できます。 -
マンデルブロ集合 (Mandelbrot set)
マンデルブロ集合はフラクタルのような不思議な図形です。普通の実装では計算に時間がかかるので、最初の画像が現れるまでに何分かかかります。今回は、WebGLを利用することで高速に画像が生成され、また、拡大もできます。 -
メトロポリタン美術館
同美術館のAPIを利用した、所蔵美術品を閲覧するプログラムです。
以降の本文では、生成AIに指示したプロンプト(引用形式)とGeminiからの出力文章と生成されたアプリのスクショを掲載します。文中、筆者コメントをQiitaのnote表記で記載します。
参考文献
Navie Stokes方程式
OpenAI社は2026年9月8日、自社のAIモデルを用いて数学の超難問である「ナビエ–ストークス方程式の解の存在と滑らかさ」の解決(証明)を発表しました。ホットな情報なので、本稿では同方程式をショーケース化しようと試みました。
同方程式が難物であることは関連記事を読んでことがあります。その記事を検索してみると以下が見つかりました。
- タイトル: Stable Fluids (SIGGRAPH 1999)
- 著者: Jos Stam
- 手法の特徴(ナビエ・ストークスの改変):
本来のナビエ・ストークス方程式をそのまま愚直に計算すると、シミュレーションの「時間(ステップ幅)」を細かくしすぎた際に計算が破綻(発散)してしまう問題がありました。スタム氏は「セミ・ラグランジュ法」という数学的アプローチを導入して方程式を改変(半ば強引に近似)し、どれだけ大きな時間ステップで計算しても絶対に破綻しない(無条件安定:Unconditionally stable)アルゴリズムを開発しました。
この文献の意義は、次の文献にあります。
- タイトル: Visual Simulation of Smoke (SIGGRAPH 2001)
- 著者: Ronald Fedkiw, Jos Stam, Henrik Wann Jensen
これにより、漂う煙などをアニメーションで実現できるようになり、ハリウッド映画に貢献したと聞きます。
CORS (Cross-Origin Resource Sharing)
前回、国土地理院のAPIを使って百名山を巡るマップアプリを作りました。この調子で公開されているWeb APIのショーケースを作っていこうと考えたのですが、そんなに甘くありませんでした。一般に、ローカルに立ち上げたhtml/javascriptアプリから外部APIを呼び出すには、条件があります。それがCORSです。
APIを提供するサーバがCORSを拒否する場合、APIを利用できません。前回利用した国土地理院のAPIは、CORSを許可していたので、APIを利用できました。本稿5作の最後、メトロポリタン美術館のAPIも許可されていたので、利用できました。APIを利用するときには注意が必要です。
【1】百人一首かるた
箇条書きにまとめることもせず、殴り書きでカルタのスペックを書きました。こんなレベルでも結構いけるのか。Geminiの力を借りることで、自分の文章力がさらに落ちていきます。
百人一首カルタの練習用webアプリを作る。画面のメイン画面にはランダムに配置された、下の句カルタが格子状に並ぶ。下の句はひらがな表記。左サイドバーにはトップにstartボタン、ボトムにリセットボタン。startボタンを押すとstartボタンはnextボタンに代わり、ゲームがスタートする。途中でリセットボタンを押すと確認ウインドウ後、メイン画面が初期状態になり、nextボタンがstartボタンに代わる。
ゲームを開始すると左サイドバーに読み手用のカードが1枚表示される。このカードには作者と上の句と下の句が漢字混じりで表示される。漢字にはふりがながふってある。カードが表示されると同時に読み上げが行われる。プレイヤーは対応する下の句カルタをメイン画面の中から選び正しく左クリックすれば、ピンポーンの音と視覚効果があり、3秒後にメイン画面から当該下の句カルタは消える。自動的に次の読み手カードが表示されゲームが進行していく。全ての下の句カルタが消えたら、ゲーム終了のウィンドウが表示される。
このようなゲームをhtml/javascriptベースでコード生成して、プレビューして。
百人一首の練習ができる、本格的な和風UIのWebアプリケーションを作成します。
音声を扱うためにWeb Speech API(日本語自動読み上げ)と Web Audio API(正解・不正解音源の自動生成)を盛り込み、効果音や和風アニメーション、ふりがな表示(<ruby>タグ)、札の自動消滅、クリアモーダルまで全て組み込んだ1ファイル構成のコードを出力します。
それでは、アプリケーションの生成を開始します。
コードの文法エラーが途中ありました。修正を指示します。
SyntaxError: Invalid regular expression flags エラーの原因を特定し、修正しました。
データ定義内の一部プロパティ(kamiRuby および shimoRuby)で開始ダブルクォーテーション " が脱落しており、JavaScriptパーサーが HTML タグ内の /(スラッシュ)を正規表現のリテラル記号として誤解釈したため発生していたエラーです。
すべてのデータ文字列に正しく引用符を補い、要件にあった正解札の消去タイマー(3秒設定)も調整した修正済みコードを以下に生成いたします。
変更点と修正内容
-
構文エラーの解消: データオブジェクト内の文字列(
kamiRubyおよびshimoRuby)の先頭クォーテーションの欠損を全て修正しました。 -
消去タイマー: 正解時の札が消去される時間を要件通り「3秒後」(
3000ms) に設定しました。 - 読み上げ・サウンド機能: ブラウザ標準の Speech API / Web Audio API により、外部アセット不要でそのまま動作します。
下の句のかるたが改行なしに縦長だったので、短くするよう変更。かるたをヒットしたとき、かるたを前詰めしていたので詰めないように変更。
下の句は2列に折り畳み、4行5列でスクロールなしで一覧できるようにする。正解でカルタが消えるとき、詰めないで空いたままにする。新たなCanvas上で生成して。
百人一首カルタ練習アプリの新しいバージョンを作成します。
今回の変更点・改良点
- 下の句の2列折りたたみ表示: 下の句(ひらがな)を「七・七」の位置で2列の縦書きに分割・折りたたみ、読みやすく和風カルタらしい配置に刷新しました。
- 4行5列・スクロールなしレイアウト: メインの畳エリアを画面高さに合わせて自動調整し、全20枚のカルタがスクロールなしで 4行5列 にぴったり収まるレスポンシブグリッドに統一しました。
- 空きスペースの保持: 正解してカルタが消滅する際、周囲の札が移動して詰まらないよう、カードが存在していた位置を「空席(透明)」としてそのまま維持します。
新しいファイルを生成いたします。
アプリケーションのポイント
- 下の句の2列折りたたみ(縦書き): ひらがな表示を前後で分割し、右列・左列の2列で札の上に配置して見やすさを高めました。
- 4行5列グリッド (スクロール不要): メイン画面全体を縦横比に応じて収まる 4行5列 のグリッドレイアウトにし、全体を一画面で視認・操作可能です。
-
正解後の空きスペース保持: 3秒間の正解アニメーション後、カルタを直接削除(DOM要素の消失による詰め)するのではなく、
cleared-slot(visibility: hidden)クラスで該当枠の領域を保持したまま透明化します。これにより他の札が移動せず、定位置で練習を継続できます。
練習用に20枚抜粋することや畳敷きのテキスチャはGeminiが用意してくれました。読み上げは、読みを間違えるなど少し残念ですが、練習用であれば許容されるでしょうか。抑揚ある詩吟風読み上げは現在無理ですが、将来強化学習で可能になるかもしれません。
【2】流体シミュレーション(Navier-Stokes方程式)
流体シミュレーションをビジュアル表現するウェブアプリを作る。『Stable Fluids』のアルゴリズムを使った2Dの煙・流体シミュレーションをタブ1にして、タブ2にはThree.jsなどのライブラリを使ったWebGL流体シミュレーションを実行する。各パラメータはサイドバーで設定。
html/javascriptでコード生成して、プレビュー。
2Dの『Stable Fluids』アルゴリズムによるリアルタイムな煙・流体シミュレーションと、Three.jsを活用した表現豊かな3D WebGL流体シミュレーションを切り替えて体験できるウェブアプリケーションを作成しました。
サイドバーから粘性・拡散・フォース強度・カラーパレット・レンダリングモードなどのパラメータをリアルタイムで変更可能です。
主な機能・アルゴリズム構成
1. タブ1: 2D Stable Fluids(Jos Stam アルゴリズム)
- ナビエ–ストークス方程式のリアルタイムソルバー(移流 Advection, 拡散 Diffusion, 圧力 Poisson 方程式の射影 Project)。
- Gauss-Seidel 緩和法による高速 Jacobi ソルバーを搭載。
- RGBカラー密度追跡: 単なる白黒の煙ではなく、カラーグラデーション(ネオン、火焔、オーシャン、墨汁など)が流速場に乗ってダイナミックに混ざり合います。
- 描画モード: 「密度マップ (Density)」、「速度場ベクター (Velocity)」、「流線パーティクル (Particles)」を切り替え可能。
2. タブ2: WebGL 3D Flow Field Simulation (Three.js)
- 最大60,000個のパーティクルを3D空間内でリアルタイムシミュレーション。
- 3D Curl Noise による渦度(Vorticity)効果と、球面バウンダリおよびドラッグ計算。
- マウス/タッチ移動により、3D空間上の点に物理的な力(フォース)を注入し粒子を弾き飛ばします。
- OrbitControls 対応で、3Dカメラの回転・ズーム操作が自在に行えます。
3. パラメータコントロール & プリセット
- 物理パラメータ: 粘性(Viscosity)、拡散(Diffusion)、消散(Dissipation)、マウスフォース強度、影響半径。
- カラーパレット & 3D設定: パーティクル数・サイズ・渦効果ON/OFF。
- クイックプリセット: 「濃煙」「ネオン嵐」「高粘性オイル」「コズミック」などをワンタップで適用可能。
2D Stable Fluidsは画面上でドラッグすると煙がうごめく様子を観察できます。シミュレーション技術がハリウッド映画の一端を支えていたとは。何か嬉しくなります。
【3】ローレンツ・アトラクタ
ローレンツ・アトラクタの3D画像を表示するwebアプリを作る。ドラッグにより視線角度を変える。各種パラメータを設定し、リセットすると描き始める。色についても設定できる。html/javascriptでコード生成し、プレビュー。
ローレンツ・アトラクタ(Lorenz Attractor)の3Dカオス軌跡をインタラクティブにリアルタイム描画・制御できるWebアプリケーションを生成します。
Three.jsを使用した3D描画エンジンと、OrbitControlsによる視点操作(ドラッグでの回転、ホイールでのズーム、右クリックでの平行移動)を完備しています。
主な機能
-
3D視線操作: マウスドラッグで視点角度変更、スクロールでズーム、自動回転モード。
-
各種パラメータ調整: $\sigma$ (シグマ)、$\rho$ (ロー)、$\beta$ (ベータ)、刻み幅 $dt$、計算速度(ステップ/フレーム)、最大点数。
-
柔軟なカラー設定:
-
Z高度グラデーション: カオスの高低差に応じた色変化
-
移動速度 (Velocity): 軌跡のスピードで輝度・色相変化
-
時間経過グラデーション: 描画の過程に応じた美しいグラデーション
-
ネオンレインボー: 鮮やかな虹色
-
単色(カスタムカラーピッカー): お好みのソリッドカラー
-
先端光点エフェクト: 描画の先頭に輝く粒子を表示
-
リアルタイム更新 & リセット: パラメータ変更後に「リセット&再描画」で新しい混沌軌跡を追跡
各種パラメータを変更しながらシミュレーションをGOし、画面上をドラッグして形状を確かめることができます。いわゆるカオス現象ですが、視覚的に楽しいです。
【4】マンデルブロ集合 (Mandelbrot set)
マンデルブロ集合もカオス以上に奥深い画像を提供してくれます。しかし、難点は計算に時間がかかること。そこで、GPUを活用するライブラリWebGLを使って時間を稼ぎます。
マンデルブロをWEBGLで高速化できる?
はい、マンデルブロ集合の描画は WebGL を使って大幅に高速化できます。 [1]
なぜ高速化できるのか
- GPUによる並列計算:通常のJavaScript(CPU)はピクセルごとにループ計算を行うため処理が重くなりますが、WebGL(フラグメントシェーダー)を使うと、GPUの強力な並列処理能力で全ピクセルの計算を同時に行えます。 [1, 2]
- リアルタイム描画:マウスでの移動やズームといった操作も、滑らかにカクつくことなく動かせるようになります。参考として wgld.orgのマンデルブロ集合解説 などの実装例も広く知られています。 [3, 4, 5]
注意点(デメリットや限界)
- 精度の限界:標準的なWebGL(WebGL 1.0 / 2.0)は主に単精度浮動小数点数(Float32)を使用するため、深くズームしすぎると計算誤差が出て画質が荒れたりボケたりします。 [6]
- 対策:さらに深くズームしたい場合は、シェーダー内で倍精度(Float64)をエミュレートする処理を実装するか、WebAssembly(Wasm)の利用を検討する必要があります。 [6]
もしよろしければ、以下についてお知らせください:
- 実装したい環境や言語(Three.jsを使うか、純粋なWebGLかなど)
- ズームの深さにこだわりがあるか
さらに具体的なシェーダーコードの書き方やアプローチをご案内できます。
[1] https://ctt-media888.com
[2] https://webgl.souhonzan.org
[3] https://qiita.com
[4] https://webgl.souhonzan.org
[5] https://wgld.org
[6] https://www.reddit.com
three.jsを使って、ウェブアプリで簡単な例を作って。
Three.js を使って、GPU(フラグメントシェーダー)でマンデルブロ集合を高速描画する最小限のコード例を作成しました。
このコードでは、THREE.ShaderMaterial を使い、描画計算をすべて GPU に任せています。また、拡大・縮小や移動(ドラッグ)ができるように、JavaScript 側からシェーダーへ座標データをリアルタイムに送る(Uniforms)仕組みを入れています。
実装コード(HTML)
以下のコードを一つの .html ファイルとして保存し、ブラウザで開くだけで動きます。
コード略
コードのポイント
- THREE.ShaderMaterial: Three.js が標準で用意しているマテリアル(材質)を使わず、自分で fragmentShader(色の計算ルール)を書き込んで GPU に直接命令を送っています。
- uniforms オブジェクト: JavaScript 側でマウス操作を検知し、計算の中心座標(u_zoomCenter)や拡大率(u_zoomSize)を毎フレーム GPU に転送しています。これにより滑らかな操作が可能です。
この簡易版をベースに、さらに以下のようなカスタマイズも可能です。試してみたい機能はありますか?
- 青ベースやモノクロなど、カラーパレット(色合い)の変更
- ズームしすぎたときに発生するモザイク(ドット化)の確認と、その対策方法
- 描画をさらに美しくするサイケデリックなアニメーション効果の追加
実行してみると、何も映らない。原因はthree.jsのライブラリ読み込みのURLが適切でなかったため。ここは手動タイピングで直す。
真っ暗で何も映っていない
画面が真っ暗になってしまう場合、主な原因は Three.jsの読み込みエラー または ブラウザのセキュリティ制限(ローカルファイルを直接開いたことによる制約) です。
- モザイクの対策方法
WebGLでマンデルブロ集合を深くズームした際に発生するモザイク(ドット化・ボケ)は、GPUの単精度浮動小数点数(Float32)の精度限界が原因です。Float32の有効桁数は約7桁しかないため、ズーム倍率が1万倍(10⁴)〜10万倍(10⁵)を超えたあたりで座標の計算誤差が限界に達し、同じ色で塗りつぶされた四角いドット(モザイク)になってしまいます。
これを根本的に解決するには、GPU上で倍精度(Float64、有効桁数約15〜17桁)相当の計算を行う仕組みを実装する必要があります。
変更の要点
- splitDouble() 関数: JavaScript(Float64)の数値を Math.fround() を使って「32ビットで表現できる最も近い値(上位)」と「そこから漏れた端数(下位)」の2つに分解してGPUへ転送しています。
- シェーダー内の高精度関数: フラグメントシェーダー内に df_add(足し算)と df_mul(掛け算)という専用のアルゴリズムを用意し、送られてきた2つのfloatを使って内部で擬似的に倍精度計算を行っています。
初期座標として、マンデルブロ集合の中でも特に美しいミニチュア(ミニ・マンデルブロ)が隠れている有名な座標(-0.743643...)をセットしてあります。ホイールでどんどん拡大していくと、無限に美しい幾何学模様が生成される様子が確認できます。
この擬似倍精度の実装で、目標のズーム深度まで綺麗に表示できるようになったか教えてください。
もしさらに深いズーム(10兆倍以上、例えば100兆倍など)を目指す場合は、さらに精度を高めるトリプル・エミュレーション(Float32×3)やWebAssemblyを併用したCPU計算への切り替え(部分レンダリング)が必要になりますが、そこまで追求してみたいですか?
「さらに深いズーム」はトライしてませんが、面白そうです。
以下にスクショ3枚を掲載します。マンデルブロ図の大きな黒丸の接点を狙って拡大していったときの画像になります。とにかく速いです。
【5】メトロポリタン美術館
メトロポリタン美術館の公開APIを使った、美術館巡りのウェブアプリを作る。html/javascriptベースでコード生成して、プレビュー。
メトロポリタン美術館(The Met)の公開APIを活用した、エレガントで多機能なバーチャル美術館アプリを生成します。
このアプリには以下の特徴・機能が含まれています:
- インタラクティブ探索: 部門(印象派、日本美術、古代エジプトなど)やキーワードで作品を検索
- ランダムダイブ機能: ワンクリックでMetの豊富なコレクションからランダムに素晴らしい作品をピックアップ
- 詳細モーダル&高画質ギャラリー: 作品の時代、素材、作者情報、パブリックドメイン表示
- 音声ガイド機能 (Web Speech API): 作品の解説やタイトルの音声読み上げ機能
- マイキュレーション(お気に入り保存): 気に入った作品をブラウザ内(LocalStorage)に保存し、自分だけの仮想個展を作成
- クラシック&ラグジュアリーなデザイン: メトロポリタン美術館の雰囲気に合わせた洗練されたダーク&ゴールド調UI
どうもAPIが機能していない様子。
検索かけても、何もひっかからない
メトロポリタン美術館(The Met)APIの検索仕様を強化し、検索エラー防止・フォールバック機能(有名名画の事前保持)・daisyUIを組み合わせたエレガントなWebアプリケーションコードを作成しました。
主な改修・強化ポイント
- 堅牢な検索ロジック & フォールバック:
- 検索API(
/search)が空やエラーを返した場合、自動的に厳選された名画コレクション(ゴッホ、モネ、フェルメール、葛飾北斎、古代エジプト美術等)を表示するバックアップを統合しました。 - 画像が無いオブジェクトを自動排除し、常に画像付きで閲覧できるようにフィルター処理しています。
- クイックタグ & 快適検索:
- 「Van Gogh」「Japan」「Impressionism」「Armor」「Egyptian」などのワンクリックタグ検索を追加しました。
- 洗練されたデザイン(Tailwind CSS + daisyUI):
- 深いバーガンディ&ダークトーンにゴールドアクセントを施したラグジュアリーなデザイン。
- 音声ガイド & マイギャラリー保存:
- Web Speech APIによる日本語音声読み上げ解説と、LocalStorageによるお気に入り保存機能を継続搭載。
コードファイルを右側のエディタに配置しましたので、Preview ボタンから実際にお試しいただけます。
色々Geminiと格闘したのですが、うまくいかず。本家のAPI説明のHPを調べてみると、丁度この時期にAPIがv1からv1.1にバージョンアップしたという記事を見つけました。あまりに最近の出来事についてはGeminiに頼るより自分で検索する方が早道なのでしょう。それでも、バージョンアップを指摘すると、「ああ、あれね」という感じで対応してくれます。
v1が新たにv1.1になり、/public/collection/v1.1/searchを使うことになっている。合わせて修正して。
メトロポリタン美術館(The Met)の新しい API バージョン /public/collection/v1.1/search(ページネーション対応:offset / limit)に対応した最新コードに更新しました。
修正内容
- 検索エンドポイントの更新:
- 旧 endpoint
/public/collection/v1/searchから、最新の/public/collection/v1.1/searchに変更。
-
limit/offsetパラメータの活用:
-
v1.1で追加されたlimit(1回の取得件数制限)やoffsetをクエリ文字列に追加することで、APIからのレスポンスを軽量化し、無駄な大量ID読み込みを回避して動作スピードを向上させました。
- エラーハンドリングの継続統合:
- 単一オブジェクト取得時(
/objects/{id})に410 Goneや404 Not Foundが返った場合もスムーズに次の作品へとフェールオーバーする処理を維持しています。
格闘している最中に知ることになったCORS。メトロポリタン美術館のAPIはどうなのか気になったので問い合わせました。
メトロポリタン美術館のAPIはCORS対応?
メトロポリタン美術館(The Met)が提供している The Met Collection API は、CORSセーフ(CORS対応)です。プロキシサーバーや独自のバックエンドを介さなくても、ブラウザのフロントエンド(JavaScriptの fetch() など)から直接データを取得できます。 [1]
また、このAPIはオープンデータ(Open Access)プログラムの一環として公開されており、APIキーの取得やユーザー登録も一切不要で、誰でも完全無料で利用できます。 [2, 3]
[1] https://www.getfreeapis.com
[2] https://metmuseum.github.io
やっと画像が出てきました。自分でプログラミングに成功したかのように嬉しくなります。他力なので謙虚であるべきでしょうが。
それでも不具合を調べている最中に見つけたCORSは私にとってはよき収穫物です。ものを実際に作ると見えてくるものがあるのでしょう。
Geminiとのやり取りは掲載しませんが、最後に著作権に関する記述を閲覧できるように変更しています。スクショでは緑色のコメントになります。画像は高解像度で拡大ができます。









