OpenGL ES 2.0 & WebGL 超入門 (概要編)

OpenGL を全く使ったことがない人を対象に、全体的なイメージを掴んで、基本的な描画ができるようになることを目標にします。

WebGL も OpenGL ES 2.0 をベースにしていますので、同じように理解できるはずです。文中で OpenGL と書いた場合、OpenGL ES 2.0 を指すと思ってください1

まずはコードを動かすことよりも、感覚的にイメージを掴んでもらうことを目指します。全体像が掴めないと、コードを見ても何をやっているのか?どういう仕組みで動いているのか?理解しづらいためです。

この記事は Qiita の記事 と同じものです。

GPU の概要

CPU の並列処理と GPU の並列処理は大きく異なっています。マルチコア CPU では、各 CPU は別のプログラムを並列実行できます。一方 GPU の各演算ユニットは全く同じプログラムを異なるデータに対して並列実行します。

図1.png

これは GPU の仕組みを簡略化して図示したものです。入力データは各演算ユニットにバラバラに渡されます。プログラムと共通設定値(GPU 機能の設定やプログラムで使われる共通値)は全ての演算ユニットで同じものが利用されます。各演算ユニットが並列で動作し、出力値を得ます。

GPU の演算ユニットは単純な処理を高速実行するように設計されていて、条件分岐が非常に苦手です。実行できるプログラムには CPU と違ってかなりの制約があります。

実際の GPU の仕組みはもっと複雑ですが、とりあえず OpenGL 入門としてはこの程度の理解で十分です。

OpenGL ES 2.0 の概要

処理全体の流れ

図2.png

OpenGL の処理全体の流れを図示しました。

セットアップが完了したら、画面更新の度にレンダリング処理を行います。レンダリング処理の先頭で準備を行い、各図形の描画を行い、最後に結果を画面に表示します。

各図形のレンダリングの流れ

図3.png

各図形のレンダリングの流れをものすごく簡略化して図示してみました。

入力値として頂点データを渡します。頂点データは各頂点ごとの情報の集まりで、各頂点の情報には座標はもちろんそれ以外の情報(色やテクスチャ位置など)も含みます。

頂点データは頂点シェーダ(Vertex Shader)というプログラムに渡され、各頂点ごとに別々の演算ユニットで並列実行されます。ここで画面上のどの位置に各頂点が描画されるのか、図形の画面上での形状が決定します。また次の断片シェーダに渡す値の計算も行います。

ラスタライズ処理で図形が実際の画面のピクセルに対応付けられます。

次に断片シェーダ(Fragment Shader)というプログラムが各ピクセルごとに別々の演算ユニットで並列実行され、各ピクセルの色が決定されます。

これを繰り返して図形を描画していきます。単純に実行順で重ね合わせることもできますが、各ピクセルごとの深さ値(depth)で何が手前にくるか決定させることもできます。3D 描画では視点からの距離を深さ値にすることで、手前にあるもので奥にあるものが隠れるように描画させられるわけです。

頂点データに何を含めるかや、頂点シェーダから断片シェーダに何を渡すかは、プログラムで何を行うかで決めることになります2

もう少し具体的に各処理で何が行われるのかを図にしてみました。三角形を一個描画しています。

図4.png

頂点データに含まれる頂点座標は、プログラマが自由に決めた座標空間内の座標で構いません。これを頂点シェーダに渡して、OpenGL 座標空間内の座標に変換します。そして各ピクセルごとに断片シェーダが実行されて色が決まります。

OpenGL 座標空間は次のように考えてください。x 座標の-1.0 が画面左端、1.0 が画面右端、y 座標の 1.0 が画面上部、-1.0 が画面下部、z 座標が深さ値に対応します。画面には z 座標で手前にある物が上に描かれるように重ね合わされます(深さテストを ON にしている場合)。

図5.png

頂点シェーダから断片シェーダへ渡す値

まずはこの描画結果を見てください。三角形の3つの頂点に座標と色を与えて描画したものです。色はそれぞれ青、赤、緑を指定しています。

グラデーション三角形

見事にグラデーションしていますね。以下は今回の処理を図にしたものです。

図6

頂点データのデータ構造は行いたい処理に合わせてプログラマが自由に設計します。ここでは座標と色を渡しています。頂点シェーダから断片シェーダへ渡す値も自由に決められます2。ここでは色をそのまま渡しています。断片シェーダでは渡された色をそのままピクセルの色として採用します。

今回の描画では頂点は3つですがピクセルはもっと沢山あります。頂点と同じ位置のピクセルの色は渡した色そのものでしょうけど、他のピクセルはどうなるのでしょうか?グラデーションしているのを見ればわかると思いますが、頂点シェーダから断片シェーダに渡される値は線形補完されます

三角形は頂点が3つしかありませんので頂点シェーダでは3つの演算が行われるだけです。一方断片シェーダはピクセルの数だけ実行されます3。断片シェーダで重い処理を行うとパフォーマンスが劣化しやすいので注意してください。


  1. OpenGL 一般に言えることもあるかもしれませんが。

  2. 数やサイズにプラットフォームごとの制限はあります。

  3. GPU によっては、上に不透明で重なるものがあって隠れてしまうピクセルは計算しないものもあります。