先日開催したAway3D勉強会の発表のフォローアップ記事となります。

写真をRGB3原色に分解して3次元で表示するHTML5 + WebGLのデモを作ってみました。ステージをドラッグすると写真が赤・青・緑の3原色に分解されて表示されます。ライブラリはJSライブラリの「Away3D TypeScript」を使っています。

このデモを通して紹介したいのは次の3つです。

  1. 色分解のロジック
  2. Flashライクで高機能なHTML5版BitmapDataクラスの紹介
  3. Flash Stage3Dにフォールバック可能なAway3D TypeScriptのレンダラー

以下で、それぞれについて詳しく紹介していきます。

実装方法

このデモでは、img要素で画像を読み込み、それを色分解し、3D空間に表示しています。

1. 色分解のロジック

Web上の多くの画像は赤・青・緑の光の3原色(8bit深度)を使って構成されています。これを確認するにはPhotoshopが便利で、[チャンネル]パネルを使えば赤・青・緑それぞれのピクセル情報を確認することができます。

今回のデモにおいては写真をRGB(赤・緑・青)のレイヤーに分解し、それぞれ描画モード「スクリーン」(もしくはピクセルのカラー情報を加算するもの)に設定して黒背景に重ねています。そうすることで元の画像が復元されます。参考までにPhotoshopで同じことを再現しようとすると次の状態となります。

2. Flashライクで高機能なHTML5版BitmapDataクラスの紹介

HTML5 Canvas (Context2D)を利用すれば、画像解析/加工することができます。ただし、HTML5 Canvas (Context2D)は低レベルのAPIしか提供されていないために、実現したい機能がある場合は自分でJavaScriptのコードを記述する必要があります。

今回利用したJSライブラリ「Away3D TypeScript」には画像を3原色+透明度に分解するBitmapData#copyChannel()というメソッドがあります。これを使えば少ないコードで分解した色情報を得ることができます。このクラスの使い方は次の通りです。

BitmapData.copyChannel(ソースのビットマップデータ, 元素材の範囲矩形, 貼付け先の座標, 元素材のRGBチャンネルを指定, 貼付け先のRGBチャンネルを指定)
// 変数
var w:number = image.width;
var h:number = image.height;
var p:Point = new Point(0, 0);
var rect = new Rectangle(0, 0, w, h);

// ImageエレメントをBitmapDataに転写
var bmd = new BitmapData(w, h);
bmd.draw(image);

// 保存先を準備
var r = new BitmapData(w, h, true, 0xFF000000);
var g = new BitmapData(w, h, true, 0xFF000000);
var b = new BitmapData(w, h, true, 0xFF000000);

// 各チェンネルをコピー
b.copyChannel(bmd, rect, p, BitmapDataChannel.BLUE, BitmapDataChannel.BLUE);
r.copyChannel(bmd, rect, p, BitmapDataChannel.RED, BitmapDataChannel.RED);
g.copyChannel(bmd, rect, p, BitmapDataChannel.GREEN, BitmapDataChannel.GREEN);

this._result = [r, g, b];

色分解については次のデモを試してみてください。読み込んでいるのはオリジナルの写真ですが、JavaScriptによって赤・緑・青の3画像(Canvasエレメント)に分解されています。

140804_rgb_js_decompose

Flashの経験者なら気づいたかもしれませんが、BitmapData クラスはFlashのAPIで存在します(Flash 8の頃からあります)。BitmapData クラスはHTML5やWebGLには元々存在しないのですが、Away3D TypeScriptにはFlash互換のAPIがいくつか整備されています。Flash経験者が学びやすい設計になっているのもAway3Dの魅力の一つです。

3D空間への展開

3原色に画像を分解したらAway3D TypeScriptを使ってWebGLの中で3D空間に配置。3D上の3平面は描画モードを加算(BlendMode.ADD)にしています。注意した点としては遠近感がつくと3平面がずれてしまうので、Away3DのOrthographicProjectionクラスを利用して、平行投影をするようにしました。Away3D TypeScriptでの平行投影のJavaScriptはつぎの通りです。

// 平行投影を利用
var projection = new OrthographicProjection();
projection.far = 60000;
projection.projectionHeight = 1500;
this.camera.projection = projection;

Flash Stage3Dにフォールバック可能なAway3D TypeScriptのレンダラー

Away3D TypeScriptの凄い機能として、WebGLが未搭載のブラウザではFlash Playerにフォールバックします。次のキャプチャ画像はWebGLがデフォルトで無効であるMac Safari 7でのデモを動かしたものです。

※次期Safari 8ではWebGLがデフォルトで有効になるらしいですが、執筆時点の最新のMac Safari 7では開発者オプションを使わない限りWebGLは無効となっています

スクリプトの処理自体はJSで行われていて、描画部分だけFlash側で再現しているようです。これを実現するにはWebGLのGLSLとFlash Stage3DのAGALのコードの変換であったり、JS側からSWF側へのテクスチャの転送など、どれをとっても実現が難しいことばかりです。 Away3Dではそれが内部的に実現されていて正直驚くばかりです。

最後に

Away3D TypeScriptはFlashライクなAPIが用意されているだけでも使いやすくて嬉しいのですが、Flashへのフォールバックのエンジンまで搭載されています。昨今、WebGL対応のブラウザが増えてきてはいるものの、実際のところ古いブラウザも数多く残っています。用途によってはフォールバックの機能は重宝するかもしれません。

今後もICS MEDIAではAway3D TypeScriptのデモを作成して紹介していこうと思います。ぜひFacebook公式ページをフォローするなどして、当サイトの更新をチェックくださいませ。

参考にしたサイト