[Next.js #31] Touching Noise Field — Three.js × GLSLで“触れるノイズ場”を作る

はじめに

ノイズ記事の連載の中で学んだ内容を、今回はひとつの作品としてまとめてみました。

ベースに使うのは、シンプルな PlaneGeometry です。 ただの平面に見えるジオメトリでも、Shader による頂点変形と色設計、そして Raycaster を組み合わせることで、触れると反応する“ノイズ場”へ変えることができます。

これまでの連載では、ノイズを「見る」「理解する」「実装する」ことを中心に扱ってきました。 今回はそこから一歩進めて、マウスで触れることで局所的に反応するインタラクティブな表現としてまとめています。

また、Raycaster といえばクリック判定やオブジェクト選択の印象が強いですが、私の過去実装では MMD キャラクターの足元から地面へレイを飛ばし、接地判定や高さ取得にも使ってきました。 今回はその Raycaster を、“マウスがジオメトリに触れる位置を取得するための道具”として活用しています。

前回の記事:

動画(YouTube):

動画(PC):

1. なぜ今回は作品として仕上げるのか

これまでの Noise 入門では、Perlin Noise、FBM、Domain Warping、頂点変形などを、段階的に理解していくことを重視してきました。

それぞれ単体でも面白い技術ですが、学んだ内容が分散したままだと、読んだ後に「結局これを組み合わせると何が作れるのか」が見えにくくなります。 そこで今回は、連載の中で扱ってきた要素をひとつの画面の中に集約し、“作品として触れる状態”にまで持ち上げることを目的にしました。

今回の Touching Noise Field では、

  • ノイズによる形状の揺らぎ
  • Domain Warping による空間のねじれ
  • Raycaster による入力位置の取得
  • 色設計による印象の制御
  • Inspector によるリアルタイム調整

といった要素が、ひとつのデモの中で繋がっています。

単なる技術検証ではなく、連載で積み上げてきた知識を“見て、触れて、調整できる形”に変えることが、今回作品として仕上げた一番大きな理由です。

2. PlaneGeometry なのに平面に見えない理由

今回ベースに使っているのは、ごく普通の PlaneGeometry です。

見た目だけを見ると、雲のような流体のような、あるいは厚みのあるノイズ面のようにも見えますが、内部的には複雑なメッシュを用意しているわけではありません。 やっていることの本質は、分割された平面の各頂点を Shader で動かしているだけです。

頂点 Shader 側では、平面上の position.xy をもとにノイズを計算し、その値に応じて pos.z を加算しています。 つまり、地形生成で高さマップを作る時と同じように、“平面の上に高さを与える”という構造です。

ただし今回は単純な地形のように固定的な山を作るのではなく、時間変化と Domain Warping を組み合わせることで、常に内部がうごめいているような印象を作っています。 さらにマウス近辺だけ局所的に変形が強まるため、ただの平面には見えにくくなります。

見た目の複雑さに対して、土台は非常にシンプルです。 このギャップが、Shader 表現の面白さのひとつだと思います。

3. Raycaster は何をしているのか

今回のインタラクションの入口になっているのが Raycaster です。

Three.js の Raycaster は、マウスやタッチ位置から 3D 空間へ向かってレイを飛ばし、どのオブジェクトに当たったかを調べるための仕組みです。 一般的にはオブジェクト選択やクリック判定に使われることが多いですが、今回は マウスが平面のどこを触れているかを知るために使っています。

流れとしてはシンプルで、

  1. マウス座標を NDC に変換する
  2. raycaster.setFromCamera() でカメラからレイを飛ばす
  3. intersectObject(plane) で平面との交点を取得する
  4. その交点を plane のローカル座標へ変換して uniform に渡す

という手順です。

この「平面上のどこに触れているか」という位置情報を Shader に渡すことで、交点そのものではなく、交点を中心にした距離場を作ることができます。 今回の表現では、この距離場を使って「近い場所ほど影響が強い」という influence を計算し、頂点変形と色変化の両方に使っています。

つまり Raycaster 自体が変形を作っているのではなく、変形の中心点を決める役割を担っています。

4. Domain Warping を局所化する意味

Domain Warping は、ノイズを評価する座標そのものを別のノイズでずらすことで、単純な模様をより複雑で有機的な流れに変える手法です。

ただ、画面全体に強い Domain Warping をかけるだけだと、常に全面が騒がしくなりやすく、今回の「触れた場所が反応する」という体験とは少しズレてしまいます。

そこで今回は、マウス位置からの距離によって influence を作り、ホバー近辺だけ Domain Warping を強くするようにしています。 平常時は比較的落ち着いたノイズ面として見せつつ、マウスが近づいた場所だけが局所的にうねり、空間がねじれるように反応します。

この局所化によって、

  • 触れていない部分は背景として落ち着く
  • 触れた部分だけが主役になる
  • 入力と変化の因果関係が視覚的に分かりやすくなる

というメリットが生まれます。

単にノイズを動かすだけでなく、“どこが、なぜ反応しているのか” を見せるために、局所化はかなり重要な役割を持っています。

5. 色設計が印象をどう変えるか

今回の見た目を支えているのは、頂点変形だけではありません。 かなり大きいのが、fragment shader 側で行っている色設計です。

ベースには深い青を置き、その上に中間の青、水色寄りのハイライトを重ねることで、平面全体に厚みと深度を感じさせています。 さらに hover している近辺には、少しだけピンク寄りのアクセントを加えることで、「今ここが反応している」という視覚的な手がかりを作っています。

もしこれが単色に近い色構成だったら、起伏はあっても表情はかなり弱かったはずです。 逆に色を丁寧に分けることで、

  • 高さの違い
  • ノイズの流れ
  • hover 部分の強調
  • 全体の雰囲気

を同時にコントロールできます。

今回の Touching Noise Field は、技術的には頂点 displacement の応用ですが、作品として成立させているのは、形状変形と色変化が一体になっていることだと感じます。

6. Inspector を付けると何が見えるか

今回のデモには、lil-gui を使って簡単な Inspector を付けました。

調整できるのは主に、

  • Radius
  • Warp Strength
  • Noise Scale
  • Elevation
  • Hover Lift

といった、変形の印象に直結するパラメータです。

これを付けることで、単なる完成品を見るだけではなく、どのパラメータが見た目にどう効いているのかをその場で確認できるようになります。

例えば、

  • Radius を大きくすると、触れた時に反応する範囲が広がる
  • Warp Strength を上げると、局所的なねじれが強くなる
  • Noise Scale を上げると、ノイズの粒度が細かくなる
  • Elevation を上げると、面全体の起伏が強まる
  • Hover Lift を上げると、マウス近辺の持ち上がりが強調される

というように、各値の役割がかなり明確です。

これによって、作品として眺めるだけでなく、ノイズ表現の設計パラメータを触って学べる状態になっています。 技術記事としても、作品としても、Inspector はかなり相性が良いと感じました。

7. 過去回との対応表

今回の Touching Noise Field は、単発で生まれたものではなく、Noise 入門の中で積み上げてきた要素の延長線上にあります。

ざっくり対応させると、次のような位置づけになります。

  • ノイズの基礎 → そもそも滑らかな乱数場をどう扱うか

  • FBM → 単純なノイズを重ねて複雑さを増す考え方

  • Domain Warping → 座標をずらして有機的な流れを作る考え方

  • Vertex Displacement → 平面に高さを与え、形として見せる方法

  • Raycaster → 3D 空間上の“触れている位置”を取得する方法

  • Inspector → パラメータをリアルタイムに観察しながら調整するための仕組み

これまでの連載では、それぞれを個別に理解することに重点を置いてきました。 今回はそれらをまとめて、鑑賞するノイズから、体験して調整できるノイズ場へと発展させています。

まとめ

今回は、Three.js と GLSL を使って Touching Noise Field という小さな作品を作りました。

ベースはシンプルな PlaneGeometry ですが、Raycaster によってマウス位置を 3D 空間上へ落とし込み、その周辺だけ Domain Warping と頂点変形を強めることで、“触れると反応するノイズ場”を実現しています。

見た目としては流体的で複雑に見えますが、内部でやっていることは、

  • Raycaster で交点を取る
  • 距離場を作る
  • その影響を Shader に渡す
  • 頂点変位と色変化に反映する

という、比較的整理しやすい構造です。

そして今回は、Inspector を付けることで、作品として見せるだけでなく、パラメータを触りながら表現の差を確認できる形にもできました。

Noise 入門の連載で扱ってきた要素が、今回ようやくひとつの画面の中で繋がった気がします。 今後はこの流れをもとに、平面以外のジオメトリや、より立体的な場へと発展させていきたいと思います。