WebGL をサポートするブラウザでは、プラグインを使用することなく HTML canvas
内で 3D グラフィックスをレンダリングするための、OpenGL ES 2.0 に基づく API を Web コンテンツで使用できます。WebGL のプログラムは JavaScript で記述する制御コードと、コンピュータの Graphics Processing Unit (GPU) で実行する特殊効果コード (シェーダーコード) で構成されます。WebGL 要素は他の HTML 要素と混ぜられ、他のページ部品やページの背景と合成されます。
この記事では、WebGL の基礎を紹介します。ここでは、3D グラフィックスに関する数学的な知識を理解していることを前提とします。よって、OpenGL そのものの説明は行いません。
このチュートリアルで使用するコード例は、 GitHub の webgl-examples リポジトリで確認できます。
3D 描画の準備
3D 描画のため WebGL を使うにあたって始めに必要なものは、canvas です。以下の HTML の断片では canvas と、WebGL コンテキストの初期化に用いる onload
イベントハンドラを定義しています。
<body onload="start()"> <canvas id="glcanvas" width="640" height="480"> このブラウザは <code><canvas></code> 要素をサポートしていません。 </canvas> </body>
WebGL コンテキストの準備
以下の JavaScript コードの start()
関数は、文書が読み込まれた後に呼び出されます。この関数の役割は WebGL コンテキストの設定と、コンテンツのレンダリングを開始することです。
var gl; // WebGL コンテキスト用のグローバル変数 function start() { var canvas = document.getElementById("glcanvas"); // GL コンテキストを初期化 gl = initWebGL(canvas); // WebGL を使用できる場合に限り、処理を継続 if (gl) { // クリアカラーを黒色、不透明に設定する gl.clearColor(0.0, 0.0, 0.0, 1.0); // 深度テストを有効化 gl.enable(gl.DEPTH_TEST); // 近くにある物体は、遠くにある物体を覆い隠す gl.depthFunc(gl.LEQUAL); // カラーバッファや深度バッファをクリアする gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); } }
ここでは始めに、canvas への参照を取得して変数 canvas
に格納しています。canvas を繰り返し参照する必要がないことが明らかな場合は、この値をグローバルに持つことは避けて、ローカル変数またはオブジェクトのメンバフィールドに格納するとよいでしょう。
canvas を確保したら、WebGL コンテキストの初期化を行うinitWebGL()
関数 (後ほど定義します) を呼び出します。
コンテキストの初期化に成功すると、gl
がコンテキストへの参照になります。この例ではクリアカラーを黒に設定しますので、コンテキストはこの色でクリアします。続いて、コンテキストを設定パラメータで調節します。この例では深度テストの有効化と、近くのオブジェクトがより遠くにあるオブジェクトを覆い隠すことを指定しています。
以上が、コードで初期化処理のために行うことのすべてです。後ほど、実際に実行し始める方法を見てみましょう。
WebGL コンテキストを作成する
initWebGL()
関数は以下のようになります:
function initWebGL(canvas) { gl = null; try { // 標準コンテキストの取得を試みる。失敗した場合は、experimental にフォールバックする。 gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl"); } catch(e) {} // GL コンテキストを取得できない場合は終了する if (!gl) { alert("WebGL を初期化できません。ブラウザはサポートしていないようです。"); gl = null; } return gl; }
canvas の WebGL コンテキストを取得するため、canvas に "webgl" という名前のコンテキストを要求します。それが失敗した場合は、"experimental-webgl" という名前で要求します。両方とも失敗した場合は、ユーザに WebGL がサポートされていないことを知らせる通知を表示します。以上で、準備の処理は完了です。この時点で、gl
は null 値 (WebGL コンテキストが利用できない) またはレンダリングを行う WebGL コンテキストへの参照のどちらかになります。
以上で、Web GL コンテキストを正常に初期化するために充分なコードが揃いました。また、黒く塗りつぶされた大きな四角形が表示され、コンテンツの受け取りを待つ状態になっています。
WebGL コンテキストをリサイズする
新しい WebGL コンテキストのビューポートの解像度は、コンテキストを取得した瞬間の canvas 要素の、CSS を適用しない状態の高さおよび幅が設定されます。canvas 要素のスタイルを変更すると表示サイズが変化しますが、レンダリング解像度は変化しません。コンテキストを生成した後に canvas 要素の width および height 属性を変更した場合も、描画するピクセル数は変化しません。ドキュメント全体が canvas であるウィンドウをユーザがリサイズしたときや、アプリ内で調節可能なグラフィックス設定を提供したい場合など、WebGL の描画解像度を変更するには、変更を知らせるために WebGL コンテキストの viewport()
関数を呼び出さなければならないでしょう。
前出の例で使用した変数 gl
および canvas
の WebGL コンテキストで描画解像度を変更する方法は以下のとおりです:
gl.viewport(0, 0, canvas.width, canvas.height);
CSS によってディスプレイ上で占める解像度とは異なる解像度で描画した場合は、canvas でスケーリングを実行します。CSS によるリサイズはたいてい、低解像度レンダリングやブラウザによるアップスケーリングを可能にすることでリソースの節約に役立ちます。ダウンスケーリングでは super sample antialiasing (SSAA) エフェクトが発生する場合があります (ネイティブ解像度でも可能性があり、またパフォーマンスコストが高いエフェクトです)。可能かつ適切であれば、力ずくでこの処理を行ってブラウザの画像縮小アルゴリズムがきれいな結果をもたらすと期待するのではなく、MSAA やブラウザのテクスチャフィルタリングの実装に頼ることが最善です。
関連情報
- An introduction to WebGL: Luz Caballero が著し、dev.opera.com で公開しています。この記事では WebGL とは何かやどのように WebGL が動作するか (レンダリングパイプラインの概念を含む) を説明して、WebGL ライブラリをいくつか紹介しています。
- An intro to modern OpenGL: Joe Groff が OpenGL に関するすばらしい記事シリーズを著しており、OpenGL の歴史から重要なグラフィックスパイプラインの概念までの説明、およびどのように OpenGL が動作するかを示すデモを紹介しています。OpenGL の知識を持っていない場合は、ここから始めるとよいでしょう。