BETA

WebGLについて

投稿日:2019-09-13
最終更新:2019-11-06

はじめに

唐突にWebGLについて理解を深めたいと思ったので、今まではログ専でしたが記事を書いてみることにしました。今後も時間が取れ次第、新記事or追記という形で更新したいと思っています。

WebGLとは

wikiを引用

WebGL(ウェブジーエル)は、ウェブブラウザで3次元コンピュータグラフィックスを表示させるための標準仕様。非営利団体のKhronos Groupで管理されている。WebGL 1.0は、ブラウザ上で利用できるOpenGL ES 2.0の派生規格であるが、細部に違いがある。WebGL 2.0は、ブラウザ上で利用できるOpenGL ES 3.0の派生規格であるが、細部に違いがある。WebGLはHTML5のcanvas要素に描画する。

要はHTMLのcanvas属性を使用して、ブラウザ上で3Dモデルを表示しちゃうよ的なサムシング

まずは生で

WebGLではThree.jsなど便利なライブラリが公開されていますが、自分の理解を多少なりとも深めるためにまずは生で描画をしていきます。
既に先駆者がいらっしゃるので、内容をより砕いて行こうと思います。

1.canvasとWebGLコンテキストの取得

var key = 'canvas';  
var canvas = document.getElementById (key);  
var gl = canvas.getContext('webgl', null);  
var size = Math.min(window.innerWidth, window.innerHeight);  
canvas.width = size;  
canvas.height = size;  

canvas、そしてWebGLコンテキストを取得した上で、サイズ等の設定を行います。

2.シェーダのコンパイル

シェーダis何

よくわからない単語が出てきました。ぐぐります。
wikiを引用

シェーダー(英: shader)とは、3次元コンピュータグラフィックスにおいて、シェーディング(陰影処理)を行うコンピュータプログラムのこと。「shade」とは「次第に変化させる」「陰影・グラデーションを付ける」という意味で、「shader」は頂点色やピクセル色などを次々に変化させるもの(より具体的に、狭義の意味で言えば関数)を意味する。

はい、よくわかりません。wiki語は難しいです。

こちらのサイトでなんとなく掴むことができました。

シェーダとは、3次元コンピュータグラフィックス(3DCG)において、陰影付けや表面の質感や凹凸の設定、各画素の表示色の決定などを行うプログラムのこと。

3Dモデルを表現するためのプログラムというところでしょうか。
いったんそういうことにしておきます。

シェーダの種類

読み進めている中でシェーダにはおおきくわけて2種類あることがわかりました。

  • 頂点シェーダ(vertex shader)
    • モデルを構成する面の頂点の画面上での位置を決定する
  • フラグメントシェーダ(fragment shader)
    • 面を構成する各画素の実際の表示色を決定する
    • ピクセルシェーダとも呼ばれる

れっつコンパイル

var vsElement = document.getElementById ('vs');  
var vs = null;  
if (vsElement.type == 'x-shader/x-vertex') {  
    vs = gl.createShader(gl.VERTEX_SHADER);  
}  
// シェーダオブジェクトに頂点シェーダーを代入  
gl.shaderSource(vs, vsElement.text);  
// 頂点シェーダをコンパイル  
gl.compileShader(vs);  

var fsElement = document.getElementById('fs');  
var fs = null;  
if (fsElement.type == 'x-shader/x-fragment') {  
    fs = gl.createShader(gl.FRAGMENT_SHADER);  
}  
// シェーダオブジェクトにフラグメントシェーダを代入  
gl.shaderSource(fs, fsElement.text);  
// フラグメントシェーダをコンパイル  
gl.compileShader (fs);  

まず頂点シェーダを作成するために、htmlにあるvsというスクリプトを呼び出しています。
これはGLSL(OpenGL Shading Language)と呼ばれているらしいです。

GLSLis何

一応やっておきます。
wikiを引用

GLSL (OpenGL Shading Language) はGLslangとしても知られ、C言語をベースとした高レベルシェーディング言語である。これはアセンブリ言語やハードウェアに依存した言語を使わないで、アプリケーションソフトウェア開発者がグラフィックスパイプラインを直接制御できるようにOpenGL ARB (Architecture Review Board)で策定された。

描画に特化したプログラミング言語というところですかね。

<script id="vs" type="x-shader/x-vertex">  
attribute vec3 position;  
void main ()  
{  
    // 1. JavaScript側から送られた頂点データをそのままgl_Positionに渡す  
    gl_Position = vec4(position, 1.0);  
}  
</script>  

