のぐそんブログ

暗いおじさんがシコシコ書くブログです。

WebGLを使って三角形を描画する為の基礎知識

WebGLを使って三角形を描画する為の基礎知識を学びたいと思います。 ちなみに、こちらに記載されている内容だけでは三角形は描画できません。

頂点バッファとインデックスバッファ

バッファ( buffer )とは、データの記憶領域などを表す一般的なコンピュータ用語です。 頂点バッファの基礎参照

頂点バッファ(VBO)

VBOは頂点データを格納する為のバッファです。 座標データや、塗のデータなどを頂点属性を格納します。

VBOに格納された頂点データは、GLSLのattribute変数に紐付けられる。

Kobito.fezzyz.png

頂点データはJavaScriptの配列として定義する。

VBOの作成方法

Kobito.gMLOWy.png

//glはキャンバスのコンテキスト
var gl = canvas.getContext('webgl');
var vbo = gl.createBuffer(); // 空のバッファを生成
gl.bindBuffer(gl.ARRAY_BUFFER, vbo); // バッファをバインド

//dataは頂点属性(配列形式)
gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(data), gl.STATIC_DRAW);
gl.bindBuffer(this.gl.ARRAY_BUFFER, null); // バッファのバインドを解除

インデックスバッファ(IBO)

IBOは頂点の描画の順番を指定する為に使用します。 頂点をどの順番で結んで行くかをバッファにしてGPUに送ることで、ポリゴンが作成されます。

Kobito.CKF6B5.png

ポリゴンの裏と表

ちなみにポリゴンには裏と表があり、 反時計周りに描くと「表」 時計回りに描くと「裏」となる。

カリング

表面と裏面でポリゴンを描いたり消したりすることができる機能のことをカリングという。

設定は、webglのコンテキストのプロパティとして設定できる。

◎表面だけ描画する。

gl.enable(gl.CULL_FACE); 

◎裏面だけ描画する。

gl.enable(gl.CULL_BACK); 

IBOの作成方法

//glはキャンバスのコンテキスト
var gl = canvas.getContext('webgl');
var ibo = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo);

//dataはインデックスデータ(配列形式)
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Int16Array(data), gl.STATIC_DRAW);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);

GLSLとは

シェーダを記述するための言語。GPU側で動作する特殊なプログラミング言語です。

頂点シェーダとフラグメントシェーダ

頂点シェーダー

主に頂点の座表示変換を行うのが頂点シェーダーの役割です。 座標だけでなく、頂点属性に係る色や、法線なども頂点シェーダーが管理しています。

フラグメントシェーダー

フラグメントシェーダーは各ピクセルに対してどんな色で出力するかを処理しています。

描画の仕組み

GLSLで定義された、頂点シェーダとフラグメントシェーダはプログラムオブジェクトに登録された後に描画されます。

Kobito.gzCM9s.png

GLSLの書き方

まずは3つの修飾子と、main関数を覚えます。

main関数

シェーダーには必ずmain関数が必要です。 これでシェーダーの行う処理を定義します。

attribute vec3 position;

void main() {
    gl_Position = position;
}
attribute

attributeが付いた変数は、頂点属性が格納された変数です。VBOに格納された値を参照する場合はattributeを使います。 頂点毎に 異なる 情報を受取る為のものです。

attribute vec3 position;

void main() {
    gl_Position = position;
}
uniform

attributeは頂点毎に異なる情報をシェーダーに渡すために使用しました。 uniformは全頂点に対して一律で使用する座標変換などの情報を渡すのに使用します。

イメージ的にはグローバル変数のような感じになります。 uniformはattributeと違い、バッファにバインドする必要がなく、JS側から直接値を送ることができます。

attribute vec3 position;
uniform mat4 mvpMatrix;

void main(void) {
    gl_Position = mvpMatrix * position;
}
varying

varyingは頂点シェーダーから、フラグメントシェーダに値を送る際に使用します。 頂点シェーダーに格納された、色情報を最終的に描画するのはフラグメントシェーダーです。 その為、varying変数を使ってフラグメントシェーダーに値を送ります。

attribute vec4 color;
varying vec4 vColor

void main(void) {
    vColor = color;
}
varying vec4 vColor;

void main(void)
{
    gl_FragColor = vColor;
}

まとめ

WebGLで、ポリゴン1つ書くためにも色々な処理をする必要があります。 はたして、これを使いこなせるが自信がありません。