[Astro #08] Shader パラメータ計算機:静的なブログに 動き を吹き込む
1. はじめに
Shader(GLSL)や物理ベースのアルゴリズムを解説する際、常に一つの壁にぶつかります。それは、「静的なコードとテキストだけでは、その動的な挙動を直感的に伝えきれない」という課題です。
例えば、海面を表現する Gerstner Wave。 その数式をどれほど緻密に記述し、最適化されたコードを提示したとしても、読者がその「波の鋭さ」や「伝播速度」がパラメータ一つでどう変化するかを理解するには、自身のローカル環境にコードを写し、コンパイルして実行するまでの高いハードルがありました。
「波長()を短くしたとき、物理的に正しい波の速度はどう導かれるのか?」
「Steepness(鋭さ)を限界まで上げたとき、数式上の波形はどう破綻するのか?」
これらの問いに、言葉ではなく「リアルタイムの数値変化」という体験で答える。それが今回の目的です。
静的な「アーカイブ」から、動的な「観測装置」へ
これまでのブログは、いわば過去の思考の「記録(アーカイブ)」でした。しかし、Astro というモダンなフレームワークを手にした今、記事は単なる記録から、読者が直接触れて結果を得られる「観測装置(シミュレーター)」へと進化させることができます。
今回は、Astro の最大の特徴である Islands Architecture を活用し、爆速な静的サイトとしてのパフォーマンスを維持したまま、記事のど真ん中に React 製のリアルタイム・パラメータ計算機を「島」として浮かべます。
数式が、ただの記号の羅列から、スライダー一つで形を変える「生きたデータ」に変わる過程を解説していきます。
前回の記事:
[Astro #07] HugoからAstroへの移行とビルド最適化・クローリング検証 // PROTOCOL.LAIN
HugoからAstro + React + MDX環境への移行記録。旧環境からのリポジトリ軽量化、SSGビルド時のOOMエラー対応、MDXパーサーの仕様対応、および移行後のクローリング状況についてまとめる。
humanxai.info2. Astro Islands(アイランド・アーキテクチャ)の恩恵
この計算機を実装するにあたって、Astroを採用した最大の理由は、その「部分的なハイドレーション(Partial Hydration)」の仕組みにあります。
一般的なSPA(Single Page Application)フレームワークでブログを作ると、ページ全体を動かすために巨大なJavaScriptファイルを読み込む必要があります。しかし、技術ブログの9割は「静的なテキスト」です。計算機を動かすためだけに、ページ全体を重くするのは、PROTOCOL.LAIN が求める最適化されたプロトコルに反します。
Astroの Islands Architecture は、この問題を鮮やかに解決します。
必要な場所だけを「起動」させる
Astroはデフォルトで「JavaScriptをゼロ」にしてHTMLを出力します。そして、インタラクティブな動きが必要なパーツ(今回の計算機など)だけを「アイランド(島)」として定義し、その島だけをReactなどで動かすことができます。
これにより、記事の読み込みは爆速な静的HTMLのまま、特定のセクションに到達したときだけ高度な計算機能を付加することが可能になります。
MDXによるシームレスな統合
実際のMDXファイルでの呼び出しは、驚くほどシンプルです。Markdownの文脈の中に、まるで標準のHTMLタグのようにReactコンポーネントを配置できます。
import GerstnerCalc from '../../components/GerstnerCalc.jsx';
## パラメータの動的観測
以下のシミュレーターで、波の物理特性をリアルタイムに計算します。
<GerstnerCalc client:visible />
ここで重要なのが client:visible というディレクティブです。
これ一行を書くだけで、Astroは「このコンポーネントがユーザーの画面内に入る(視認される)まで、JavaScriptの読み込みと実行を待機させる」という高度な最適化を自動で行います。
読者が記事の冒頭を読んでいる間、計算機のリソースは消費されません。スクロールして計算機が必要になった瞬間に、アイランドが「目を覚ます」。この無駄のなさが、サイト全体のパフォーマンスを高い次元で維持しつつ、リッチな体験を提供する鍵となっています。
3. 実装のポイント
シミュレーターの実装において重視したのは、「軽量な計算ロジック」と「サイトの世界観を壊さないデザイン」の両立です。
React によるリアクティブな計算
ロジック自体は非常にシンプルです。React の useState を利用して、スライダーからの入力を即座に変数へ反映させます。
// 入力値が変わるたびに再計算が走る
const [wavelength, setWavelength] = useState(10.0);
const [steepness, setSteepness] = useState(0.5);
// 物理定数に基づいた計算
const k = (2 * Math.PI) / wavelength; // 波数
const c = Math.sqrt(9.8 / k); // 速度
const a = steepness / k; // 振幅
波長(λ)が変化すれば、即座に波数(k)が再計算され、それが重力加速度との関係から速度(c)を導き出す。この一連のフローが、読者がスライダーを動かす「0.1秒以下」のラグで画面に反映されます。
デザイン:PROTOCOL.LAIN への最適化
「普通」のUIを拒み、サイトの持つサイバーパンクな雰囲気を強調するため、CSSには以下の工夫を凝らしました。
1. accent-color によるモダンな色付け
スライダー(input type="range")のカスタマイズはかつては複雑でしたが、現在は accent-color プロパティ一行で、ブラウザ標準のパーツにサイトのテーマカラー(マゼンタ)を流し込めます。
input[type="range"] {
accent-color: #ff0055; /* スライダーを不穏な赤色に */
}
2. ターミナル・フォントとネオンの発光
計算結果を表示するパネルは、かつてのブラウン管端末や、現代のハッカー・コンソールを彷彿とさせるデザインに仕上げました。
- Font:
Courier Newやmonospaceを指定し、等幅フォントによる「データ感」を演出。 - Glow:
box-shadowとtext-shadowを薄く重ねることで、暗闇に浮かび上がる液晶の「光の漏れ」を表現。
.output-screen {
background-color: #0a0f18;
border: 1px dashed rgba(0, 229, 255, 0.3);
/* ほんのりとした水色の発光 */
box-shadow: 0 0 15px rgba(0, 229, 255, 0.1);
}
これらの要素が組み合わさることで、単なる「計算機」は、PROTOCOL.LAIN のレイヤーの一部として機能する「端末(ターミナル)」へと昇華されます。
4. まとめ:アーカイブから「体験」のレイヤーへ
技術ブログを構築する際、私たちはしばしば「既存のプラグインをいかに正しく動かすか」という設定の泥沼に時間を吸い取られがちです。今回も、コードブロックのシンタックスハイライトという些細な装飾一つをめぐって、プラグイン同士の競合やキャッシュの反乱という「システムの壁」に直面しました。
しかし、その泥沼から一歩抜け出し、「Astro Islands」 という強力なプロトコルを直接ハックすることで、ただの静的なテキストを「動的な観測装置」へと作り変えることができました。
今回の構築で得られた知見
- Islands Architecture の有用性: ページ全体を SPA にせずとも、必要な箇所だけに React を注入することで、パフォーマンスと表現力はトレードオフなしで共存できる。
- 「普通」を脱却するデザイン: 既存のプラグインに頼らずとも、少量の CSS と
::before疑似要素を駆使するだけで、サイトの世界観(PROTOCOL.LAIN)を反映した独自の UI は構築可能である。 - 体験の提供: 数式(Katex)による静的な証明と、シミュレーターによる動的な観測。この二つを組み合わせることで、解説の解像度は飛躍的に向上する。
COMM_LOG: astro-08-interactive-shader-calc