Webgl-quick-guide
WebGL-はじめに
数年前、Javaアプリケーション(アプレットとJOGLの組み合わせ)を使用して、GPU(Graphical Processing Unit)に対応することにより、Web上の3Dグラフィックを処理していました。 アプレットを実行するにはJVMが必要なため、Javaアプレットに依存することが難しくなりました。 数年後、人々はJavaアプレットの使用をやめました。
Adobe(Flash、AIR)が提供するStage3D APIは、GPUハードウェアアクセラレーションアーキテクチャを提供しました。 これらのテクノロジーを使用して、プログラマーはWebブラウザーとIOSおよびAndroidプラットフォームで2Dおよび3D機能を備えたアプリケーションを開発できます。 Flashは独自のソフトウェアであったため、Web標準としては使用されませんでした。
2011年3月に、WebGLがリリースされました。 JVMなしで実行できるオープンウェアです。 Webブラウザーによって完全に制御されます。
HTML 5の新しいリリースには、2D Canvas、WebGL、SVG、3D CSSトランスフォーム、SMILなどの3Dグラフィックスをサポートするいくつかの機能があります。 このチュートリアルでは、WebGLの基本について説明します。
OpenGLとは何ですか?
OpenGL(Open Graphics Library)は、2Dおよび3Dグラフィックス向けのクロス言語、クロスプラットフォームAPIです。 コマンドのコレクションです。 OpenGL4.5はOpenGLの最新バージョンです。 次の表に、OpenGLに関連する一連のテクノロジーを示します。
API | Technology Used |
---|---|
OpenGL ES | It is the library for 2D and 3D graphics on embedded systems - including consoles, phones, appliances, and vehicles. OpenGL ES 3.1 is its latest version. It is maintained by the Khronos Group www.khronos.org |
JOGL | It is the Java binding for OpenGL. JOGL 4.5 is its latest version and it is maintained by jogamp.org. |
WebGL | It is the JavaScript binding for OpenGL. WebGL 1.0 is its latest version and it is maintained by the khronos group. |
OpenGLSL | OpenGL Shading Language. It is a programming language which is a companion to OpenGL 2.0 and higher. It is a part of the core OpenGL 4.4 specification. It is an API specifically tailored for embedded systems such as those present on mobile phones and tablets. |
注意-WebGLでは、GLSLを使用してシェーダーを記述します。
WebGLとは何ですか?
WebGL(Web Graphics Library)は、Web上の3Dグラフィックスの新しい標準です。2Dグラフィックスとインタラクティブな3Dグラフィックスをレンダリングする目的で設計されています。 これは、電話やその他のモバイルデバイス向けの低レベル3D APIであるOpenGLのES 2.0ライブラリから派生しています。 WebGLはES 2.0(Embedded Systems)と同様の機能を提供し、最新の3Dグラフィックスハードウェアで良好に機能します。
これは、HTML5で使用できるJavaScript APIです。 WebGLコードは、HTML5の<canvas>タグ内に記述されます。 これは、インターネットブラウザーが使用されたコンピューター上のグラフィック処理ユニット(GPU)にアクセスできるようにする仕様です。
WebGLの開発者
*Vladimir Vukicevic* という名前のアメリカとセルビアのソフトウェアエンジニアが基盤を作り、WebGLの作成を主導しました
- 2007年、ウラジミールはHTMLドキュメントのCanvas要素の OpenGL プロトタイプの作業を開始しました。
- 2011年3月、Kronos GroupはWebGLを作成しました。
レンダリング
レンダリングとは、コンピュータープログラムを使用してモデルから画像を生成するプロセスです。 グラフィックスでは、仮想シーンは、レンダリングプログラムを介して渡されるジオメトリ、視点、テクスチャ、照明、シェーディングなどの情報を使用して記述されます。 このレンダープログラムの出力はデジタル画像になります。
レンダリングには2種類あります-
- ソフトウェアレンダリング-すべてのレンダリング計算はCPUの助けを借りて行われます。
- ハードウェアレンダリング-すべてのグラフィックス計算はGPU(グラフィックスプロセッシングユニット)によって行われます。
レンダリングはローカルまたはリモートで実行できます。 レンダリングされる画像が非常に複雑な場合、レンダリングは、複雑なシーンをレンダリングするのに必要な十分なハードウェアリソースを備えた専用サーバーでリモートで実行されます。 *サーバーベースのレンダリング*とも呼ばれます。 レンダリングはCPUによってローカルで実行することもできます。 *クライアントベースのレンダリング*と呼ばれます。
WebGLは、クライアントベースのレンダリングアプローチに従って3Dシーンをレンダリングします。 画像の取得に必要なすべての処理は、クライアントのグラフィックスハードウェアを使用してローカルで実行されます。
GPU
NVIDIAによると、GPUは「変換、照明、三角形のセットアップ/クリッピング、レンダリングエンジンを統合したシングルチッププロセッサであり、1秒間に最低1,000万ポリゴンを処理できます」。順次処理用に最適化されたいくつかのコアを備えたマルチコアプロセッサとは異なり、GPUは並列ワークロードを効率的に処理する数千の小さなコアで構成されています。 したがって、GPUは、ディスプレイへの出力を目的としたフレームバッファー(完全なフレームデータを含むRAMの一部)でのイメージの作成を高速化します。
GPU加速コンピューティング
GPU加速コンピューティングでは、アプリケーションはCPUにロードされます。 コードの*計算集約*部分に遭遇するたびに、コードのその部分が読み込まれ、GPUで実行されます。 システムにグラフィックスを効率的な方法で処理する能力を与えます。
GPUには個別のメモリがあり、一度にコードの小さな部分の複数のコピーを実行します。 GPUは、中央メモリではなく、ローカルメモリにあるすべてのデータを処理します。 したがって、GPUで処理する必要があるデータは、GPUメモリにロード/コピーしてから処理する必要があります。
上記のアーキテクチャを備えたシステムでは、3Dプログラムの処理を高速化するために、CPUとGPU間の通信オーバーヘッドを減らす必要があります。 そのためには、GPUと繰り返し通信するのではなく、すべてのデータをコピーしてGPUに保持する必要があります。
サポートされているブラウザ
次の表は、WebGLをサポートするブラウザのリストを示しています-
ウェブブラウザー
Browser Name | Version | Support |
---|---|---|
Internet Explorer | 11 and above | Complete support |
Google Chrome | 39 and above | Complete support |
Safari | 8 | Complete support |
Firefox | 36 and above | Partial support |
Opera | 27 and above | Partial support |
モバイルブラウザ
Browser Name | Version | Support |
---|---|---|
Chrome for Android | 42 | Partial support |
Android browser | 40 | Partial support |
IOS Safari | 8.3 | Complete support |
Opera Mini | 8 | Does not support |
Blackberry Browser | 10 | Complete support |
IE mobile | 10 | Partial support |
WebGLの利点
WebGLを使用する利点は次のとおりです-
- * JavaScriptプログラミング*-WebGLアプリケーションはJavaScriptで記述されています。 これらのアプリケーションを使用すると、HTMLドキュメントの他の要素と直接やり取りできます。 他のJavaScriptライブラリを使用することもできます(例: JQuery)およびHTMLテクノロジーを使用して、WebGLアプリケーションを強化します。
- モバイルブラウザでのサポートの増加-WebGLは、iOSサファリ、Androidブラウザ、Chrome for Androidなどのモバイルブラウザもサポートします。
- オープンソース-WebGLはオープンソースです。 ライブラリのソースコードにアクセスして、ライブラリの機能と開発方法を理解できます。
- コンパイルの必要はありません-JavaScriptはプログラミングとハーフHTMLの半分のコンポーネントです。 このスクリプトを実行するために、ファイルをコンパイルする必要はありません。 代わりに、任意のブラウザを使用してファイルを直接開き、結果を確認できます。 WebGLアプリケーションはJavaScriptを使用して開発されているため、WebGLアプリケーションもコンパイルする必要はありません。
- 自動メモリ管理-JavaScriptは自動メモリ管理をサポートしています。 手動でメモリを割り当てる必要はありません。 WebGLはJavaScriptのこの機能を継承します。
- 設定が簡単-WebGLはHTML 5に統合されているため、追加の設定は不要です。 WebGLアプリケーションを作成するために必要なものは、テキストエディタとWebブラウザだけです。
環境設定
WebGLに別の環境を設定する必要はありません。 WebGLをサポートするブラウザーには、WebGL用の独自の組み込みセットアップがあります。
WebGL-Html5 Canvasの概要
Web上でグラフィカルアプリケーションを作成するために、HTML-5は、2D Canvas、WebGL、SVG、3D CSSトランスフォーム、SMILなどの豊富な機能セットを提供します。 WebGLアプリケーションを作成するには、HTML-5の既存のキャンバス要素を使用します。 この章では、HTML-5 2Dキャンバス要素の概要を説明します。
HTML5 Canvas
HTML-5 <canvas> は、JavaScriptを使用してグラフィックを描画するための簡単で強力なオプションを提供します。 グラフの描画、写真の合成、または単純な(それほど単純ではない)アニメーションの作成に使用できます。
これは、2つの特定の属性 width と height に加えて、id、name、classなどのすべてのコアHTML-5属性を持つ単純な <canvas> 要素です。
構文
HTMLキャンバスタグの構文は次のとおりです。 二重引用符( "")内でキャンバスの名前を言及する必要があります。
<canvas id = "mycanvas" width = "100" height = "100"></canvas>
キャンバスの属性
canvasタグには、id、width、およびheightの3つの属性があります。
- Id -Idは、_Document Object Model(DOM)_のキャンバス要素の識別子を表します。
- 幅-幅はキャンバスの幅を表します。
- 高さ-高さはキャンバスの高さを表します。
これらの属性は、キャンバスのサイズを決定します。 プログラマーがcanvasタグの下でそれらを指定していない場合、Firefox、Chrome、Web Kitなどのブラウザーは、デフォルトでサイズ300×150のcanvas要素を提供します。
例-キャンバスを作成する
次のコードは、キャンバスを作成する方法を示しています。 CSSを使用して、キャンバスに色付きの境界線を付けました。
<html>
<head>
<style>
#mycanvas{border:1px solid red;}
</style>
</head>
<body>
<canvas id = "mycanvas" width = "100" height = "100"></canvas>
</body>
</html>
実行すると、上記のコードは次の出力を生成します-
レンダリングコンテキスト
<canvas>は最初は空白です。 キャンバス要素に何かを表示するには、スクリプト言語を使用する必要があります。 このスクリプト言語は、レンダリングコンテキストにアクセスして描画する必要があります。
canvas要素には、* getContext()というDOMメソッドがあります。これは、レンダリングコンテキストとその描画関数を取得するために使用されます。 このメソッドは、1つのパラメーター、コンテキストのタイプ *2d を取ります。
次のコードは、必要なコンテキストを取得するために記述されます。 以下に示すように、このスクリプトをbodyタグ内に記述できます。
<!DOCTYPE HTML>
<html>
<body>
<canvas id = "mycanvas" width = "600" height = "200"></canvas>
<script>
var canvas = document.getElementById('mycanvas');
var context = canvas.getContext('2d');
context.font = '20pt Calibri';
context.fillStyle = 'green';
context.fillText('Welcome to finddevguides', 70, 70);
</script>
</body>
</html>
実行すると、上記のコードは次の出力を生成します-
HTML-5 2D Canvasの例については、次のリンクリンクを確認してください:/html5/html5_canvas [HTML-5 Canvas]。
WebGLコンテキスト
HTML5 Canvasは、WebGLアプリケーションの作成にも使用されます。 canvas要素でWebGLレンダリングコンテキストを作成するには、* canvas.getContext()メソッドに *2d の代わりに文字列 experimental-webgl を渡す必要があります。 一部のブラウザは「 webgl 」のみをサポートしています。
<!DOCTYPE html>
<html>
<canvas id = 'my_canvas'></canvas>
<script>
var canvas = document.getElementById('my_canvas');
var gl = canvas.getContext('experimental-webgl');
gl.clearColor(0.9,0.9,0.8,1);
gl.clear(gl.COLOR_BUFFER_BIT);
</script>
</html>
実行すると、上記のコードは次の出力を生成します-
WebGL-基本
WebGLは、主に3D APIではなく低レベルのラスタライズAPIです。 WebGLを使用して画像を描画するには、画像を表すベクトルを渡す必要があります。 次に、OpenGL SLを使用して、指定されたベクトルをピクセル形式に変換し、画面に画像を表示します。 WebGLアプリケーションの作成には、この章で説明する一連の手順が含まれます。
WebGL-座標系
他の3Dシステムと同様に、WebGLにはx、y、z軸があり、 z 軸は depth を示します。 WebGLの座標は、(1、1、1)および(-1、-1、-1)に制限されています。 つまり、WebGLグラフィックを投影する画面をキューブと見なす場合、キューブの1つのコーナーは(1、1、1)になり、反対側のコーナーは(-1、-1、-1)になります。 WebGLは、これらの境界を越えて描画されるものを表示しません。
次の図は、WebGL座標系を示しています。 Z軸は深さを示します。 zの正の値は、オブジェクトがスクリーン/ビューアーの近くにあることを示し、zの負の値は、オブジェクトがスクリーンから離れていることを示します。 同様に、xの正の値は、オブジェクトが画面の右側にあることを示し、負の値は、オブジェクトが左側にあることを示します。 同様に、yの正と負の値は、オブジェクトが画面の上部にあるか下部にあるかを示します。
WebGLグラフィックス
キャンバスオブジェクトのWebGLコンテキストを取得したら、JavaScriptのWebGL APIを使用してグラフィカル要素の描画を開始できます。
WebGLを開始する前に知っておく必要がある基本的な用語を次に示します。
頂点
一般に、ポリゴンなどのオブジェクトを描画するには、平面上のポイントをマークし、それらを結合して目的のポリゴンを形成します。 *頂点*は、3Dオブジェクトのエッジの結合を定義するポイントです。 それぞれx、y、z軸を表す3つの浮動小数点値で表されます。
例
次の例では、次の頂点を持つ三角形を描画しています-(0.5、0.5)、(-0.5、0.5)、(-0.5、-0.5)。
注-JavaScript配列を使用してこれらの頂点を手動で保存し、頂点バッファーを使用してWebGLレンダリングパイプラインに渡す必要があります。
指標
WebGLでは、数値を使用して頂点を識別します。 これらの数値はインデックスとして知られています。 これらのインデックスは、WebGLでメッシュを描画するために使用されます。
注-頂点と同様に、JavaScript配列を使用してインデックスを保存し、インデックスバッファーを使用してWebGLレンダリングパイプラインに渡します。
配列
OpenGLやJoGLとは異なり、頂点を直接レンダリングするためのWebGLには事前定義されたメソッドはありません。 JavaScript配列を使用して手動で保存する必要があります。
例
var vertices = [ 0.5, 0.5, 0.1,-0.5, 0.5,-0.5]
バッファ
バッファは、データを保持するWebGLのメモリ領域です。 描画バッファ、フレームバッファ、ベテックスバッファ、インデックスバッファなど、さまざまなバッファがあります。 vertex buffer および index buffer は、モデルのジオメトリを記述および処理するために使用されます。
頂点バッファーオブジェクトは頂点に関するデータを格納し、インデックスバッファーオブジェクトはインデックスに関するデータを格納します。 頂点を配列に格納した後、これらのBufferオブジェクトを使用して頂点をWegGLグラフィックパイプラインに渡します。
- フレームバッファ*は、シーンデータを保持するグラフィックメモリの一部です。 このバッファーには、表面の幅と高さ(ピクセル単位)、各ピクセルの色、深さ、ステンシルバッファーなどの詳細が含まれます。
Mesh
2Dまたは3Dオブジェクトを描画するために、WebGL APIは2つのメソッド、つまり* drawArrays()および drawElements()を提供します。 これら2つのメソッドは、描画するオブジェクトを選択できる *mode というパラメーターを受け入れます。 このフィールドで提供されるオプションは、ポイント、ライン、および三角形に制限されています。
これらの2つの方法を使用して3Dオブジェクトを描画するには、ポイント、ライン、または三角形を使用して1つ以上のプリミティブポリゴンを構築する必要があります。 その後、これらのプリミティブポリゴンを使用して、メッシュを形成できます。
プリミティブポリゴンを使用して描画された3Dオブジェクトは、*メッシュ*と呼ばれます。 WebGLは3Dグラフィカルオブジェクトを描画するいくつかの方法を提供しますが、ユーザーは通常メッシュを描画することを好みます。
例
次の例では、2つの三角形→\ {1、2、3}および\ {4、1、3}を使用して正方形を描いていることがわかります。
シェーダープログラム
通常、三角形を使用してメッシュを構築します。 WebGLはGPUアクセラレーションコンピューティングを使用するため、これらの三角形に関する情報はCPUからGPUに転送される必要があり、通信のオーバーヘッドが大きくなります。
WebGLは、通信のオーバーヘッドを削減するソリューションを提供します。 GPUで実行されるES SL(Embedded System Shader Language)を使用するため、* shaderプログラム*(OpenGL ES Shading Language/GLSL を使用して記述するプログラム)を使用して、クライアントシステムにグラフィカル要素を描画するために必要なすべてのプログラムを記述します)。
これらのシェーダーはGPU用のプログラムであり、シェーダープログラムの記述に使用される言語はGLSLです。 これらのシェーダーでは、頂点、変換、マテリアル、ライト、カメラが相互作用して特定の画像を作成する方法を正確に定義します。
つまり、メッシュのピクセルを取得するアルゴリズムを実装するスニペットです。 シェーダーについては、後の章で詳しく説明します。 シェーダーには、頂点シェーダーとフラグメントシェーダーの2種類があります。
頂点シェーダー
Vertextシェーダーは、すべての頂点で呼び出されるプログラムコードです。 ジオメトリ(例:三角形)をある場所から別の場所に変換(移動)するために使用されます。 頂点座標、法線、色、テクスチャ座標など、各頂点のデータ(頂点ごとのデータ)を処理します。
頂点シェーダーの ES GL コードでは、プログラマはデータを処理する属性を定義する必要があります。 これらの属性は、JavaScriptで記述された Vertex Buffer Object を指します。
次のタスクは、頂点シェーダーを使用して実行できます-
- 頂点変換
- 通常の変換と正規化
- テクスチャ座標生成
- テクスチャ座標変換
- 点灯
- 色材用途
フラグメントシェーダー(ピクセルシェーダー)
メッシュは複数の三角形で形成され、各三角形の表面は*フラグメント*として知られています。 フラグメントシェーダーは、すべてのフラグメントのすべてのピクセルで実行されるコードです。 _個々のピクセル_の色を計算して塗りつぶすために書かれています。
以下のタスクは、フラグメントシェーダーを使用して実行できます-
- 補間値の操作
- テクスチャアクセス
- テクスチャアプリケーション
- Fog
- 色の合計
OpenGL ES SL変数
*OpenGL ES SL* の完全な形式は、OpenGL Embedded System Shading Languageです。 シェーダープログラムでデータを処理するために、ES SLは3種類の変数を提供します。 彼らは次のとおりです-
- 属性-これらの変数は、頂点シェーダープログラムの入力値を保持します。 属性は、頂点ごとのデータを含む頂点バッファーオブジェクトを指します。 頂点シェーダーが呼び出されるたびに、属性は異なる頂点のVBOを指します。
- Uniforms -これらの変数は、ライトポジション、テクスチャ座標、色など、頂点シェーダーとフラグメントシェーダーの両方に共通の入力データを保持します。
- 変数-これらの変数は、頂点シェーダーからフラグメントシェーダーにデータを渡すために使用されます。
これだけ多くの基本事項があるので、次にグラフィックスパイプラインについて説明します。
WebGL-グラフィックパイプライン
3Dグラフィックスをレンダリングするには、一連の手順に従う必要があります。 これらのステップは*グラフィックスパイプライン*または*レンダリングパイプライン*と呼ばれます。 次の図は、WebGLグラフィックパイプラインを示しています。
次のセクションでは、パイプラインの各ステップの役割を1つずつ説明します。
JavaScript
WebGLアプリケーションの開発中に、GPUと通信するシェーダー言語コードを作成します。 JavaScriptは、次のアクションを含むプログラムの制御コードを記述するために使用されます-
- * WebGLの初期化*-JavaScriptを使用してWebGLコンテキストを初期化します。
- 配列の作成-ジオメトリのデータを保持するJavaScript配列を作成します。
- バッファオブジェクト-配列をパラメータとして渡すことにより、バッファオブジェクト(頂点とインデックス)を作成します。
- シェーダー-JavaScriptを使用してシェーダーを作成、コンパイル、リンクします。
- 属性-属性を作成し、有効にし、JavaScriptを使用してバッファオブジェクトに関連付けることができます。
- ユニフォーム-JavaScriptを使用してユニフォームを関連付けることもできます。
- 変換マトリックス-JavaScriptを使用して、変換マトリックスを作成できます。
最初に、必要なジオメトリのデータを作成し、バッファーの形でシェーダーに渡します。 シェーダー言語の属性変数は、頂点シェーダーへの入力として渡されるバッファーオブジェクトを指します。
頂点シェーダー
メソッド* drawElements()および drawArray()を呼び出してレンダリングプロセスを開始すると、頂点バッファーオブジェクトで提供される各頂点に対して頂点シェーダーが実行されます。 プリミティブポリゴンの各頂点の位置を計算し、さまざまな *gl_position に格納します。 また、通常は頂点に関連付けられている*色、テクスチャ座標*、*頂点*などの他の属性も計算します。
プリミティブアセンブリ
各頂点の位置とその他の詳細を計算した後、次のフェーズは*プリミティブアセンブリステージ*です。 ここで三角形が組み立てられ、ラスタライザに渡されます。
ラスタライズ
ラスタライズのステップでは、プリミティブの最終画像のピクセルが決定されます。 それには2つのステップがあります-
- カリング-最初に、多角形の向き(正面か背面か)が決定されます。 ビュー領域に表示されない不適切な向きの三角形はすべて破棄されます。 このプロセスはカリングと呼ばれます。
- クリッピング-三角形の一部が表示領域の外側にある場合、表示領域の外側の部分は削除されます。 このプロセスはクリッピングと呼ばれます。
フラグメントシェーダ
フラグメントシェーダーは
- さまざまな変数の頂点シェーダーからのデータ、
- ラスタライズステージのプリミティブ、そして
- 頂点間の各ピクセルのカラー値を計算します。
フラグメントシェーダーは、各フラグメントのすべてのピクセルのカラー値を保存します。 これらのカラー値は、フラグメント操作中にアクセスできます。これについては、次に説明します。
フラグメント操作
フラグメント操作は、プリミティブの各ピクセルの色を決定した後に実行されます。 これらのフラグメント操作には、次のものが含まれる場合があります-
- 深さ
- カラーバッファーブレンド *ディザリング
すべてのフラグメントが処理されると、2Dイメージが形成され、画面に表示されます。* フレームバッファ*は、レンダリングパイプラインの最終的な宛先です。
フレームバッファ
フレームバッファは、シーンデータを保持するグラフィックメモリの一部です。 このバッファーには、表面の幅と高さ(ピクセル単位)、各ピクセルの色、深度バッファーとステンシルバッファーなどの詳細が含まれます。
WebGL-サンプルアプリケーション
WebGLとWebGLパイプライン(グラフィックアプリケーションをレンダリングするための手順)の基本について説明しました。 この章では、サンプルアプリケーションを使用して、WebGLを使用して三角形を作成し、アプリケーションで実行される手順を観察します。
WebGLアプリケーションの構造
WebGLアプリケーションコードは、JavaScriptとOpenGLシェーダー言語の組み合わせです。
- CPUと通信するにはJavaScriptが必要です
- GPUとの通信にはOpenGLシェーダー言語が必要です。
サンプルアプリケーション
次に、WebGLを使用して2D座標を持つ単純な三角形を描画する方法を学ぶために、簡単な例を見てみましょう。
<!doctype html>
<html>
<body>
<canvas width = "300" height = "300" id = "my_Canvas"></canvas>
<script>
/*Step1: Prepare the canvas and get WebGL context*/
var canvas = document.getElementById('my_Canvas');
var gl = canvas.getContext('experimental-webgl');
/*Step2: Define the geometry and store it in buffer objects*/
var vertices = [-0.5, 0.5, -0.5, -0.5, 0.0, -0.5,];
//Create a new buffer object
var vertex_buffer = gl.createBuffer();
//Bind an empty array buffer to it
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
//Pass the vertices data to the buffer
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
//Unbind the buffer
gl.bindBuffer(gl.ARRAY_BUFFER, null);
/*Step3: Create and compile Shader programs*/
//Vertex shader source code
var vertCode =
'attribute vec2 coordinates;' +
'void main(void) {' + ' gl_Position = vec4(coordinates,0.0, 1.0);' + '}';
//Create a vertex shader object
var vertShader = gl.createShader(gl.VERTEX_SHADER);
//Attach vertex shader source code
gl.shaderSource(vertShader, vertCode);
//Compile the vertex shader
gl.compileShader(vertShader);
//Fragment shader source code
var fragCode = 'void main(void) {' + 'gl_FragColor = vec4(0.0, 0.0, 0.0, 0.1);' + '}';
//Create fragment shader object
var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
//Attach fragment shader source code
gl.shaderSource(fragShader, fragCode);
//Compile the fragment shader
gl.compileShader(fragShader);
//Create a shader program object to store combined shader program
var shaderProgram = gl.createProgram();
//Attach a vertex shader
gl.attachShader(shaderProgram, vertShader);
//Attach a fragment shader
gl.attachShader(shaderProgram, fragShader);
//Link both programs
gl.linkProgram(shaderProgram);
//Use the combined shader program object
gl.useProgram(shaderProgram);
/*Step 4: Associate the shader programs to buffer objects*/
//Bind vertex buffer object
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
//Get the attribute location
var coord = gl.getAttribLocation(shaderProgram, "coordinates");
//point an attribute to the currently bound VBO
gl.vertexAttribPointer(coord, 2, gl.FLOAT, false, 0, 0);
//Enable the attribute
gl.enableVertexAttribArray(coord);
/*Step5: Drawing the required object (triangle)*/
//Clear the canvas
gl.clearColor(0.5, 0.5, 0.5, 0.9);
//Enable the depth test
gl.enable(gl.DEPTH_TEST);
//Clear the color buffer bit
gl.clear(gl.COLOR_BUFFER_BIT);
//Set the view port
gl.viewport(0,0,canvas.width,canvas.height);
//Draw the triangle
gl.drawArrays(gl.TRIANGLES, 0, 3);
</script>
</body>
</html>
それは次の結果を生成します-
上記のプログラムを注意深く観察すると、WebGLを使用して単純な三角形を描くために5つの連続した手順を実行しました。 手順は次のとおりです-
ステップ1-キャンバスを準備し、WebGLレンダリングコンテキストを取得します
現在のHTMLキャンバスオブジェクトを取得し、そのWebGLレンダリングコンテキストを取得します。
ステップ2-ジオメトリを定義し、バッファオブジェクトに保存します
頂点、インデックス、色などのジオメトリの属性を定義し、JavaScript配列に保存します。 次に、1つ以上のバッファーオブジェクトを作成し、データを含む配列をそれぞれのバッファーオブジェクトに渡します。 この例では、三角形の頂点をJavaScript配列に保存し、この配列を頂点バッファーオブジェクトに渡します。
ステップ3-シェーダープログラムの作成とコンパイル
頂点シェーダーおよびフラグメントシェーダープログラムを作成し、コンパイルし、これら2つのプログラムをリンクすることにより、結合プログラムを作成します。
ステップ4-シェーダープログラムをバッファオブジェクトに関連付ける
バッファーオブジェクトと結合されたシェーダープログラムを関連付けます。
ステップ5-必要なオブジェクト(三角形)の描画
この手順には、色のクリア、バッファビットのクリア、深度テストの有効化、ビューポートの設定などの操作が含まれます。 最後に、* drawArrays()または drawElements()*のいずれかのメソッドを使用して、必要なプリミティブを描画する必要があります。
これらのすべての手順については、このチュートリアルでさらに説明します。
WebGL-コンテキスト
WebGLアプリケーションを作成するための最初のステップは、WebGLレンダリングコンテキストオブジェクトを取得することです。 このオブジェクトは、WebGL描画バッファーと対話し、すべてのWebGLメソッドを呼び出すことができます。 次の操作は、WebGLコンテキストを取得するために実行されます-
- HTML-5キャンバスを作成する
- キャンバスIDを取得する
- WebGLを入手する
HTML-5 Canvas要素の作成
第5章では、HTML-5キャンバス要素の作成方法について説明しました。 HTML-5ドキュメントの本文内で、キャンバスを作成し、名前を付けて、パラメーターidにパラメーターとして渡します。 幅と高さの属性を使用して、キャンバスの寸法を定義できます(オプション)。
例
次の例は、寸法500×500のキャンバス要素を作成する方法を示しています。 可視性のためにCSSを使用して、キャンバスに境界線を作成しました。 次のコードをコピーして、 my_canvasl という名前のファイルに貼り付けます。
<!DOCTYPE HTML>
<html>
<head>
<style>
#mycanvas{border:1px solid blue;}
</style>
</head>
<body>
<canvas id = "mycanvas" width = "300" height = "300"></canvas>
</body>
</html>
それは次の結果を生成します-
キャンバスIDを取得する
キャンバスを作成したら、WebGLコンテキストを取得する必要があります。 WebGL描画コンテキストを取得する最初のことは、現在のキャンバス要素のIDを取得することです。
キャンバスIDは、DOM(ドキュメントオブジェクトモデル)メソッド* getElementById()*を呼び出すことによって取得されます。 このメソッドはパラメーターとして文字列値を受け入れるため、現在のキャンバスの名前を渡します。
たとえば、キャンバス名が my_canvas の場合、以下に示すようにキャンバスIDが取得されます-
var canvas = document.getElementById('my_Canvas');
WebGL描画コンテキストを取得します
WebGLRenderingContextオブジェクト(またはWebGL描画コンテキストオブジェクトまたは単にWebGLコンテキスト)を取得するには、現在の HTMLCanvasElement の* getContext()*メソッドを呼び出します。 getContext()の構文は次のとおりです-
canvas.getContext(contextType, contextAttributes);
文字列 webgl または experimental-webgl を contentType として渡します。 contextAttributes パラメーターはオプションです。 (この手順を進める間、ブラウザが[.underline]#WebGL#バージョン1(OpenGL ES 2.0)を実装していることを確認してください)。
次のコードスニペットは、WebGLレンダリングコンテキストを取得する方法を示しています。 ここで、 gl は取得したコンテキストオブジェクトへの参照変数です。
var canvas = document.getElementById('my_Canvas');
var gl = canvas.getContext('experimental-webgl');
WebGLContextAttributes
パラメーター WebGLContextAttributes は必須ではありません。 このパラメータは、以下にリストされているブール値を受け入れるさまざまなオプションを提供します-
Sr.No. | Attributes & Description |
---|---|
1 |
Alpha 値がtrueの場合、キャンバスにアルファバッファーを提供します。 デフォルトでは、その値はtrueです。 |
2 |
depth 値がtrueの場合、少なくとも16ビットの深度バッファーを含む描画バッファーを取得します。 デフォルトでは、その値はtrueです。 |
3 |
stencil 値がtrueの場合、少なくとも8ビットのステンシルバッファーを含む描画バッファーを取得します。 デフォルトでは、その値はfalseです。 |
4 |
antialias 値がtrueの場合、アンチエイリアスを実行する描画バッファーを取得します。 デフォルトでは、その値はtrueです。 |
5 |
premultipliedAlpha 値がtrueの場合、アルファが事前に乗算された色を含む描画バッファーを取得します。 デフォルトでは、その値はtrueです。 |
6 |
preserveDrawingBuffer その値がtrueの場合、バッファーはクリアされず、作成者によってクリアまたは上書きされるまで値が保持されます。 デフォルトでは、その値はfalseです。 |
次のコードスニペットは、 anti-aliasing を実行しないステンシルバッファーを使用してWebGLコンテキストを作成する方法を示しています。
var canvas = document.getElementById('canvas1');
var context = canvas.getContext('webgl', { antialias: false, stencil: true });
WebGLRenderingContextの作成時に、描画バッファーが作成されます。 ContextオブジェクトはOpenGLの状態を管理し、描画バッファーにレンダリングします。
WebGLRenderingContext
これはWebGLの主要なインターフェイスです。 WebGL描画コンテキストを表します。 このインターフェイスには、描画バッファでさまざまなタスクを実行するために使用されるすべてのメソッドが含まれています。 このインターフェイスの属性を次の表に示します。
Sr.No. | Attributes & Description |
---|---|
1 |
Canvas これは、このコンテキストを作成したキャンバス要素への参照です。 |
2 |
drawingBufferWidth この属性は、描画バッファーの実際の幅を表します。 HTMLCanvasElementのwidth属性とは異なる場合があります。 |
3 |
drawingBufferHeight この属性は、描画バッファーの実際の高さを表します。 HTMLCanvasElementのheight属性とは異なる場合があります。 |
WebGL-ジオメトリ
WebGLコンテキストを取得したら、プリミティブ(描画するオブジェクト)のジオメトリを定義して保存する必要があります。 WebGLでは、JavaScript配列を使用して、頂点、インデックス、プリミティブの色などのジオメトリの詳細を定義します。 これらの詳細をシェーダープログラムに渡すには、バッファーオブジェクトを作成し、それぞれのバッファーにデータを含むJavaScript配列を格納(アタッチ)する必要があります。
- 注意:*これらのバッファオブジェクトは、シェーダープログラム(頂点シェーダー)の属性に関連付けられます。
必要なジオメトリの定義
頂点を使用して描画された2Dまたは3Dモデルは、*メッシュ*と呼ばれます。 メッシュ内の各ファセットは*ポリゴン*と呼ばれ、ポリゴンは3つ以上の頂点で構成されます。
WebGLレンダリングコンテキストでモデルを描画するには、JavaScript配列を使用して頂点とインデックスを定義する必要があります。 たとえば、図に示すように、座標\ {(5,5)、(-5,5)、(-5、-5)}にある三角形を作成する場合、配列を作成できます頂点の場合-
var vertices = [
0.5,0.5, //Vertex 1
0.5,-0.5, //Vertex 2
-0.5,-0.5, //Vertex 3
];
同様に、インデックスの配列を作成できます。 上記の三角形のインデックスのインデックスは[0、1、2]になり、次のように定義できます-
var indices = [ 0,1,2 ]
インデックスの理解を深めるために、正方形のようなより複雑なモデルを検討してください。 正方形を2つの三角形のセットとして表すことができます。 (0,3,1)と(3,1,2)が正方形を描く2つの三角形である場合、インデックスは次のように定義されます-
var indices = [0,3,1,3,1,2];
注-
プリミティブを描画するために、WebGLは次の2つの方法を提供します-
- * drawArrays()*-このメソッドを使用しながら、JavaScript配列を使用してプリミティブの頂点を渡します。
- * drawElements()*-このメソッドを使用している間、JavaScript配列を使用してプリミティブの頂点とインデックスの両方を渡します。
バッファオブジェクト
バッファオブジェクトは、システムに割り当てられたメモリ領域を示すWebGLが提供するメカニズムです。 これらのバッファオブジェクトには、頂点、インデックス、色などに対応する、描画するモデルのデータを保存できます。
これらのバッファーオブジェクトを使用すると、属性変数の1つを介してシェーダープログラム(頂点シェーダー)に複数のデータを渡すことができます。 これらのバッファオブジェクトはGPUメモリに常駐するため、直接レンダリングでき、パフォーマンスが向上します。
ジオメトリを処理するには、2種類のバッファオブジェクトがあります。 彼らは-
- 頂点バッファオブジェクト(VBO)-レンダリングされるグラフィカルモデルの頂点ごとのデータを保持します。 WebGLで頂点バッファーオブジェクトを使用して、頂点座標、法線、色、テクスチャ座標などの頂点に関するデータを格納および処理します。
- インデックスバッファオブジェクト(IBO)-レンダリングされるグラフィカルモデルのインデックス(インデックスデータ)を保持します。
必要なジオメトリを定義し、JavaScript配列に格納した後、これらの配列をバッファーオブジェクトに渡し、そこからデータがシェーダープログラムに渡される必要があります。 バッファにデータを保存するには、次の手順に従います。
- 空のバッファを作成します。
- 適切な配列オブジェクトを空のバッファーにバインドします。
- typed array のいずれかを使用して、データ(頂点/インデックス)をバッファに渡します。
- バッファーのバインドを解除します(オプション)。
バッファを作成する
空のバッファオブジェクトを作成するために、WebGLは* createBuffer()*というメソッドを提供します。 このメソッドは、作成が成功した場合、新しく作成されたバッファーオブジェクトを返します。それ以外の場合は、失敗した場合にnull値を返します。
WebGLはステートマシンとして動作します。 バッファが作成されると、後続のバッファ操作は、アンバインドするまで現在のバッファで実行されます。 次のコードを使用してバッファを作成します-
var vertex_buffer = gl.createBuffer();
注- gl は、現在のWebGLコンテキストへの参照変数です。
バッファーをバインドする
空のバッファオブジェクトを作成したら、適切な配列バッファ(ターゲット)をそれにバインドする必要があります。 WebGLは、この目的のために* bindBuffer()*というメソッドを提供します。
構文
- bindBuffer()*メソッドの構文は次のとおりです-
void bindBuffer (enum target, Object buffer)
このメソッドは2つのパラメーターを受け入れます。これらについては以下で説明します。
ターゲット-最初の変数は、空のバッファにバインドするバッファのタイプを表す列挙値です。 このパラメーターのオプションとして、2つの定義済み列挙値があります。 彼らは-
- ARRAY_BUFFER 頂点データを表します。
- ELEMENT_ARRAY_BUFFER インデックスデータを表します。
オブジェクトバッファ-2番目のものは、前のステップで作成されたバッファオブジェクトへの参照変数です。 参照変数は、頂点バッファーオブジェクトまたはインデックスバッファーオブジェクトにすることができます。
例
次のコードスニペットは、bindBuffer()メソッドの使用方法を示しています。
//vertex buffer
var vertex_buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
//Index buffer
var Index_Buffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buffer);
データをバッファに渡す
次のステップは、データ(頂点/インデックス)をバッファに渡すことです。 データは配列の形になり、バッファに渡す前に、WebGL型付き配列の1つでラップする必要があります。 WebGLは、この目的のために* bufferData()*という名前のメソッドを提供します。
構文
bufferData()メソッドの構文は次のとおりです-
void bufferData (enum target, Object data, enum usage)
このメソッドは3つのパラメータを受け入れ、それらは以下で説明されています-
ターゲット-最初のパラメータは、使用した配列バッファのタイプを表す列挙値です。このパラメータのオプションは-
- 頂点データ*を表す *ARRAY_BUFFER 。
- ELEMENT_ARRAY_BUFFER は、*インデックスデータ*を表します。
オブジェクトデータ-2番目のパラメータは、バッファオブジェクトに書き込まれるデータを含むオブジェクト値です。 ここでは、 typed array を使用してデータを渡す必要があります。
使用法-このメソッドの3番目のパラメーターは、図形を描画するためにバッファーオブジェクトデータ(保存されたデータ)を使用する方法を指定する列挙型変数です。 以下にリストされているように、このパラメーターには3つのオプションがあります。
- gl.STATIC_DRAW -データは一度指定され、何度も使用されます。
- gl.STREAM_DRAW -データは1回指定され、数回使用されます。
- gl.DYNAMIC_DRAW -データは繰り返し指定され、何度も使用されます。
例
次のコードスニペットは、* bufferData()*メソッドの使用方法を示しています。 頂点とインデックスは、それぞれ頂点とインデックスのデータを保持する配列であると仮定します。
//vertex buffer
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
//Index buffer
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
型付き配列
WebGLは、 typed array と呼ばれる特別なタイプの配列を提供して、インデックス頂点やテクスチャなどのデータ要素を転送します。 これらの型付き配列は大量のデータを保存し、ネイティブバイナリ形式で処理するため、パフォーマンスが向上します。 WebGLが使用する型付き配列は、Int8Array、Uint8Array、Int16Array、Uint16Array、Int32Array、UInt32Array、Float32Array、およびFloat64Arrayです。
注意
- 一般的に、頂点データを保存するには、 Float32Array を使用します。インデックスデータを保存するには、 Uint16Array を使用します。
- new キーワードを使用して、JavaScript配列のように型付き配列を作成できます。
バッファーのバインドを解除します
バッファを使用した後、アンバインドすることをお勧めします。 以下に示すように、バッファオブジェクトの代わりにnull値を渡すことで実行できます。
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
WebGLは、バッファ操作を実行するために次のメソッドを提供します-
Sr.No. | Methods and Description |
---|---|
1 |
void *bindBuffer *(enum target, Object buffer) target-ARRAY_BUFFER、ELEMENT_ARRAY_BUFFER |
2 |
void* bufferData*(enum target, long size, enum usage) target-ARRAY_BUFFER、ELEMENT_ARRAY_BUFFER usage − STATIC_DRAW、STREAM_DRAW、DYNAMIC_DRAW |
3 |
void bufferData (enum target, Object data, enum usage) target_および_usage-上記の bufferData と同じ |
4 |
void bufferSubData(enum target, long offset, Object data) target-ARRAY_BUFFER、ELEMENT_ARRAY_BUFFER |
5 | Object *createBuffer() * |
6 | void* deleteBuffer*(Object buffer) |
7 |
any getBufferParameter(enum target, enum pname) target-ARRAY_BUFFER、ELEMENT_ ARRAY_BUFFER pname-BUFFER_SIZE、BUFFER_USAGE |
8 | bool isBuffer(Object buffer) |
WebGL-シェーダー
シェーダーは、GPUで実行されるプログラムです。 シェーダーはOpenGL ESシェーダー言語(ES SLとして知られています)で記述されています。 ES SLには、独自の変数、データ型、修飾子、組み込みの入力および出力があります。
データ型
次の表に、OpenGL ES SLが提供する基本的なデータ型を示します。
Sr.No. | Type & Description |
---|---|
1 |
void 空の値を表します。 |
2 |
bool trueまたはfalseを受け入れます。 |
3 |
int これは符号付き整数データ型です。 |
4 |
float これは、浮動スカラーデータ型です。 |
5 |
vec2, vec3, vec4 n成分の浮動小数点ベクトル |
6 |
bvec2, bvec3, bvec4 ブールベクトル |
7 |
ivec2, ivec3, ivec4 符号付き整数ベクトル |
8 |
mat2, mat3, mat4 2x2、3x3、4x4 floatマトリックス |
9 |
sampler2D 2Dテクスチャにアクセスする |
10 |
samplerCube キューブマップテクスチャへのアクセス |
予選
OpenGL ES SLには3つの主要な修飾子があります-
Sr.No. | Qualifier & Description |
---|---|
1 |
attribute この修飾子は、頂点シェーダーと頂点ごとのデータのOpenGL ES間のリンクとして機能します。 この属性の値は、頂点シェーダーの実行ごとに変化します。 |
2 |
uniform この修飾子は、シェーダープログラムとWebGLアプリケーションをリンクします。 属性修飾子とは異なり、ユニフォームの値は変更されません。 制服は読み取り専用です。変数を宣言するために、任意の基本データ型でそれらを使用できます。 例-均一 vec4 lightPosition; |
3 |
varying この修飾子は、補間データの頂点シェーダーとフラグメントシェーダー間のリンクを形成します。 float、vec2、vec3、vec4、mat2、mat3、mat4、または配列のデータ型で使用できます。 例-変化する vec3 通常; |
頂点シェーダー
頂点シェーダーは、すべての頂点で呼び出されるプログラムコードです。 ジオメトリ(例:三角形)をある場所から別の場所に変換(移動)します。 頂点座標、法線、色、テクスチャ座標など、各頂点のデータ(頂点ごとのデータ)を処理します。
頂点シェーダーのES GLコードでは、プログラマはデータを処理する属性を定義する必要があります。 これらの属性は、JavaScriptで記述された頂点バッファーオブジェクトを指します。 次のタスクは、頂点変換とともに頂点シェーダーを使用して実行できます-
- 頂点変換
- 通常の変換と正規化
- テクスチャ座標生成
- テクスチャ座標変換
- 点灯 *色材用途
事前定義された変数
OpenGL ES SLは、頂点シェーダーに次の定義済み変数を提供します-
Sr.No. | Variables & Description |
---|---|
1 |
頂点の位置を保持します。 |
2 |
mediump float gl_PointSize; 変換されたポイントサイズを保持します。 この変数の単位はピクセルです。 |
サンプルコード
次の頂点シェーダーのサンプルコードをご覧ください。 三角形の頂点を処理します。
attribute vec2 coordinates;
void main(void) {
gl_Position = vec4(coordinates, 0.0, 1.0);
};
上記のコードを注意深く観察すると、 coordinates という名前の属性変数が宣言されています。 (この変数は、メソッド* getAttribLocation()を使用して頂点バッファーオブジェクトに関連付けられます。 属性 *coordinates は、パラメーターとしてシェーダープログラムオブジェクトと共にこのメソッドに渡されます。
指定された頂点シェーダープログラムの2番目のステップで、 gl_position 変数が定義されます。
gl_Position
gl_Positionは、頂点シェーダープログラムでのみ使用可能な定義済み変数です。 頂点の位置が含まれています。 上記のコードでは、 coordinates 属性はベクトルの形式で渡されます。 頂点シェーダーは頂点ごとの操作であるため、gl_position値は各頂点に対して計算されます。
後で、gl_position値は、頂点の処理が終了した後にプリミティブを操作するプリミティブアセンブリ、クリッピング、カリング、およびその他の固定機能操作で使用されます。
頂点シェーダーのすべての可能な操作用の頂点シェーダープログラムを作成できます。これについては、このチュートリアルで個別に説明します。
フラグメントシェーダ
- メッシュ*は複数の三角形で構成され、各三角形の表面は*フラグメント*と呼ばれます。 フラグメントシェーダーは、各フラグメントのすべてのピクセルで実行されるコードです。 これは、個々のピクセルの色を計算して塗りつぶすために書かれています。 次のタスクは、フラグメントシェーダーを使用して実行できます-
- 補間値の操作
- テクスチャアクセス
- テクスチャアプリケーション
- Fog *色の合計
事前定義された変数
OpenGL ES SLは、フラグメントシェーダーに次の定義済み変数を提供します-
Sr.No. | Variables & Description |
---|---|
1 |
mediump vec4* gl_FragCoord*; フレームバッファー内のフラグメントの位置を保持します。 |
2 |
bool gl_FrontFacing; 前向きのプリミティブに属するフラグメントを保持します。 |
3 |
mediump vec2 gl_PointCoord; ポイント内のフラグメントの位置を保持します(ポイントラスタライズのみ)。 |
4 |
mediump vec4 gl_FragColor; シェーダーの出力フラグメントカラー値を保持します |
5 |
mediump vec4 gl_FragData[n] カラーアタッチメント n のフラグメントカラーを保持します。 |
サンプルコード
次のフラグメントシェーダーのサンプルコードは、三角形のすべてのピクセルに色を適用する方法を示しています。
void main(void) {
gl_FragColor = vec4(0, 0.8, 0, 1);
}
上記のコードでは、 color 値は変数 `+ gl.FragColor +`に保存されます。 フラグメントシェーダープログラムは、固定関数変数を使用して出力をパイプラインに渡します。 FragColorはその1つです。 この変数は、モデルのピクセルの色の値を保持します。
シェーダープログラムの保存とコンパイル
シェーダーは独立したプログラムであるため、それらを個別のスクリプトとして記述し、アプリケーションで使用できます。 または、以下に示すように、 string 形式で直接保存できます。
var vertCode =
'attribute vec2 coordinates;' +
'void main(void) {' +
' gl_Position = vec4(coordinates, 0.0, 1.0);' +
'}';
シェーダーのコンパイル
コンパイルには次の3つの手順が含まれます-
- シェーダーオブジェクトの作成
- 作成されたシェーダーオブジェクトへのソースコードの添付
- プログラムをコンパイルする
頂点シェーダーの作成
空のシェーダーを作成するために、WebGLには* createShader()*というメソッドが用意されています。 シェーダーオブジェクトを作成して返します。 その構文は次のとおりです-
Object createShader (enum type)
構文で見られるように、このメソッドはパラメーターとして事前定義された列挙値を受け入れます。 これには2つのオプションがあります-
- 頂点シェーダーを作成するための gl.VERTEX_SHADER
- フラグメントシェーダーを作成するための gl.FRAGMENT_SHADER 。
ソースをシェーダーにアタッチする
メソッド* shaderSource()*を使用して、作成したシェーダーオブジェクトにソースコードを添付できます。 その構文は次のとおりです-
void shaderSource(Object shader, string source)
このメソッドは、2つのパラメータを受け入れます-
- shader -作成したシェーダーオブジェクトを1つのパラメーターとして渡す必要があります。
- ソース-シェーダープログラムコードを文字列形式で渡す必要があります。
プログラムのコンパイル
プログラムをコンパイルするには、* compileShader()*メソッドを使用する必要があります。 その構文は次のとおりです-
compileShader(Object shader)
このメソッドは、シェーダープログラムオブジェクトをパラメーターとして受け入れます。 シェーダープログラムオブジェクトを作成した後、ソースコードをアタッチし、そのオブジェクトをこのメソッドに渡します。
次のコードスニペットは、頂点シェーダーとフラグメントシェーダーを作成してコンパイルし、三角形を作成する方法を示しています。
//Vertex Shader
var vertCode =
'attribute vec3 coordinates;' +
'void main(void) {' +
' gl_Position = vec4(coordinates, 1.0);' +
'}';
var vertShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertShader, vertCode);
gl.compileShader(vertShader);
//Fragment Shader
var fragCode =
'void main(void) {' +
' gl_FragColor = vec4(0, 0.8, 0, 1);' +
'}';
var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragShader, fragCode);
gl.compileShader(fragShader);
複合プログラム
両方のシェーダープログラムを作成してコンパイルした後、両方のシェーダー(頂点とフラグメント)を含む結合プログラムを作成する必要があります。 次の手順に従う必要があります-
- プログラムオブジェクトを作成する
- 両方のシェーダーを取り付けます
- 両方のシェーダーをリンクする
- プログラムを使用する
プログラムオブジェクトを作成する
メソッド* createProgram()*を使用して、プログラムオブジェクトを作成します。 空のプログラムオブジェクトを返します。 ここにその構文があります-
createProgram();
シェーダーを取り付けます
メソッド* attachShader()*を使用して、作成したプログラムオブジェクトにシェーダーをアタッチします。 その構文は次のとおりです-
attachShader(Object program, Object shader);
このメソッドは、2つのパラメータを受け入れます-
- プログラム-作成された空のプログラムオブジェクトを1つのパラメーターとして渡します。
- Shader -コンパイルされたシェーダープログラム(頂点シェーダー、フラグメントシェーダー)のいずれかを渡す
注-このメソッドを使用して両方のシェーダーをアタッチする必要があります。
シェーダーをリンクする
シェーダーをアタッチしたプログラムオブジェクトを渡すことにより、メソッド* linkProgram()*を使用してシェーダーをリンクします。 その構文は次のとおりです-
linkProgram(shaderProgram);
プログラムを使用する
WebGLは、* useProgram()*というメソッドを提供します。 リンクされたプログラムをそれに渡す必要があります。 その構文は次のとおりです-
useProgram(shaderProgram);
次のコードスニペットは、組み合わせたシェーダープログラムを作成、リンク、および使用する方法を示しています。
var shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertShader);
gl.attachShader(shaderProgram, fragShader);
gl.linkProgram(shaderProgram);
gl.useProgram(shaderProgram);
属性とバッファオブジェクトの関連付け
頂点シェーダープログラムの各属性は、頂点バッファーオブジェクトを指します。 頂点バッファオブジェクトを作成した後、プログラマはそれらを頂点シェーダプログラムの属性に関連付ける必要があります。 各属性は、データ値を抽出する1つの頂点バッファーオブジェクトのみを指し、これらの属性はシェーダープログラムに渡されます。
頂点バッファーオブジェクトを頂点シェーダープログラムの属性に関連付けるには、以下の手順に従う必要があります-
- 属性の場所を取得する
- 属性を頂点バッファーオブジェクトに向ける
- 属性を有効にする
属性の場所を取得する
WebGLは、属性の場所を返す* getAttribLocation()*というメソッドを提供します。 その構文は次のとおりです-
ulong getAttribLocation(Object program, string name)
このメソッドは、頂点シェーダープログラムオブジェクトと頂点シェーダープログラムの属性値を受け入れます。
次のコードスニペットは、このメソッドの使用方法を示しています。
var coordinatesVar = gl.getAttribLocation(shader_program, "coordinates");
ここで、 shader_program はシェーダープログラムのオブジェクトであり、 coordinates は頂点シェーダープログラムの属性です。
属性をVBOに向ける
バッファオブジェクトを属性変数に割り当てるために、WebGLは* vertexAttribPointer()*というメソッドを提供します。 このメソッドの構文は次のとおりです-
void vertexAttribPointer(location, int size, enum type, bool normalized, long stride, long offset)
このメソッドは6つのパラメーターを受け入れます。これらについては以下で説明します。
- 場所-属性変数の保存場所を指定します。 このオプションでは、* getAttribLocation()*メソッドによって返される値を渡す必要があります。
- サイズ-バッファオブジェクトの頂点ごとのコンポーネントの数を指定します。
- タイプ-データのタイプを指定します。
- Normalized -これはブール値です。 trueの場合、非浮動データは[0、1]に正規化されます。それ以外の場合は、[-1、1]に正規化されます。
- ストライド-異なる頂点データ要素間のバイト数、またはデフォルトのストライドの場合はゼロを指定します。
- Offset -頂点データの格納元のバイトを示すために、バッファオブジェクトのオフセット(バイト単位)を指定します。 データが最初から保存されている場合、_offset_は0です。
次のスニペットは、プログラムで* vertexAttribPointer()*を使用する方法を示しています-
gl.vertexAttribPointer(coordinatesVar, 3, gl.FLOAT, false, 0, 0);
属性を有効にする
頂点シェーダーアトリビュートをアクティブにして、頂点シェーダーのバッファオブジェクトにアクセスします。 この操作のために、WebGLは* enableVertexAttribArray()*メソッドを提供します。 このメソッドは、パラメーターとして属性の場所を受け入れます。 プログラムでこのメソッドを使用する方法は次のとおりです-
gl.enableVertexAttribArray(coordinatesVar);
WebGL-モデルの描画
バッファーをシェーダーに関連付けた後、最後の手順は必要なプリミティブを描画することです。 WebGLには、モデルを描画するための* drawArrays()および drawElements()*という2つのメソッドがあります。
drawArrays()
- drawArrays()*は、頂点を使用してモデルを描画するために使用されるメソッドです。 ここにその構文があります-
void drawArrays(enum mode, int first, long count)
このメソッドは、次の3つのパラメータを取ります-
- mode -WebGLでは、モデルはプリミティブ型を使用して描画されます。 モードを使用して、プログラマはWebGLが提供するプリミティブタイプのいずれかを選択する必要があります。 このオプションの可能な値は、gl.POINTS、gl.LINE_STRIP、gl.LINE_LOOP、gl.LINES、gl.TRIANGLE_STRIP、gl.TRIANGLE_FAN、およびgl.TRIANGLESです。
- first -このオプションは、有効な配列の開始要素を指定します。 負の値にすることはできません。
- count -このオプションは、レンダリングする要素の数を指定します。
- drawArrays()*メソッドを使用してモデルを描画する場合、WebGLは形状のレンダリング中に、頂点座標が定義されている順序でジオメトリを作成します。
例
- drawArray()メソッドを使用して単一の三角形を描画する場合は、以下に示すように、3つの頂点を渡して drawArrays()*メソッドを呼び出す必要があります。
var vertices = [-0.5,-0.5, -0.25,0.5, 0.0,-0.5,];
gl.drawArrays(gl.TRIANGLES, 0, 3);
以下に示すような三角形を生成します。
連続した三角形を描画したい場合、次の3つの頂点を順番に頂点バッファーに渡し、レンダリングされる要素の数を6として指定する必要があるとします。
var vertices = [-0.5,-0.5, -0.25,0.5, 0.0,-0.5, 0.0,-0.5, 0.25,0.5, 0.5,-0.5,];
gl.drawArrays(gl.TRIANGLES, 0, 6);
以下に示すように、連続した三角形が生成されます。
drawElements()
- drawElements()*は、頂点とインデックスを使用してモデルを描画するために使用されるメソッドです。 その構文は次のとおりです-
void drawElements(enum mode, long count, enum type, long offset)
このメソッドは、次の4つのパラメータを取ります-
- mode -WebGLモデルはプリミティブ型を使用して描画されます。 モードを使用して、プログラマはWebGLが提供するプリミティブタイプのいずれかを選択する必要があります。 このオプションの可能な値のリストは、gl.POINTS、gl.LINE_STRIP、gl.LINE_LOOP、gl.LINES、gl.TRIANGLE_STRIP、gl.TRIANGLE_FAN、およびgl.TRIANGLESです。
- count -このオプションは、レンダリングする要素の数を指定します。
- type -このオプションは、UNSIGNED_BYTEまたはUNSIGNED_SHORTでなければならないインデックスのデータ型を指定します。
- offset -このオプションは、レンダリングの開始点を指定します。 通常、最初の要素(0)です。
- drawElements()*メソッドを使用してモデルを描画する場合、インデックスバッファーオブジェクトも頂点バッファーオブジェクトと共に作成する必要があります。 この方法を使用する場合、頂点データは1回処理され、インデックスに記載されている回数だけ使用されます。
例
インデックスを使用して単一の三角形を描画する場合は、インデックスを頂点とともに渡し、以下に示すように* drawElements()*メソッドを呼び出す必要があります。
var vertices = [ -0.5,-0.5,0.0, -0.25,0.5,0.0, 0.0,-0.5,0.0 ];
var indices = [0,1,2];
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT,0);
それは次の出力を生成します-
- drawElements()*メソッドを使用して伝染性の三角形を描画する場合は、他の頂点を追加し、残りの頂点のインデックスを指定するだけです。
var vertices = [
-0.5,-0.5,0.0,
-0.25,0.5,0.0,
0.0,-0.5,0.0,
0.25,0.5,0.0,
0.5,-0.5,0.0
];
var indices = [0,1,2,2,3,4];
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT,0);
それは次の出力を生成します-
必要な操作
プリミティブを描画する前に、以下で説明するいくつかの操作を実行する必要があります。
キャンバスをクリアする
まず、* clearColor()*メソッドを使用して、キャンバスをクリアする必要があります。 目的の色のRGBA値をパラメーターとしてこのメソッドに渡すことができます。 次に、WebGLはキャンバスをクリアし、指定された色で塗りつぶします。 したがって、この方法を使用して背景色を設定できます。
次の例を見てください。 ここでは、グレー色のRGBA値を渡します。
gl.clearColor(0.5, 0.5, .5, 1);
深度テストを有効にする
以下に示すように、* enable()*メソッドを使用して深度テストを有効にします。
gl.enable(gl.DEPTH_TEST);
カラーバッファビットをクリアする
以下に示すように、* clear()*メソッドを使用して、色と深度バッファーをクリアします。
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
ビューポートを設定する
ビューポートは、描画バッファのレンダリング結果を含む長方形の表示可能領域を表します。 * viewport()*メソッドを使用して、ビューポートの寸法を設定できます。 次のコードでは、ビューポートの寸法がキャンバスの寸法に設定されています。
gl.viewport(0,0,canvas.width,canvas.height);
WebGL-描画ポイント
以前(第5章)に、ステップバイステップのプロセスに従ってプリミティブを描画する方法について説明しました。 5つのステップでプロセスを説明しました。 新しい形状を描くたびに、これらの手順を繰り返す必要があります。 この章では、WebGLで3D座標を使用してポイントを描画する方法について説明します。 さらに先に進む前に、5つのステップを見てみましょう。
必要な手順
WebGLアプリケーションを作成してポイントを描画するには、次の手順が必要です。
ステップ1-キャンバスを準備し、WebGLレンダリングコンテキストを取得
このステップでは、メソッド* getContext()。*を使用してWebGLレンダリングコンテキストオブジェクトを取得します。
ステップ2-ジオメトリを定義し、バッファオブジェクトに格納します
3つのポイントを描画しているため、3D座標で3つの頂点を定義し、それらをバッファーに保存します。
var vertices = [
-0.5,0.5,0.0,
0.0,0.5,0.0,
-0.25,0.25,0.0,
];
ステップ3-シェーダープログラムの作成とコンパイル
この手順では、頂点シェーダーおよびフラグメントシェーダープログラムを記述し、それらをコンパイルし、これら2つのプログラムをリンクして結合プログラムを作成する必要があります。
- 頂点シェーダー-与えられた例の頂点シェーダーでは、3D座標を保存するためにベクトル属性を定義し、それを gl_position 変数に割り当てます。
- gl_pointsize は、ポイントにサイズを割り当てるために使用される変数です。 ポイントサイズを10として割り当てます。
var vertCode = 'attribute vec3 coordinates;' +
'void main(void) {' +
' gl_Position = vec4(coordinates, 1.0);' +
'gl_PointSize = 10.0;'+
'}';
- フラグメントシェーダー-フラグメントシェーダーで、フラグメントの色を gl_FragColor 変数に割り当てるだけです
var fragCode = 'void main(void) {' +' gl_FragColor = vec4(1, 0.5, 0.0, 1);' +'}';
ステップ4-シェーダープログラムをバッファオブジェクトに関連付ける
この手順では、バッファーオブジェクトをシェーダープログラムに関連付けます。
ステップ5-必要なオブジェクトの描画
メソッド* drawArrays()*を使用してポイントを描画します。 描画するポイントの数は3つなので、カウント値は3です。
gl.drawArrays(gl.POINTS, 0, 3)
例– WebGLを使用して3つのポイントを描く
ここに3つの点を描く完全なWebGLプログラムがあります-
<!doctype html>
<html>
<body>
<canvas width = "570" height = "570" id = "my_Canvas"></canvas>
<script>
/*================Creating a canvas=================*/
var canvas = document.getElementById('my_Canvas');
gl = canvas.getContext('experimental-webgl');
/*==========Defining and storing the geometry=======*/
var vertices = [
-0.5,0.5,0.0,
0.0,0.5,0.0,
-0.25,0.25,0.0,
];
//Create an empty buffer object to store the vertex buffer
var vertex_buffer = gl.createBuffer();
//Bind appropriate array buffer to it
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
//Pass the vertex data to the buffer
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
//Unbind the buffer
gl.bindBuffer(gl.ARRAY_BUFFER, null);
/*=========================Shaders========================*/
//vertex shader source code
var vertCode =
'attribute vec3 coordinates;' +
'void main(void) {' +
' gl_Position = vec4(coordinates, 1.0);' +
'gl_PointSize = 10.0;'+
'}';
//Create a vertex shader object
var vertShader = gl.createShader(gl.VERTEX_SHADER);
//Attach vertex shader source code
gl.shaderSource(vertShader, vertCode);
//Compile the vertex shader
gl.compileShader(vertShader);
//fragment shader source code
var fragCode =
'void main(void) {' +
' gl_FragColor = vec4(0.0, 0.0, 0.0, 0.1);' +
'}';
//Create fragment shader object
var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
//Attach fragment shader source code
gl.shaderSource(fragShader, fragCode);
//Compile the fragmentt shader
gl.compileShader(fragShader);
//Create a shader program object to store
//the combined shader program
var shaderProgram = gl.createProgram();
//Attach a vertex shader
gl.attachShader(shaderProgram, vertShader);
//Attach a fragment shader
gl.attachShader(shaderProgram, fragShader);
//Link both programs
gl.linkProgram(shaderProgram);
//Use the combined shader program object
gl.useProgram(shaderProgram);
/*======== Associating shaders to buffer objects ========*/
//Bind vertex buffer object
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
//Get the attribute location
var coord = gl.getAttribLocation(shaderProgram, "coordinates");
//Point an attribute to the currently bound VBO
gl.vertexAttribPointer(coord, 3, gl.FLOAT, false, 0, 0);
//Enable the attribute
gl.enableVertexAttribArray(coord);
/*============= Drawing the primitive ===============*/
//Clear the canvas
gl.clearColor(0.5, 0.5, 0.5, 0.9);
//Enable the depth test
gl.enable(gl.DEPTH_TEST);
//Clear the color buffer bit
gl.clear(gl.COLOR_BUFFER_BIT);
//Set the view port
gl.viewport(0,0,canvas.width,canvas.height);
//Draw the triangle
gl.drawArrays(gl.POINTS, 0, 3);
</script>
</body>
</html>
それは次の結果を生成します-
WebGL-三角形の描画
前の章(第11章)では、WebGLを使用して3つのポイントを描画する方法について説明しました。 第5章では、三角形の描画方法を示すサンプルアプリケーションを取り上げました。 両方の例で、頂点のみを使用してプリミティブを描画しました。
より複雑な形状/メッシュを描画するために、頂点とともにジオメトリのインデックスもシェーダーに渡します。 この章では、インデックスを使用して三角形を描く方法を説明します。
三角形を描くために必要な手順
WebGLアプリケーションを作成して三角形を描くには、次の手順が必要です。
ステップ1-キャンバスの準備とWebGLレンダリングコンテキストの取得
このステップでは、* getContext()*を使用してWebGLレンダリングコンテキストオブジェクトを取得します。
ステップ2-ジオメトリを定義し、バッファオブジェクトに保存します
インデックスを使用して三角形を描画しているため、インデックスを含む三角形の3つの頂点を渡して、バッファに保存する必要があります。
var vertices = [
-0.5,0.5,0.0,
-0.5,-0.5,0.0,
0.5,-0.5,0.0,
];
indices = [0,1,2];
ステップ3-シェーダープログラムの作成とコンパイル
この手順では、頂点シェーダーおよびフラグメントシェーダープログラムを記述し、それらをコンパイルし、これら2つのプログラムをリンクして結合プログラムを作成する必要があります。
- 頂点シェーダー-プログラムの頂点シェーダーで、3D座標を保存するベクトル属性を定義し、それを gl_position に割り当てます。
var vertCode =
'attribute vec3 coordinates;' +
'void main(void) {' +
' gl_Position = vec4(coordinates, 1.0);' +
'}';
- フラグメントシェーダー-フラグメントシェーダーでは、フラグメントの色を gl_FragColor 変数に割り当てるだけです。
var fragCode = 'void main(void) {' +
' gl_FragColor = vec4(1, 0.5, 0.0, 1);' +
'}';
ステップ4-シェーダープログラムをバッファオブジェクトに関連付ける
この手順では、バッファーオブジェクトとシェーダープログラムを関連付けます。
- ステップ5-必要なオブジェクトの描画 *
インデックスを使用して三角形を描画するため、 `+ drawElements()+`を使用します。 このメソッドには、インデックスの数を渡す必要があります。* indices.length *の値は、インデックスの数を示します。
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT,0);
例–三角形の描画
次のプログラムコードは、インデックスを使用してWebGLで三角形を描画する方法を示しています-
<!doctype html>
<html>
<body>
<canvas width = "570" height = "570" id = "my_Canvas"></canvas>
<script>
/*============== Creating a canvas ====================*/
var canvas = document.getElementById('my_Canvas');
gl = canvas.getContext('experimental-webgl');
/*======== Defining and storing the geometry ===========*/
var vertices = [
-0.5,0.5,0.0,
-0.5,-0.5,0.0,
0.5,-0.5,0.0,
];
indices = [0,1,2];
//Create an empty buffer object to store vertex buffer
var vertex_buffer = gl.createBuffer();
//Bind appropriate array buffer to it
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
//Pass the vertex data to the buffer
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
//Unbind the buffer
gl.bindBuffer(gl.ARRAY_BUFFER, null);
//Create an empty buffer object to store Index buffer
var Index_Buffer = gl.createBuffer();
//Bind appropriate array buffer to it
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, Index_Buffer);
//Pass the vertex data to the buffer
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
//Unbind the buffer
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
/*================ Shaders ====================*/
//Vertex shader source code
var vertCode =
'attribute vec3 coordinates;' +
'void main(void) {' +
' gl_Position = vec4(coordinates, 1.0);' +
'}';
//Create a vertex shader object
var vertShader = gl.createShader(gl.VERTEX_SHADER);
//Attach vertex shader source code
gl.shaderSource(vertShader, vertCode);
//Compile the vertex shader
gl.compileShader(vertShader);
//fragment shader source code
var fragCode =
'void main(void) {' +
' gl_FragColor = vec4(0.0, 0.0, 0.0, 0.1);' +
'}';
//Create fragment shader object
var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
//Attach fragment shader source code
gl.shaderSource(fragShader, fragCode);
//Compile the fragmentt shader
gl.compileShader(fragShader);
//Create a shader program object to store
//the combined shader program
var shaderProgram = gl.createProgram();
//Attach a vertex shader
gl.attachShader(shaderProgram, vertShader);
//Attach a fragment shader
gl.attachShader(shaderProgram, fragShader);
//Link both the programs
gl.linkProgram(shaderProgram);
//Use the combined shader program object
gl.useProgram(shaderProgram);
/*======= Associating shaders to buffer objects =======*/
//Bind vertex buffer object
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
//Bind index buffer object
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, Index_Buffer);
//Get the attribute location
var coord = gl.getAttribLocation(shaderProgram, "coordinates");
//Point an attribute to the currently bound VBO
gl.vertexAttribPointer(coord, 3, gl.FLOAT, false, 0, 0);
//Enable the attribute
gl.enableVertexAttribArray(coord);
/*=========Drawing the triangle===========*/
//Clear the canvas
gl.clearColor(0.5, 0.5, 0.5, 0.9);
//Enable the depth test
gl.enable(gl.DEPTH_TEST);
//Clear the color buffer bit
gl.clear(gl.COLOR_BUFFER_BIT);
//Set the view port
gl.viewport(0,0,canvas.width,canvas.height);
//Draw the triangle
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT,0);
</script>
</body>
</html>
この例を実行すると、次の出力が生成されます-
WebGL-描画モード
前の章(第12章)では、WebGLを使用して三角形を描画する方法について説明しました。 三角形に加えて、WebGLはさまざまな他の描画モードをサポートしています。 この章では、WebGLがサポートする描画モードについて説明します。
モードパラメータ
メソッドの構文を見てみましょう-* drawElements()とdraw * Arrays()。
void drawElements(enum mode, long count, enum type, long offset);
void drawArrays(enum mode, int first, long count);
明確に観察すると、両方のメソッドがパラメーター mode を受け入れます。 このパラメーターを使用すると、プログラマーはWebGLで描画モードを選択できます。
WebGLが提供する描画モードを次の表にリストします。
Sr.No. | Mode & Description |
---|---|
1 |
gl.POINTS 一連のポイントを描画します。 |
2 |
gl.LINES 接続されていない一連のラインセグメント(個々のライン)を描画します。 |
3 |
gl.LINE_STRIP 接続された一連の線分を描画します。 |
4 |
gl.LINE_LOOP 接続された一連の線分を描画します。 また、最初と最後の頂点を結合してループを形成します。 |
5 |
gl.TRIANGLES 一連の別々の三角形を描画します。 |
6 |
gl.TRIANGLE_STRIP 接続された一連の三角形をストリップ形式で描画します。 |
7 |
gl.TRIANGLE_FAN ファンのように最初の頂点を共有する一連の接続された三角形を描画します。 |
例– 3本の平行線を引く
次の例は、 gl.LINES を使用して3本の平行線を描く方法を示しています。
<!doctype html>
<html>
<body>
<canvas width = "300" height = "300" id = "my_Canvas"></canvas>
<script>
/*======= Creating a canvas =========*/
var canvas = document.getElementById('my_Canvas');
var gl = canvas.getContext('experimental-webgl');
/*======= Defining and storing the geometry ======*/
var vertices = [
-0.7,-0.1,0,
-0.3,0.6,0,
-0.3,-0.3,0,
0.2,0.6,0,
0.3,-0.3,0,
0.7,0.6,0
]
//Create an empty buffer object
var vertex_buffer = gl.createBuffer();
//Bind appropriate array buffer to it
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
//Pass the vertex data to the buffer
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
//Unbind the buffer
gl.bindBuffer(gl.ARRAY_BUFFER, null);
/*=================== Shaders ====================*/
//Vertex shader source code
var vertCode =
'attribute vec3 coordinates;' +
'void main(void) {' +
' gl_Position = vec4(coordinates, 1.0);' +
'}';
//Create a vertex shader object
var vertShader = gl.createShader(gl.VERTEX_SHADER);
//Attach vertex shader source code
gl.shaderSource(vertShader, vertCode);
//Compile the vertex shader
gl.compileShader(vertShader);
//Fragment shader source code
var fragCode =
'void main(void) {' +
'gl_FragColor = vec4(0.0, 0.0, 0.0, 0.1);' +
'}';
//Create fragment shader object
var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
//Attach fragment shader source code
gl.shaderSource(fragShader, fragCode);
//Compile the fragmentt shader
gl.compileShader(fragShader);
//Create a shader program object to store
//the combined shader program
var shaderProgram = gl.createProgram();
//Attach a vertex shader
gl.attachShader(shaderProgram, vertShader);
//Attach a fragment shader
gl.attachShader(shaderProgram, fragShader);
//Link both the programs
gl.linkProgram(shaderProgram);
//Use the combined shader program object
gl.useProgram(shaderProgram);
/*======= Associating shaders to buffer objects ======*/
//Bind vertex buffer object
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
//Get the attribute location
var coord = gl.getAttribLocation(shaderProgram, "coordinates");
//Point an attribute to the currently bound VBO
gl.vertexAttribPointer(coord, 3, gl.FLOAT, false, 0, 0);
//Enable the attribute
gl.enableVertexAttribArray(coord);
/*============ Drawing the triangle =============*/
//Clear the canvas
gl.clearColor(0.5, 0.5, 0.5, 0.9);
//Enable the depth test
gl.enable(gl.DEPTH_TEST);
//Clear the color and depth buffer
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
//Set the view port
gl.viewport(0,0,canvas.width,canvas.height);
//Draw the triangle
gl.drawArrays(gl.LINES, 0, 6);
//POINTS, LINE_STRIP, LINE_LOOP, LINES,
//TRIANGLE_STRIP,TRIANGLE_FAN, TRIANGLES
</script>
</body>
</html>
この例を実行すると、次の出力が生成されます-
描画モード
上記のプログラムで、* drawArrays()*のモードを次の描画モードのいずれかに置き換えると、毎回異なる出力が生成されます。
Drawing Modes | Outputs |
---|---|
LINE_STRIP | Line Strip |
LINE_LOOP | Line Loop |
TRIANGLE_STRIP | Triangle Strip |
TRIANGLE_FAN | Triangle Fan |
TRIANGLES | Triangles |
WebGL-クワッドの描画
前の章では、WebGLが提供するさまざまな描画モードについて説明しました。 これらのモードのいずれかを使用して、インデックスを使用してプリミティブを描画することもできます。 WebGLでモデルを描画するには、これらのプリミティブのいずれかを選択し、必要なメッシュ(つまり、1つ以上のプリミティブを使用して形成されたモデル)を描画する必要があります。
この章では、WebGLを使用して四角形を描画する方法を示す例を取り上げます。
四角形を描く手順
WebGLアプリケーションを作成して四角形を描画するには、次の手順が必要です。
ステップ1-キャンバスを準備し、WebGLレンダリングコンテキストを取得
このステップでは、* getContext()*を使用してWebGLレンダリングコンテキストオブジェクトを取得します。
ステップ2-ジオメトリを定義し、バッファオブジェクトに格納します
正方形は、2つの三角形を使用して描画できます。 この例では、2つの三角形(1つの共通エッジ)とインデックスの頂点を提供します。
var vertices = [
-0.5,0.5,0.0,
-0.5,-0.5,0.0,
0.5,-0.5,0.0,
0.5,0.5,0.0
];
indices = [3,2,1,3,1,0];
ステップ3-シェーダープログラムの作成とコンパイル
この手順では、頂点シェーダーおよびフラグメントシェーダープログラムを記述し、それらをコンパイルし、これらの2つのプログラムをリンクして結合プログラムを作成する必要があります。
- 頂点シェーダー-プログラムの頂点シェーダーで、3D座標を保存するベクトル属性を定義し、それを gl_position に割り当てます。
var vertCode =
'attribute vec3 coordinates;' +
'void main(void) {' +
' gl_Position = vec4(coordinates, 1.0);' +
'}';
- フラグメントシェーダー-フラグメントシェーダーでは、フラグメントの色を gl_FragColor 変数に割り当てるだけです。
var fragCode = 'void main(void) {' +' gl_FragColor = vec4(0.5, 0.3, 0.0, 7.5);' +'}';
ステップ4-シェーダープログラムをバッファオブジェクトに関連付ける
この手順では、バッファーオブジェクトをシェーダープログラムに関連付けます。
ステップ5-必要なオブジェクトの描画
インデックスを使用して2つの三角形を描画してクワッドを形成しているため、メソッド* drawElements()を使用します。 このメソッドには、インデックスの数を渡す必要があります。 *indices.length の値は、インデックスの数を示します。
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT,0);
例-四角形を描く
次のプログラムは、四角形を描画するWebGLアプリケーションを作成する方法を示しています。
<!doctype html>
<html>
<body>
<canvas width = "570" height = "570" id = "my_Canvas"></canvas>
<script>
/*============ Creating a canvas =================*/
var canvas = document.getElementById('my_Canvas');
gl = canvas.getContext('experimental-webgl');
/*========== Defining and storing the geometry =========*/
var vertices = [
-0.5,0.5,0.0,
-0.5,-0.5,0.0,
0.5,-0.5,0.0,
0.5,0.5,0.0
];
indices = [3,2,1,3,1,0];
//Create an empty buffer object to store vertex buffer
var vertex_buffer = gl.createBuffer();
//Bind appropriate array buffer to it
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
//Pass the vertex data to the buffer
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
//Unbind the buffer
gl.bindBuffer(gl.ARRAY_BUFFER, null);
//Create an empty buffer object to store Index buffer
var Index_Buffer = gl.createBuffer();
//Bind appropriate array buffer to it
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, Index_Buffer);
//Pass the vertex data to the buffer
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
//Unbind the buffer
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
/*====================== Shaders =======================*/
//Vertex shader source code
var vertCode =
'attribute vec3 coordinates;' +
'void main(void) {' +
' gl_Position = vec4(coordinates, 1.0);' +
'}';
//Create a vertex shader object
var vertShader = gl.createShader(gl.VERTEX_SHADER);
//Attach vertex shader source code
gl.shaderSource(vertShader, vertCode);
//Compile the vertex shader
gl.compileShader(vertShader);
//Fragment shader source code
var fragCode =
'void main(void) {' +
' gl_FragColor = vec4(0.0, 0.0, 0.0, 0.1);' +
'}';
//Create fragment shader object
var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
//Attach fragment shader source code
gl.shaderSource(fragShader, fragCode);
//Compile the fragmentt shader
gl.compileShader(fragShader);
//Create a shader program object to
//store the combined shader program
var shaderProgram = gl.createProgram();
//Attach a vertex shader
gl.attachShader(shaderProgram, vertShader);
//Attach a fragment shader
gl.attachShader(shaderProgram, fragShader);
//Link both the programs
gl.linkProgram(shaderProgram);
//Use the combined shader program object
gl.useProgram(shaderProgram);
/* ======= Associating shaders to buffer objects =======*/
//Bind vertex buffer object
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
//Bind index buffer object
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, Index_Buffer);
//Get the attribute location
var coord = gl.getAttribLocation(shaderProgram, "coordinates");
//Point an attribute to the currently bound VBO
gl.vertexAttribPointer(coord, 3, gl.FLOAT, false, 0, 0);
//Enable the attribute
gl.enableVertexAttribArray(coord);
/*============= Drawing the Quad ================*/
//Clear the canvas
gl.clearColor(0.5, 0.5, 0.5, 0.9);
//Enable the depth test
gl.enable(gl.DEPTH_TEST);
//Clear the color buffer bit
gl.clear(gl.COLOR_BUFFER_BIT);
//Set the view port
gl.viewport(0,0,canvas.width,canvas.height);
//Draw the triangle
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT,0);
</script>
</body>
</html>
この例を実行すると、次の出力が生成されます-
WebGL-色
これまでのすべての例では、 gl_FragColor 変数に目的の色の値を割り当てることにより、オブジェクトに色を適用しました。 それに加えて、頂点の座標とインデックスのように、各頂点の色を定義できます。 この章では、WebGLを使用して四角形に色を適用する方法を示す例を取り上げます。
色を適用する
色を適用するには、JavaScript配列でRGB値を使用して各頂点の色を定義する必要があります。 同じ値をすべての頂点に割り当てて、オブジェクトに一意の色を付けることができます。 色を定義したら、カラーバッファーを作成してこれらの値を保存し、頂点シェーダー属性に関連付ける必要があります。
頂点シェーダーで、座標属性(頂点の位置を保持する)とともに、色を処理するために*属性*および*可変*を定義します。
*color* 属性は頂点ごとの色の値を保持し、 *varying* はフラグメントシェーダーへの入力として渡される変数です。 したがって、 *color* 値を *varying* に割り当てる必要があります。
フラグメントシェーダーでは、色の値を保持する varying が gl_FragColor に割り当てられ、オブジェクトの最終的な色が保持されます。
色を適用する手順
WebGLアプリケーションを作成してクワッドを描画し、それに色を適用するには、次の手順が必要です。
ステップ1-キャンバスを準備し、WebGLレンダリングコンテキストを取得
このステップでは、* getContext()*を使用してWebGLレンダリングコンテキストオブジェクトを取得します。
ステップ2-ジオメトリを定義し、バッファオブジェクトに格納します
正方形は、2つの三角形を使用して描画できます。 したがって、この例では、2つの三角形(1つの共通エッジ)とインデックスの頂点を提供します。 色を適用するため、色の値を保持する変数も定義され、それぞれの色の値(赤、青、緑、ピンク)が割り当てられます。
var vertices = [
-0.5,0.5,0.0,
-0.5,-0.5,0.0,
0.5,-0.5,0.0,
0.5,0.5,0.0
];
var colors = [ 0,0,1, 1,0,0, 0,1,0, 1,0,1,];
indices = [3,2,1,3,1,0];
ステップ3-シェーダープログラムの作成とコンパイル
この手順では、頂点シェーダーおよびフラグメントシェーダープログラムを記述し、それらをコンパイルし、これらの2つのプログラムをリンクして結合プログラムを作成する必要があります。
- Vertex Shader -プログラムの頂点シェーダーで、3D座標(位置)と各頂点の色を格納するベクトル属性を定義します。 varing 変数は、頂点シェーダーからフラグメントシェーダーにカラー値を渡すために宣言されます。 そして最後に、色属性に保存された値が*変数*に割り当てられます。
var vertCode = 'attribute vec3 coordinates;'+
'attribute vec3 color;'+
'varying vec3 vColor;'+
'void main(void) {' +
' gl_Position = vec4(coordinates, 1.0);' +
'vColor = color;'+
'}';
- フラグメントシェーダー-フラグメントシェーダーでは、 varying を gl_FragColor 変数に割り当てます。
var fragCode = 'precision mediump float;'+
'varying vec3 vColor;'+
'void main(void) {'+
'gl_FragColor = vec4(vColor, 1.);'+
'}';
ステップ4-シェーダープログラムをバッファオブジェクトに関連付ける
この手順では、バッファーオブジェクトとシェーダープログラムを関連付けます。
ステップ5-必要なオブジェクトの描画
インデックスを使用して、四角形を形成する2つの三角形を描画しているため、メソッド* drawElements()を使用します。 このメソッドには、インデックスの数を渡す必要があります。 *indices.length の値は、インデックスの数を示します。
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT,0);
例–色の適用
次のプログラムは、WebGLアプリケーションを使用して四角形を描画し、色を適用する方法を示しています。
<!doctype html>
<html>
<body>
<canvas width = "300" height = "300" id = "my_Canvas"></canvas>
<script>
/*============= Creating a canvas ==================*/
var canvas = document.getElementById('my_Canvas');
gl = canvas.getContext('experimental-webgl');
/*========== Defining and storing the geometry ==========*/
var vertices = [
-0.5,0.5,0.0,
-0.5,-0.5,0.0,
0.5,-0.5,0.0,
0.5,0.5,0.0
];
var colors = [0,0,1, 1,0,0, 0,1,0, 1,0,1,];
indices = [3,2,1,3,1,0];
//Create an empty buffer object and store vertex data
var vertex_buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
//Create an empty buffer object and store Index data
var Index_Buffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, Index_Buffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
//Create an empty buffer object and store color data
var color_buffer = gl.createBuffer ();
gl.bindBuffer(gl.ARRAY_BUFFER, color_buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
/*======================= Shaders =======================*/
//vertex shader source code
var vertCode = 'attribute vec3 coordinates;'+
'attribute vec3 color;'+
'varying vec3 vColor;'+
'void main(void) {' +
' gl_Position = vec4(coordinates, 1.0);' +
'vColor = color;'+
'}';
//Create a vertex shader object
var vertShader = gl.createShader(gl.VERTEX_SHADER);
//Attach vertex shader source code
gl.shaderSource(vertShader, vertCode);
//Compile the vertex shader
gl.compileShader(vertShader);
//fragment shader source code
var fragCode = 'precision mediump float;'+
'varying vec3 vColor;'+
'void main(void) {'+
'gl_FragColor = vec4(vColor, 1.);'+
'}';
//Create fragment shader object
var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
//Attach fragment shader source code
gl.shaderSource(fragShader, fragCode);
//Compile the fragmentt shader
gl.compileShader(fragShader);
//Create a shader program object to
//store the combined shader program
var shaderProgram = gl.createProgram();
//Attach a vertex shader
gl.attachShader(shaderProgram, vertShader);
//Attach a fragment shader
gl.attachShader(shaderProgram, fragShader);
//Link both the programs
gl.linkProgram(shaderProgram);
//Use the combined shader program object
gl.useProgram(shaderProgram);
/* ======== Associating shaders to buffer objects =======*/
//Bind vertex buffer object
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
//Bind index buffer object
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, Index_Buffer);
//Get the attribute location
var coord = gl.getAttribLocation(shaderProgram, "coordinates");
//point an attribute to the currently bound VBO
gl.vertexAttribPointer(coord, 3, gl.FLOAT, false, 0, 0);
//Enable the attribute
gl.enableVertexAttribArray(coord);
//bind the color buffer
gl.bindBuffer(gl.ARRAY_BUFFER, color_buffer);
//get the attribute location
var color = gl.getAttribLocation(shaderProgram, "color");
//point attribute to the volor buffer object
gl.vertexAttribPointer(color, 3, gl.FLOAT, false,0,0) ;
//enable the color attribute
gl.enableVertexAttribArray(color);
/*============Drawing the Quad====================*/
//Clear the canvas
gl.clearColor(0.5, 0.5, 0.5, 0.9);
//Enable the depth test
gl.enable(gl.DEPTH_TEST);
//Clear the color buffer bit
gl.clear(gl.COLOR_BUFFER_BIT);
//Set the view port
gl.viewport(0,0,canvas.width,canvas.height);
//Draw the triangle
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT,0);
</script>
</body>
</html>
この例を実行すると、次の出力が生成されます-
WebGL-翻訳
これまで、WebGLを使用してさまざまな形状を描画し、色を適用する方法について説明しました。 ここで、この章では、三角形の変換方法を示す例を取り上げます。
翻訳
翻訳は、WebGLが提供する*アフィン変換*の1つです。 平行移動を使用して、xyz平面上の三角形(任意のオブジェクト)を移動できます。 三角形[a、b、c]があり、正のX軸に向かって5単位、正のY軸に向かって3単位の位置に三角形を移動するとします。 その場合、新しい頂点は[a + 5、b + 3、c + 0]になります。 つまり、三角形を平行移動するには、各頂点に平行移動距離、たとえばtx、ty、tzを追加する必要があります。
これは*頂点ごとの操作*なので、頂点シェーダープログラムで実行できます。
頂点シェーダーでは、属性 coordinates (頂点の位置を保持する)とともに、平行移動距離(x、y、z)を保持する均一変数を定義します。 後で、この均一変数を座標変数に追加し、結果を gl_Position 変数に割り当てます。
注意-頂点シェーダーは各頂点で実行されるため、三角形のすべての頂点が変換されます。
三角形を翻訳する手順
WebGLアプリケーションを作成して三角形を描画し、それを新しい位置に変換するには、次の手順が必要です。
ステップ1-キャンバスを準備し、WebGLレンダリングコンテキストを取得
このステップでは、* getContext()*を使用してWebGLレンダリングコンテキストオブジェクトを取得します。
ステップ2-ジオメトリを定義し、バッファオブジェクトに格納します
三角形を描画しているため、三角形の3つの頂点を渡して、バッファーに保存する必要があります。
var vertices = [ -0.5,0.5,0.0, -0.5,-0.5,0.0, 0.5,-0.5,0.0, ];
ステップ3-シェーダープログラムの作成とコンパイル
この手順では、頂点シェーダーおよびフラグメントシェーダープログラムを記述し、それらをコンパイルし、これらの2つのプログラムをリンクして結合プログラムを作成する必要があります。
- 頂点シェーダー-プログラムの頂点シェーダーで、3D座標を格納するためのベクター属性を定義します。 それと共に、平行移動距離を格納するための均一変数を定義し、最後にこれらの2つの値を追加して、頂点の最終位置を保持する gl_position に割り当てます。
var vertCode =
'attribute vec4 coordinates;' +
'uniform vec4 translation;'+
'void main(void) {' +
' gl_Position = coordinates + translation;' +
'}';
- フラグメントシェーダー-フラグメントシェーダーでは、フラグメントカラーを変数gl_FragColorに単純に割り当てます。
var fragCode = 'void main(void) {' +' gl_FragColor = vec4(1, 0.5, 0.0, 1);' +'}';
ステップ4-シェーダープログラムをバッファオブジェクトに関連付ける
この手順では、バッファーオブジェクトをシェーダープログラムに関連付けます。
ステップ5-必要なオブジェクトの描画
インデックスを使用して三角形を描画しているため、メソッド* drawArrays()*を使用します。 このメソッドには、考慮される頂点/要素の数を渡す必要があります。 三角形を描画しているため、3をパラメーターとして渡します。
gl.drawArrays(gl.TRIANGLES, 0, 3);
例–三角形の翻訳
次の例は、xyz平面上の三角形を変換する方法を示しています。
<!doctype html>
<html>
<body>
<canvas width = "300" height = "300" id = "my_Canvas"></canvas>
<script>
/*=================Creating a canvas=========================*/
var canvas = document.getElementById('my_Canvas');
gl = canvas.getContext('experimental-webgl');
/*===========Defining and storing the geometry==============*/
var vertices = [
-0.5,0.5,0.0,
-0.5,-0.5,0.0,
0.5,-0.5,0.0,
];
//Create an empty buffer object and store vertex data
var vertex_buffer = gl.createBuffer();
//Create a new buffer
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
//bind it to the current buffer
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
//Pass the buffer data
gl.bindBuffer(gl.ARRAY_BUFFER, null);
/*========================Shaders============================*/
//vertex shader source code
var vertCode =
'attribute vec4 coordinates;' +
'uniform vec4 translation;'+
'void main(void) {' +
' gl_Position = coordinates + translation;' +
'}';
//Create a vertex shader program object and compile it
var vertShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertShader, vertCode);
gl.compileShader(vertShader);
//fragment shader source code
var fragCode =
'void main(void) {' +
' gl_FragColor = vec4(0.0, 0.0, 0.0, 0.1);' +
'}';
//Create a fragment shader program object and compile it
var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragShader, fragCode);
gl.compileShader(fragShader);
//Create and use combiened shader program
var shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertShader);
gl.attachShader(shaderProgram, fragShader);
gl.linkProgram(shaderProgram);
gl.useProgram(shaderProgram);
/* ===========Associating shaders to buffer objects============*/
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
var coordinatesVar = gl.getAttribLocation(shaderProgram, "coordinates");
gl.vertexAttribPointer(coordinatesVar, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(coordinatesVar);
/* ==========translation======================================*/
var Tx = 0.5, Ty = 0.5, Tz = 0.0;
var translation = gl.getUniformLocation(shaderProgram, 'translation');
gl.uniform4f(translation, Tx, Ty, Tz, 0.0);
/*=================Drawing the riangle and transforming it========================*/
gl.clearColor(0.5, 0.5, 0.5, 0.9);
gl.enable(gl.DEPTH_TEST);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.viewport(0,0,canvas.width,canvas.height);
gl.drawArrays(gl.TRIANGLES, 0, 3);
</script>
</body>
</html>
この例を実行すると、次の出力が生成されます-
WebGL-スケーリング
この章では、WebGLを使用して三角形のスケールを変更する方法を示す例を取り上げます。
スケーリング
スケーリングは、オブジェクトのサイズを拡大または縮小することに他なりません。 たとえば、三角形にサイズ[a、b、c]の頂点がある場合、頂点[2a、2b、2c]の三角形のサイズは2倍になります。 したがって、三角形をスケーリングするには、各頂点にスケーリング係数を掛ける必要があります。 特定の頂点をスケーリングすることもできます。
三角形をスケーリングするには、プログラムの頂点シェーダーで、均一なマトリックスを作成し、このマトリックスで座標値を乗算します。 後で、対角位置(最後の対角位置1)にx、y、z座標のスケーリング係数を持つ4×4対角行列を渡します。
必要な手順
WebGLアプリケーションを作成して三角形を拡大縮小するには、次の手順が必要です。
ステップ1-キャンバスを準備し、WebGLレンダリングコンテキストを取得
このステップでは、* getContext()*を使用してWebGLレンダリングコンテキストオブジェクトを取得します。
ステップ2-ジオメトリを定義し、バッファオブジェクトに格納します
三角形を描画しているため、三角形の3つの頂点を渡して、バッファーに保存する必要があります。
var vertices = [ -0.5,0.5,0.0, -0.5,-0.5,0.0, 0.5,-0.5,0.0, ];
ステップ3-シェーダープログラムの作成とコンパイル
この手順では、頂点シェーダーおよびフラグメントシェーダープログラムを記述し、それらをコンパイルし、これらの2つのプログラムをリンクして結合プログラムを作成する必要があります。
- 頂点シェーダー-プログラムの頂点シェーダーで、3D座標を格納するためのベクター属性を定義します。 それとともに、スケーリング係数を格納するために均一なマトリックスを定義し、最後に、これらの2つの値を乗算して、頂点の最終位置を保持する gl_position に割り当てます。
var vertCode =
'attribute vec4 coordinates;' +
'uniform mat4 u_xformMatrix;' +
'void main(void) {' +
' gl_Position = u_xformMatrix * coordinates;' +
'}';
- フラグメントシェーダー-フラグメントシェーダーでは、フラグメントの色を gl_FragColor 変数に割り当てるだけです。
var fragCode = 'void main(void) {' +' gl_FragColor = vec4(1, 0.5, 0.0, 1);' +'}';
ステップ4-シェーダープログラムをバッファオブジェクトに関連付ける
この手順では、バッファーオブジェクトをシェーダープログラムに関連付けます。
ステップ5-必要なオブジェクトの描画
インデックスを使用して三角形を描画しているため、* drawArrays()*メソッドを使用します。 このメソッドには、考慮される頂点/要素の数を渡す必要があります。 三角形を描画しているため、3をパラメーターとして渡します。
gl.drawArrays(gl.TRIANGLES, 0, 3);
例–三角形のスケーリング
次の例は、三角形をスケーリングする方法を示しています-
<!doctype html>
<html>
<body>
<canvas width = "300" height = "300" id = "my_Canvas"></canvas>
<script>
/*=================Creating a canvas=========================*/
var canvas = document.getElementById('my_Canvas');
gl = canvas.getContext('experimental-webgl');
/*===========Defining and storing the geometry==============*/
var vertices = [
-0.5,0.5,0.0,
-0.5,-0.5,0.0,
0.5,-0.5,0.0,
];
//Create an empty buffer object and store vertex data
var vertex_buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
/*========================Shaders============================*/
//Vertex shader source code
var vertCode =
'attribute vec4 coordinates;' +
'uniform mat4 u_xformMatrix;' +
'void main(void) {' +
' gl_Position = u_xformMatrix * coordinates;' +
'}';
//Create a vertex shader program object and compile it
var vertShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertShader, vertCode);
gl.compileShader(vertShader);
//fragment shader source code
var fragCode =
'void main(void) {' +
' gl_FragColor = vec4(0.0, 0.0, 0.0, 0.1);' +
'}';
//Create a fragment shader program object and compile it
var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragShader, fragCode);
gl.compileShader(fragShader);
//Create and use combiened shader program
var shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertShader);
gl.attachShader(shaderProgram, fragShader);
gl.linkProgram(shaderProgram);
gl.useProgram(shaderProgram);
/*===================scaling==========================*/
var Sx = 1.0, Sy = 1.5, Sz = 1.0;
var xformMatrix = new Float32Array([
Sx, 0.0, 0.0, 0.0,
0.0, Sy, 0.0, 0.0,
0.0, 0.0, Sz, 0.0,
0.0, 0.0, 0.0, 1.0
]);
var u_xformMatrix = gl.getUniformLocation(shaderProgram, 'u_xformMatrix');
gl.uniformMatrix4fv(u_xformMatrix, false, xformMatrix);
/* ===========Associating shaders to buffer objects============*/
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
var coordinatesVar = gl.getAttribLocation(shaderProgram, "coordinates");
gl.vertexAttribPointer(coordinatesVar, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(coordinatesVar);
/*=================Drawing the Quad========================*/
gl.clearColor(0.5, 0.5, 0.5, 0.9);
gl.enable(gl.DEPTH_TEST);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.viewport(0,0,canvas.width,canvas.height);
gl.drawArrays(gl.TRIANGLES, 0, 3);
</script>
</body>
</html>
この例を実行すると、次の出力が生成されます-
WebGL-ローテーション
この章では、WebGLを使用して三角形を回転する方法を示す例を取り上げます。
例–三角形を回転させる
次のプログラムは、WebGLを使用して三角形を回転する方法を示しています。
<!doctype html>
<html>
<body>
<canvas width = "400" height = "400" id = "my_Canvas"></canvas>
<script>
/*=================Creating a canvas=========================*/
var canvas = document.getElementById('my_Canvas');
gl = canvas.getContext('experimental-webgl');
/*===========Defining and storing the geometry==============*/
var vertices = [ -1,-1,-1, 1,-1,-1, 1, 1,-1 ];
var colors = [ 1,1,1, 1,1,1, 1,1,1 ];
var indices = [ 0,1,2 ];
//Create and store data into vertex buffer
var vertex_buffer = gl.createBuffer ();
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
//Create and store data into color buffer
var color_buffer = gl.createBuffer ();
gl.bindBuffer(gl.ARRAY_BUFFER, color_buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
//Create and store data into index buffer
var index_buffer = gl.createBuffer ();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
/*==========================Shaders=========================*/
var vertCode = 'attribute vec3 position;'+
'uniform mat4 Pmatrix;'+
'uniform mat4 Vmatrix;'+
'uniform mat4 Mmatrix;'+
'attribute vec3 color;'+//the color of the point
'varying vec3 vColor;'+
'void main(void) { '+//pre-built function
'gl_Position = Pmatrix*Vmatrix*Mmatrix*vec4(position, 1.);'+
'vColor = color;'+
'}';
var fragCode = 'precision mediump float;'+
'varying vec3 vColor;'+
'void main(void) {'+
'gl_FragColor = vec4(vColor, 1.);'+
'}';
var vertShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertShader, vertCode);
gl.compileShader(vertShader);
var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragShader, fragCode);
gl.compileShader(fragShader);
var shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertShader);
gl.attachShader(shaderProgram, fragShader);
gl.linkProgram(shaderProgram);
/*===========associating attributes to vertex shader ============*/
var Pmatrix = gl.getUniformLocation(shaderProgram, "Pmatrix");
var Vmatrix = gl.getUniformLocation(shaderProgram, "Vmatrix");
var Mmatrix = gl.getUniformLocation(shaderProgram, "Mmatrix");
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
var position = gl.getAttribLocation(shaderProgram, "position");
gl.vertexAttribPointer(position, 3, gl.FLOAT, false,0,0) ;//position
gl.enableVertexAttribArray(position);
gl.bindBuffer(gl.ARRAY_BUFFER, color_buffer);
var color = gl.getAttribLocation(shaderProgram, "color");
gl.vertexAttribPointer(color, 3, gl.FLOAT, false,0,0) ;//color
gl.enableVertexAttribArray(color);
gl.useProgram(shaderProgram);
/*========================= MATRIX ========================= */
function get_projection(angle, a, zMin, zMax) {
var ang = Math.tan((angle*.5)*Math.PI/180);//angle*.5
return [
0.5/ang, 0 , 0, 0,
0, 0.5*a/ang, 0, 0,
0, 0, -(zMax+zMin)/(zMax-zMin), -1,
0, 0, (-2*zMax*zMin)/(zMax-zMin), 0
];
}
var proj_matrix = get_projection(40, canvas.width/canvas.height, 1, 100);
var mov_matrix = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1];
var view_matrix = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1];
//translating z
view_matrix[14] = view_matrix[14]-6;//zoom
/*=======================rotation========================*/
function rotateZ(m, angle) {
var c = Math.cos(angle);
var s = Math.sin(angle);
var mv0 = m[0], mv4 = m[4], mv8 = m[8];
m[0] = c*m[0]-s*m[1];
m[4] = c*m[4]-s*m[5];
m[8] = c*m[8]-s*m[9];
m[1] = c*m[1]+s*mv0;
m[5] = c*m[5]+s*mv4;
m[9] = c*m[9]+s*mv8;
}
/*=================Drawing===========================*/
var time_old = 0;
var animate = function(time) {
var dt = time-time_old;
rotateZ(mov_matrix, dt*0.002);
time_old = time;
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
gl.clearColor(0.5, 0.5, 0.5, 0.9);
gl.clearDepth(1.0);
gl.viewport(0.0, 0.0, canvas.width, canvas.height);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.uniformMatrix4fv(Pmatrix, false, proj_matrix);
gl.uniformMatrix4fv(Vmatrix, false, view_matrix);
gl.uniformMatrix4fv(Mmatrix, false, mov_matrix);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buffer);
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
window.requestAnimationFrame(animate);
}
animate(0);
</script>
</body>
</html>
この例を実行すると、次の出力が生成されます-
WebGL-キューブ回転
この章では、WebGLを使用して回転3Dキューブを描画する方法を示す例を取り上げます。
例–回転する3Dキューブを描く
次のプログラムは、回転する3Dキューブを描画する方法を示しています-
<!doctype html>
<html>
<body>
<canvas width = "570" height = "570" id = "my_Canvas"></canvas>
<script>
/*============= Creating a canvas =================*/
var canvas = document.getElementById('my_Canvas');
gl = canvas.getContext('experimental-webgl');
/*============ Defining and storing the geometry =========*/
var vertices = [
-1,-1,-1, 1,-1,-1, 1, 1,-1, -1, 1,-1,
-1,-1, 1, 1,-1, 1, 1, 1, 1, -1, 1, 1,
-1,-1,-1, -1, 1,-1, -1, 1, 1, -1,-1, 1,
1,-1,-1, 1, 1,-1, 1, 1, 1, 1,-1, 1,
-1,-1,-1, -1,-1, 1, 1,-1, 1, 1,-1,-1,
-1, 1,-1, -1, 1, 1, 1, 1, 1, 1, 1,-1,
];
var colors = [
5,3,7, 5,3,7, 5,3,7, 5,3,7,
1,1,3, 1,1,3, 1,1,3, 1,1,3,
0,0,1, 0,0,1, 0,0,1, 0,0,1,
1,0,0, 1,0,0, 1,0,0, 1,0,0,
1,1,0, 1,1,0, 1,1,0, 1,1,0,
0,1,0, 0,1,0, 0,1,0, 0,1,0
];
var indices = [
0,1,2, 0,2,3, 4,5,6, 4,6,7,
8,9,10, 8,10,11, 12,13,14, 12,14,15,
16,17,18, 16,18,19, 20,21,22, 20,22,23
];
//Create and store data into vertex buffer
var vertex_buffer = gl.createBuffer ();
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
//Create and store data into color buffer
var color_buffer = gl.createBuffer ();
gl.bindBuffer(gl.ARRAY_BUFFER, color_buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
//Create and store data into index buffer
var index_buffer = gl.createBuffer ();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
/*=================== Shaders =========================*/
var vertCode = 'attribute vec3 position;'+
'uniform mat4 Pmatrix;'+
'uniform mat4 Vmatrix;'+
'uniform mat4 Mmatrix;'+
'attribute vec3 color;'+//the color of the point
'varying vec3 vColor;'+
'void main(void) { '+//pre-built function
'gl_Position = Pmatrix*Vmatrix*Mmatrix*vec4(position, 1.);'+
'vColor = color;'+
'}';
var fragCode = 'precision mediump float;'+
'varying vec3 vColor;'+
'void main(void) {'+
'gl_FragColor = vec4(vColor, 1.);'+
'}';
var vertShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertShader, vertCode);
gl.compileShader(vertShader);
var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragShader, fragCode);
gl.compileShader(fragShader);
var shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertShader);
gl.attachShader(shaderProgram, fragShader);
gl.linkProgram(shaderProgram);
/* ====== Associating attributes to vertex shader =====*/
var Pmatrix = gl.getUniformLocation(shaderProgram, "Pmatrix");
var Vmatrix = gl.getUniformLocation(shaderProgram, "Vmatrix");
var Mmatrix = gl.getUniformLocation(shaderProgram, "Mmatrix");
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
var position = gl.getAttribLocation(shaderProgram, "position");
gl.vertexAttribPointer(position, 3, gl.FLOAT, false,0,0) ;
//Position
gl.enableVertexAttribArray(position);
gl.bindBuffer(gl.ARRAY_BUFFER, color_buffer);
var color = gl.getAttribLocation(shaderProgram, "color");
gl.vertexAttribPointer(color, 3, gl.FLOAT, false,0,0) ;
//Color
gl.enableVertexAttribArray(color);
gl.useProgram(shaderProgram);
/*==================== MATRIX =====================*/
function get_projection(angle, a, zMin, zMax) {
var ang = Math.tan((angle*.5)*Math.PI/180);//angle*.5
return [
0.5/ang, 0 , 0, 0,
0, 0.5*a/ang, 0, 0,
0, 0, -(zMax+zMin)/(zMax-zMin), -1,
0, 0, (-2*zMax*zMin)/(zMax-zMin), 0
];
}
var proj_matrix = get_projection(40, canvas.width/canvas.height, 1, 100);
var mov_matrix = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1];
var view_matrix = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1];
//translating z
view_matrix[14] = view_matrix[14]-6;//zoom
/*==================== Rotation ====================*/
function rotateZ(m, angle) {
var c = Math.cos(angle);
var s = Math.sin(angle);
var mv0 = m[0], mv4 = m[4], mv8 = m[8];
m[0] = c*m[0]-s*m[1];
m[4] = c*m[4]-s*m[5];
m[8] = c*m[8]-s*m[9];
m[1]=c*m[1]+s*mv0;
m[5]=c*m[5]+s*mv4;
m[9]=c*m[9]+s*mv8;
}
function rotateX(m, angle) {
var c = Math.cos(angle);
var s = Math.sin(angle);
var mv1 = m[1], mv5 = m[5], mv9 = m[9];
m[1] = m[1]*c-m[2]*s;
m[5] = m[5]*c-m[6]*s;
m[9] = m[9]*c-m[10]*s;
m[2] = m[2]*c+mv1*s;
m[6] = m[6]*c+mv5*s;
m[10] = m[10]*c+mv9*s;
}
function rotateY(m, angle) {
var c = Math.cos(angle);
var s = Math.sin(angle);
var mv0 = m[0], mv4 = m[4], mv8 = m[8];
m[0] = c*m[0]+s*m[2];
m[4] = c*m[4]+s*m[6];
m[8] = c*m[8]+s*m[10];
m[2] = c*m[2]-s*mv0;
m[6] = c*m[6]-s*mv4;
m[10] = c*m[10]-s*mv8;
}
/*================= Drawing ===========================*/
var time_old = 0;
var animate = function(time) {
var dt = time-time_old;
rotateZ(mov_matrix, dt*0.005);//time
rotateY(mov_matrix, dt*0.002);
rotateX(mov_matrix, dt*0.003);
time_old = time;
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
gl.clearColor(0.5, 0.5, 0.5, 0.9);
gl.clearDepth(1.0);
gl.viewport(0.0, 0.0, canvas.width, canvas.height);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.uniformMatrix4fv(Pmatrix, false, proj_matrix);
gl.uniformMatrix4fv(Vmatrix, false, view_matrix);
gl.uniformMatrix4fv(Mmatrix, false, mov_matrix);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buffer);
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
window.requestAnimationFrame(animate);
}
animate(0);
</script>
</body>
</html>
この例を実行すると、次の出力が生成されます-
WebGL-インタラクティブキューブ
この章では、マウスコントロールを使用して回転できる3Dキューブを描画する方法を示す例を取り上げます。
例–インタラクティブなキューブを描く
次のプログラムは、マウスコントロールを使用してキューブを回転させる方法を示しています-
<!doctype html>
<html>
<body>
<canvas width = "570" height = "570" id = "my_Canvas"></canvas>
<script>
/*============= Creating a canvas ======================*/
var canvas = document.getElementById('my_Canvas');
gl = canvas.getContext('experimental-webgl');
/*========== Defining and storing the geometry ==========*/
var vertices = [
-1,-1,-1, 1,-1,-1, 1, 1,-1, -1, 1,-1,
-1,-1, 1, 1,-1, 1, 1, 1, 1, -1, 1, 1,
-1,-1,-1, -1, 1,-1, -1, 1, 1, -1,-1, 1,
1,-1,-1, 1, 1,-1, 1, 1, 1, 1,-1, 1,
-1,-1,-1, -1,-1, 1, 1,-1, 1, 1,-1,-1,
-1, 1,-1, -1, 1, 1, 1, 1, 1, 1, 1,-1,
];
var colors = [
5,3,7, 5,3,7, 5,3,7, 5,3,7,
1,1,3, 1,1,3, 1,1,3, 1,1,3,
0,0,1, 0,0,1, 0,0,1, 0,0,1,
1,0,0, 1,0,0, 1,0,0, 1,0,0,
1,1,0, 1,1,0, 1,1,0, 1,1,0,
0,1,0, 0,1,0, 0,1,0, 0,1,0
];
var indices = [
0,1,2, 0,2,3, 4,5,6, 4,6,7,
8,9,10, 8,10,11, 12,13,14, 12,14,15,
16,17,18, 16,18,19, 20,21,22, 20,22,23
];
//Create and store data into vertex buffer
var vertex_buffer = gl.createBuffer ();
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
//Create and store data into color buffer
var color_buffer = gl.createBuffer ();
gl.bindBuffer(gl.ARRAY_BUFFER, color_buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
//Create and store data into index buffer
var index_buffer = gl.createBuffer ();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
/*=================== SHADERS =================== */
var vertCode = 'attribute vec3 position;'+
'uniform mat4 Pmatrix;'+
'uniform mat4 Vmatrix;'+
'uniform mat4 Mmatrix;'+
'attribute vec3 color;'+//the color of the point
'varying vec3 vColor;'+
'void main(void) { '+//pre-built function
'gl_Position = Pmatrix*Vmatrix*Mmatrix*vec4(position, 1.);'+
'vColor = color;'+
'}';
var fragCode = 'precision mediump float;'+
'varying vec3 vColor;'+
'void main(void) {'+
'gl_FragColor = vec4(vColor, 1.);'+
'}';
var vertShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertShader, vertCode);
gl.compileShader(vertShader);
var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragShader, fragCode);
gl.compileShader(fragShader);
var shaderprogram = gl.createProgram();
gl.attachShader(shaderprogram, vertShader);
gl.attachShader(shaderprogram, fragShader);
gl.linkProgram(shaderprogram);
/*======== Associating attributes to vertex shader =====*/
var _Pmatrix = gl.getUniformLocation(shaderprogram, "Pmatrix");
var _Vmatrix = gl.getUniformLocation(shaderprogram, "Vmatrix");
var _Mmatrix = gl.getUniformLocation(shaderprogram, "Mmatrix");
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
var _position = gl.getAttribLocation(shaderprogram, "position");
gl.vertexAttribPointer(_position, 3, gl.FLOAT, false,0,0);
gl.enableVertexAttribArray(_position);
gl.bindBuffer(gl.ARRAY_BUFFER, color_buffer);
var _color = gl.getAttribLocation(shaderprogram, "color");
gl.vertexAttribPointer(_color, 3, gl.FLOAT, false,0,0) ;
gl.enableVertexAttribArray(_color);
gl.useProgram(shaderprogram);
/*==================== MATRIX ====================== */
function get_projection(angle, a, zMin, zMax) {
var ang = Math.tan((angle*.5)*Math.PI/180);//angle*.5
return [
0.5/ang, 0 , 0, 0,
0, 0.5*a/ang, 0, 0,
0, 0, -(zMax+zMin)/(zMax-zMin), -1,
0, 0, (-2*zMax*zMin)/(zMax-zMin), 0
];
}
var proj_matrix = get_projection(40, canvas.width/canvas.height, 1, 100);
var mo_matrix = [ 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 ];
var view_matrix = [ 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 ];
view_matrix[14] = view_matrix[14]-6;
/*================= Mouse events ======================*/
var AMORTIZATION = 0.95;
var drag = false;
var old_x, old_y;
var dX = 0, dY = 0;
var mouseDown = function(e) {
drag = true;
old_x = e.pageX, old_y = e.pageY;
e.preventDefault();
return false;
};
var mouseUp = function(e){
drag = false;
};
var mouseMove = function(e) {
if (!drag) return false;
dX = (e.pageX-old_x)*2*Math.PI/canvas.width,
dY = (e.pageY-old_y)*2*Math.PI/canvas.height;
THETA+= dX;
PHI+=dY;
old_x = e.pageX, old_y = e.pageY;
e.preventDefault();
};
canvas.addEventListener("mousedown", mouseDown, false);
canvas.addEventListener("mouseup", mouseUp, false);
canvas.addEventListener("mouseout", mouseUp, false);
canvas.addEventListener("mousemove", mouseMove, false);
/*=========================rotation================*/
function rotateX(m, angle) {
var c = Math.cos(angle);
var s = Math.sin(angle);
var mv1 = m[1], mv5 = m[5], mv9 = m[9];
m[1] = m[1]*c-m[2]*s;
m[5] = m[5]*c-m[6]*s;
m[9] = m[9]*c-m[10]*s;
m[2] = m[2]*c+mv1*s;
m[6] = m[6]*c+mv5*s;
m[10] = m[10]*c+mv9*s;
}
function rotateY(m, angle) {
var c = Math.cos(angle);
var s = Math.sin(angle);
var mv0 = m[0], mv4 = m[4], mv8 = m[8];
m[0] = c*m[0]+s*m[2];
m[4] = c*m[4]+s*m[6];
m[8] = c*m[8]+s*m[10];
m[2] = c*m[2]-s*mv0;
m[6] = c*m[6]-s*mv4;
m[10] = c*m[10]-s*mv8;
}
/*=================== Drawing =================== */
var THETA = 0,
PHI = 0;
var time_old = 0;
var animate = function(time) {
var dt = time-time_old;
if (!drag) {
dX *= AMORTIZATION, dY*=AMORTIZATION;
THETA+=dX, PHI+=dY;
}
//set model matrix to I4
mo_matrix[0] = 1, mo_matrix[1] = 0, mo_matrix[2] = 0,
mo_matrix[3] = 0,
mo_matrix[4] = 0, mo_matrix[5] = 1, mo_matrix[6] = 0,
mo_matrix[7] = 0,
mo_matrix[8] = 0, mo_matrix[9] = 0, mo_matrix[10] = 1,
mo_matrix[11] = 0,
mo_matrix[12] = 0, mo_matrix[13] = 0, mo_matrix[14] = 0,
mo_matrix[15] = 1;
rotateY(mo_matrix, THETA);
rotateX(mo_matrix, PHI);
time_old = time;
gl.enable(gl.DEPTH_TEST);
//gl.depthFunc(gl.LEQUAL);
gl.clearColor(0.5, 0.5, 0.5, 0.9);
gl.clearDepth(1.0);
gl.viewport(0.0, 0.0, canvas.width, canvas.height);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.uniformMatrix4fv(_Pmatrix, false, proj_matrix);
gl.uniformMatrix4fv(_Vmatrix, false, view_matrix);
gl.uniformMatrix4fv(_Mmatrix, false, mo_matrix);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buffer);
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
window.requestAnimationFrame(animate);
}
animate(0);
</script>
</body>
</html>
この例を実行すると、次の出力が生成されます-