3D知識編では3D描画に関する知識について紹介しました。今度は実際にWebGL2を用いて描画してみましょう。3D知識編3D描画編(この記事)アニメーション編テクスチャ編3D描画プログラムの骨組みプログラムの大きな流れは基礎編のときとほとんど変わりません。ある程度整理した骨組みとなるコードを以下に示しておきます。Canvasを作成してbodyに追加します。シェーダを読み込みPromiseを返します。Programを返します。バーテックスシェーダをコンパイルします。フラグメントシェーダについても同様にします。シェーダプログラムを作成します。プログラムを使用します。バッファを作成し返します。シェーダを読み込み終わったら開始します。gl.flush();});ここに追加していきましょう。シェーダを書き換える今回の変更点は、すべてバーテックスシェーダ側です。3D知識編で説明した通り、いくつかの変換行列が必要になります。projectionの3つだけあればいいのですが、人によってはもっと細かく分けたり、逆にmvp行列としてひとつにまとめたりする人もいます。この辺りは好きにしていいでしょう。変換行列ですが、これは頂点ごとに異なる値を使うのではなく、すべての頂点で共通の値です。いった場合はin変数ではなく、uniform変数を使います。uniform変数は、どのシェーダからも読み出すことができる、定数のような変数です。変換行列は4行4列の行列(Matrix)ですので、mat4型を使います。1.0);}ここで変換行列をかける順番に注意してください。projectionの順でかけていきます。フラグメントシェーダに関してはそのままです。vColor;}設定を変更する3D描画をするためには、まずいくつかの設定を有効にしておきます。gl.enable(gl.CULL_FACE);ここではデプステストと背面カリングを有効化しておきます。これらの内容については、次の項目を読んでください。3D描画のための設定WebGL2には、3D描画のためのいくつかの設定があります。そのうちの主要なものだけ紹介したいと思います。order)基礎編では、三角形は反時計回りに頂点を配置すると言いました。これは設定で変更することができます。この設定のことをワインディングオーダーと言います。今回は設定は変更しませんが、変更できるということは覚えておきましょう。culling)負担を軽減するために無駄なポリゴン(三角形)を省く作業をカリングと言います。背面カリングはそのうちの代表的なもので、後ろを向いてるポリゴンを描画しないというものです。3Dグラフィックスを扱うならば有効化しておきましょう。test)デプステスト、あるいは深度テストは、その名の通り描画対象の「深さ」を調べるテストです。デフォルトでは奥行きを無視して後に描いたほうが手前にくる表示になりますが、普通は奥のものほど後ろに表示されて欲しいでしょう。デプステストを使えばこれを実現できます。WebGL2ではあらかじめデプスバッファと呼ばれるバッファが用意されており、フラグメント(ピクセル)ごとに深度値がここに書き込まれます。デプステストが有効化されていると、書き込もうとしているフラグメントの深度と現在の深度を比較して、デプステストに合格したフラグメントのみが書き込まれます。ここでの比較関数は自由に設定することができます。型抜きやマスクと呼ばれる機能が実現でききます。ステンシルバッファというマスクデータ用のバッファを用意しておき、ステンシルバッファと比較することで、ピクセルを描画する・しないを決定します。一般的に、画面の部分的な合成や、3Dモデルの縁取りなどに使われます。test)シザーテストは描画可能領域を設定します。デフォルトではビューポートと同一の範囲になっています。画面の一部のみをクリアしたい場合などに使用するといいでしょう。次にuniform変数用の変換行列を用意しましょう。何もないところから行列データを用意するのは大変なので、既存のライブラリを使用します。ここではglMatrixというライブラリを使用します。以下のURLからダウンロードしてください。http://glmatrix.net/ダウンロードしたらscript要素に追加します。defer></script>できたら変換行列を作成します。変換行列の値は適当で構いません。nearとfarは「Z座標」ではなく「距離」を表す。far);model行列、view行列、projection行列の用意がそれぞれできました。次はこれをuniform変数に書き込んでいきましょう。uniform変数の設定uniform変数はすべての頂点およびフラグメントで共通の値となる変数です。変換行列などはuniform変数を使用します。設定方法はin変数とそこまで変わりません。使用するメソッドが少々異なります。projection);位置を取得して書き込むのはin変数の時と変わりません。違うのは書き込むメソッドです。ここで使用しているuniformMatrix4fvはuniform変数に4行4列のfloat行列を書き込むメソッドです。他にもuniform3fvとすればvec3型の変数に書き込むメソッドになりますし、int型へ書き込むときはfのかわりにiとします。vのような命名規則になっています。少々面倒ですが、目的に応じたメソッドを使用してください。今回も単純な四角形を用意しましょう。今回は背面カリングを有効化しているので、ワインディングオーダーが反時計回りなことには、今まで以上に気をつけましょう。2]);実行結果さて、ここまで準備できたら後は実行するだけです。実際に実行してみましょう。立体的になった四角形が表示されたはずです。変換行列の値を様々に変えてみて、どうなるか試してみましょう。Canvasを作成してbodyに追加します。シェーダを読み込みPromiseを返します。Programを返します。バーテックスシェーダをコンパイルします。フラグメントシェーダについても同様にします。シェーダプログラムを作成します。プログラムを使用します。バッファを作成し返します。シェーダを読み込み終わったら開始します。nearとfarは「Z座標」ではなく「距離」を表す。Objectを使ってuniform変数を設定するuniform変数にはもうひとつ設定方法があります。Object(UBO)を使う方法です。uniform変数は通常ひとつのシェーダープログラムに結び付けられていますが、UBOを使えば複数のシェーダープログラムに結びつけることが可能になります。この利点は今の時点では全く無意味ですが、今の段階で使い方だけ学んでおきましょう。変数をuniformブロックで宣言するまずはシェーダーを書き換えます。個別にuniform変数として宣言していたものをブロックとして宣言し直します。1.0);}uniformブロックには名前をつける必要があります。ここではMatricesとしています。メモリレイアウトを指定をlayoutでしておくと便利です。レイアウトに指定できるのはstd140のみです。レイアウトの指定を省略すると、メモリ上の配置がどうなるか環境依存になってしまい、何が起こるかわかりません。uniformブロックに書き込むuniform変数への書き込み部分を全く書き換えてしまいます。ブロックのインデックスを取得します。バインディングポイントを好きに指定します。uniformブロックをバインディングポイントにバインドします。バッファを作り、書き込みます。バッファをバインディングポイントにバインドします。uniformBuffer);手順はコメントの通りです。uniformブロックへ書き込むときは、個別の変数にではなく、一度にまとめて書き込みます。実行するそれでは実行してみてください。同じように四角形が表示されるはずです。Switchにウェブブラウザが搭載されたら、どの程度のことができるのかRSSプロフィール古都ことふるみやことです。フロントエンドとかいろいろやるよ。