こちらが参考になりました。

  • attribute
    • この修飾子を付けて宣言された変数が、頂点ごとに異なる情報をシェーダ側で受け取る変数となる
  • vec3
    • 3点を持つベクトル

要はこれが頂点位置であり、X,Y,Zが入ってきます。

  • gl_Position
    • 頂点シェーダを受け取るための組み込み変数

gl_Position = vec4(position, 1.0);
ここでは3次元として入ってきたローカル座標の頂点位置を vec4によって4次元に変換しています。

次にフラグメントシェーダですが、こちらも頂点シェーダと似たような形で準備をします。

<script id="fs" type="x-shader/x-fragment">  
precision mediump float;  
void main ()  
{  
    // 2.処理する座標を白色で塗りつぶす  
    gl_FragColor = vec4 (vec3 (1.0), 1.0);  
}  
</script>  
  • precision
    • 精度修飾子とよばれ、どの程度の精度でデータを扱うかを指定できる
  • mediump
    • mediumpという精度でデータを扱う。他にもlowphighpの計3種類がある。

precision mediump float;
floatにmediumpの精度を求めるということになります。
gl_FragColor = vec4 (vec3 (1.0), 1.0);
頂点シェーダと同じような形で設定を行い、こちらは色合いをRGB値で設定します。

3.WebGLProgramとシェーダをリンク

// WebGLProgram  
var program = gl.createProgram();  
// WebGLProgramに頂点シェーダーを紐付ける  
gl.attachShader(program, vs);  
// WebGLProgramにフラグメントシェーダーを紐付ける  
gl.attachShader(program, fs);  
// WebGLProgramに紐付けられた、頂点シェーダとフラグメントシェーダをWebGLProgramにリンクさせる  
gl.linkProgram (program);  
// WebGLProgramのパラメータを取得する  
if (gl.getProgramParameter(program, gl.LINK_STATUS)) {  
    // WebGLProgramを有効化する  
    gl.useProgram(program);  
}else {  
    console.log (gl.getProgramInfoLog(program));  
    return;  
}  

頂点情報と色情報をWebGLにリンクさせています。

4.三角ポリゴンの頂点バッファ生成

// 空のバッファ生成  
var positionBuffer = gl.createBuffer();  
// 生成したバッファをバインドする  
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);  
var position = [  
    0, 0.5, 0,  
    -0.5, -0.5, 0,  
    0.5 ,-0.5, 0  
];  
// バインドされたバッファに三角ポリゴンのデータをセットする  
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array (position), gl.STATIC_DRAW);  
// バインド解除  
gl.bindBuffer(gl.ARRAY_BUFFER, null);  

ここで描画を行っています。
positionの値で図形を変更することができます。

5.描画

render ();  

function render ()  
{  
    // 背景描画  
    gl.clearColor (0.8, 0.8, 0.8, 1.0);  
    // バッファをクリアする  
    gl.clear (gl.COLOR_BUFFER_BIT);  

    // ビューポートを設定  
    gl.viewport(0, 0, size, size);  

    // 三角ポリゴン頂点バッファをバインド  
    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);  
    // 頂点シェーダのアドレスを保持  
    var positionAddress = gl.getAttribLocation(program, "position");  
    // 頂点属性を有効化する  
    gl.enableVertexAttribArray(positionAddress);  
    // 頂点属性に頂点データを設定する  
    gl.vertexAttribPointer(positionAddress, 3, gl.FLOAT, false, 0,   

    //描画  
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 3);  
}  
  • 背景
    • RGBA
  • ビューポート
    • 表示位置の設定
  • 描画
    • gl.TRIANGLE_STRIPを変更することで、表現方法が変わります。

ここまでを行い、htmlを開くと三角ポリゴンが一つ描画されているはずです。

おわりに

とりあえず書き連ねてみましたがまだ頭に入ったという感じは全く無いです。
これを元に簡易3Dモデルの描画をしてからわかったことを補足や追記をしていきます。
その後にライブラリを使ってみて感動する予定です。

技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
駆け出しエンジニアからエキスパートまで全ての方々のアウトプットを歓迎しております!
or 外部アカウントで 登録 / ログイン する
クランチについてもっと詳しく

この記事が掲載されているブログ

だいたいめもたまにめも

よく一緒に読まれる記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう