参考webglorg;
原則として上記ページを見ながら学習した記録です。
大まかな流れ
- HTMLからcanvasエレメントを取得
- canvasからWebGLコンテキストの取得
- シェーダのコンパイル
- モデルデータを用意
- 頂点バッファの生成と通知
- 座標変換行列の生成と通知
- 描写命令発行
- canvasを更新してレンダリング
ソースをコンパイルしてシェーダを生成する一連の流れ
function create_shader(id){
// シェーダを格納する変数
var shader;
// HTMLからscriptタグへの参照を取得
var scriptElement = document.getElementById(id);
// scriptタグが存在しない場合は抜ける
if(!scriptElement){return;}
// scriptタグのtype属性をチェック
switch(scriptElement.type){
// 頂点シェーダの場合
case 'x-shader/x-vertex':
shader = gl.createShader(gl.VERTEX_SHADER);
break;
// フラグメントシェーダの場合
case 'x-shader/x-fragment':
shader = gl.createShader(gl.FRAGMENT_SHADER);
break;
default :
return;
}
// 生成されたシェーダにソースを割り当てる
gl.shaderSource(shader, scriptElement.text);
// シェーダをコンパイルする
gl.compileShader(shader);
// シェーダが正しくコンパイルされたかチェック
if(gl.getShaderParameter(shader, gl.COMPILE_STATUS)){
// 成功していたらシェーダを返して終了
return shader;
}else{
// 失敗していたらエラーログをアラートする
alert(gl.getShaderInfoLog(shader));
}
}
プログラムオムジェクトの生成とリンク
シェーダを生成できたら次はプログラムオブジェクトを生成する。
頂点シェーダからフラグメントシェーダへデータを渡すために、 varying 修飾子付きの変数を使うことができるが、このシェーダからシェーダへのデータの橋渡しを実現してくれるのが、プログラムオブジェクト。
プログラムオブジェクトは、頂点シェーダとフラグメントシェーダ、また WebGL プログラムと各シェーダとのデータのやり取りを管理してくれる重要なオブジェクト。
function create_program(vs, fs){
// プログラムオブジェクトの生成
var program = gl.createProgram();
// プログラムオブジェクトにシェーダを割り当てる
gl.attachShader(program, vs);
gl.attachShader(program, fs);
// シェーダをリンク
gl.linkProgram(program);
// シェーダのリンクが正しく行なわれたかチェック
if(gl.getProgramParameter(program, gl.LINK_STATUS)){
// 成功していたらプログラムオブジェクトを有効にする
gl.useProgram(program);
// プログラムオブジェクトを返して終了
return program;
}else{
// 失敗していたらエラーログをアラートする
alert(gl.getProgramInfoLog(program));
}
}
モデルデータと頂点属性
頂点属性とは
頂点属性とは、頂点が持つ様々な要素のこと。
WebGL の場合は最低限、頂点が位置情報という属性を持っている必要がある。
頂点属性とVBO
VBO を生成するためには、まず先に頂点の個数に応じた配列を用意する。
例えば三つの頂点からなる一枚のポリゴンを定義するときは・・・
var vertex_position = [
// X, Y, Z
0.0, 1.0, 0.0,
1.0, 0.0, 0.0,
-1.0, 0.0, 0.0
];
VBOの生成
createBufferを使う。
バッファを操作するためには、バッファをWebGLにバインドする必要がある。
function create_vbo(data){
// バッファオブジェクトの生成
var vbo = gl.createBuffer();
// バッファをバインドする
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
// バッファにデータをセット
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.STATIC_DRAW);
// バッファのバインドを無効化
gl.bindBuffer(gl.ARRAY_BUFFER, null);
// 生成した VBO を返して終了
return vbo;
}