見出し画像

【A-Frame+GLSL】 Parallax Occlusion Mappingを実装してみる

A-Frameで利用できるParallax Occlusion Mapping(POM)を実装しました。
これを利用すると、ブラウザ3D環境で画像を立体的に表示できます。

A-Frameとは

A-Frameは、ウェブ上で仮想現実(VR)体験を簡単に作成できるように設計されたオープンソースのWebフレームワークです。HTMLに似たシンプルなマークアップ言語を使って、3Dシーン、VR体験、AR(拡張現実)体験を構築できます。これにより、Web開発者は従来のHTMLとJavaScriptの知識を活用して、3Dのインタラクティブな体験を簡単に作成できます。

A-FrameはMozillaによって開発され、WebVR規格に基づいています。これにより、多くのVRデバイス(Oculus Rift、HTC Vive、Google Cardboardなど)やデスクトップ、モバイルブラウザで動作するVR体験を実現します。A-FrameはEntity-Componentシステムを利用し、コンポーネントを使ってオブジェクトに振る舞いや外見を追加することができます。これにより、カスタマイズ性と再利用性が高まります。

また、バックエンドにはthree.jsが利用されていて、その機能を使ってGLSLを記述することができます。

GLSLとは

GLSL(OpenGL Shading Language)は、グラフィックスハードウェアでシェーダーを記述するための高級プログラミング言語です。OpenGLのために特別に設計されており、GPU(グラフィックス処理ユニット)で直接実行されるプログラムを作成することができます。GLSLを使用することで、3Dグラフィックスのレンダリングプロセスにおいて、高度にカスタマイズされた視覚効果や画像処理が可能になります。

主要な特徴

  • ハードウェアに依存しない: GLSLはクロスプラットフォームで利用でき、さまざまなグラフィックスハードウェアで一貫した動作を提供します。

  • リアルタイムのパフォーマンス: GLSLで記述されたシェーダーはGPUで直接実行されるため、高速に処理されます。これは、リアルタイムのゲームやインタラクティブなアプリケーションにとって重要です。

  • C言語ベースの構文: GLSLはC言語に基づいた構文を持っているため、既にプログラミングの経験がある人にとっては比較的学びやすいです。

Parallax Occlusion Mappingとは

Parallax Occlusion Mapping(パララックスオクルージョンマッピング、POM)は、テクスチャの詳細と奥行きを向上させる高度なレンダリング技術です。この技術は、表面の凹凸をリアルに表現することで、3Dモデルにリアルな立体感を与えますが、実際にはモデルのジオメトリを増やすことなく実現されます。

原理

Parallax Occlusion Mappingは、視点に基づいてテクスチャ座標を変更し、表面に高さのあるように見せる技術です。具体的には、ユーザーの視点に応じてテクスチャの各ピクセルの見え方を変え、そのピクセルがどの程度「突出」または「凹んでいる」かを計算します。この計算は、主にハイトマップ(高さマップ)を用いて行われます。

実装

POMはシェーダーで実装され、以下のステップで処理されます:

  1. ハイトマップの読み取り: モデルの表面にテクスチャとして適用されたハイトマップから高さデータを取得します。

  2. 視差計算: 視点の位置からハイトマップを使用してテクスチャ座標をオフセットします。これにより、表面が視点によって異なる角度から見えるようになります。

  3. 自己遮蔽と陰影の追加: 凹凸のある表面では、特定の部分が他の部分によって遮られることがあります。POMはこれを計算し、よりリアルな陰影を生成します。

利点と制限

利点:

  • リアルな表面のテクスチャを実現でき、視覚的なインパクトが高まります。

  • ポリゴン数を増やさずに詳細な表現が可能で、パフォーマンスへの影響を抑えることができます。

制限:

  • 計算が複雑であり、特にモバイルデバイスなどのリソースが限られた環境ではパフォーマンスに影響を与えることがあります。

  • 平面的な物体には向いていますが、複雑なジオメトリには適用が難しい場合があります。

Parallax Occlusion Mappingは、ゲームやシミュレーションなど、リアルタイムで高品質なビジュアルが求められるアプリケーションでよく使用されます。

作ったもの

凹凸が表現される
急な角度から見ると表示が乱れる(POMの制限)

コードはglitch.comに置きました。Remixボタンから、クローンしてブラウザ上でソースコードを編集できます。

デモ

コード

実装に当たり、以下のウェブサイトを参考にさせていただきました。


概念図

rayStepの求め方
接空間での各要素の対応

実装のポイント

レイマーチングの領域判定は接空間で行う

レイマーチングは、視点から各ピクセルに向けて放射されるレイ(光線)をシミュレートし、そのレイがシーン内のオブジェクトとどのように交差するかを計算する処理です。レイを少しずつ前進させる行進(マーチ)のような処理です。

接空間は、ポリゴンメッシュの各頂点における局所的な座標系を指します。これは3Dモデルの各頂点で定義される空間であり、頂点の法線ベクトルを含む平面(接平面)に基づいています。

ワールド空間は、3Dシーン全体のグローバルな座標系を指し、シーン内のすべてのオブジェクトがこの共通の座標系に位置づけられます。


POMの処理では、以下のような変数が絡んできます。

  • 描画対象頂点の座標(接空間)

  • カメラ座標(ワールド空間)

  • 深度マップ底面の深さ(ワールド空間)

異なる座標系の変数同士を直接計算することは基本的にできません。そこで今回は各変数を接空間に変換して処理を行ないました。


所感

A-FrameでGLSLを記述すると、ブラウザ上で動作する低レベルのGPU処理をhtmlファイルだけで記述できることに驚きました。
ブラウザ3Dでも、面白い表現が思ったより簡単に実現できるのかもしれません。



この記事が気に入ったらサポートをしてみませんか?