Edit
OpenGL ESとは

OpenGL for Embedded Systemsを略してOpenGL ESと読んでおり、正に組み込み用のOpenGLのサブセットである。バージョンに関する対応は以下の通り。またこのページでは ES3.0 を中心に説明する。

OpenGLESのバージョン対応OpenGLのバージョン(サブセット)
1.01.3
1.11.5
2.02.0

Edit
バージョン指定

利用するGLESのバージョンを指定するには、GLcontextを作成する場合にバージョン指定の引数をわたすことで有効にできる。

const EGLint attribList[] =
{
    EGL_CONTEXT_CLIENT_VERSION, 3,
    EGL_NONE
};
context = eglCreateContext(display, config, NULL, attribList);

ここでは、android での例だが、glesのコンテキスト周りの関数は環境によって、違うため、詳細は各プラットフォームのリファレンスを参照すること。

Edit
GLとGLESとの違い。

OpenGL ES(OpenGL for Embedded Systems)は、主に携帯電話などの組み込みシステムで使用されている3次元コンピュータグラフィックス用 API である。OpenGL ES の 1.0 と 2.0 は 後方互換性がない別物になってる。

Edit
OpenGL OpenGLES1.0 OpenGLES2.0 の違い

OpenGL

glBegin(GL_TRIANGLES);
   glVertex3f(1,0,0);
   glVertex3f(0,1,0);
   glVertex3f(-1,0,0);
glEnd();

OpenGLES 1.0

GLfloat vertices[] = {1,0,0, 0,1,0, -1,0,0};

glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableClientState(GL_VERTEX_ARRAY);

OpenGLES 2.0以降

static const char gVertexShader[] ="attribute vec4 vPosition;\n void main() {  gl_Position = vPosition; }";
static const char gFragmentShader[] = "precision mediump float;\n void main() { gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n }";

GLuint gProgram;
GLuint gvPositionHandle;
glAttachShader(gProgram, gVertexShader);
glAttachShader(gProgram, gFragmentShader);
glLinkProgram(gProgram);

glUseProgram(gProgram);
glVertexAttribPointer(gvPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices);
glEnableVertexAttribArray(gvPositionHandle);
glDrawArrays(GL_TRIANGLES, 0, 3);

OpenGLでは頂点を配列で渡さず1頂点毎に指定しているが、ESでは配列で処理される。またES2.0では固定機能パイプライン(固定機能シェーダー)が、なくなっているため三角形を描画する場合でも、Vertex Shaderと、Fragment Shader のシェーダーコードが必要になる。

※注意上記ソースだけでは表示されません。あくまで違いの説明の為です。

Edit
OSのバージョンとGLESの対応状況

GLESバージョンGLSLバージョン対応Android対応iOS
2.01.0Android 2.2以上iOS 3.0以上
3.03.0Android 4.3以上iOS 7.0以上
3.13.1Android 5.0以上無し

Edit
各バッファ機能の説明

GLESではOpenGLと違い、モダンな実装を強要される。これは限られたリソースを最大限に発揮させるための仕様であり、特にゲームなどの高いパフォーマンスが要求されるには有効である。そのモダンな実装の中でもバッファ管理はその中核となるものである。

種別バッファ名概要
頂点データ管理VAO(Vertex Array Object)VBOやIBOを取りまとめて管理するためのオブジェクト(コンテキスト)。狭義のバッファでは無いが、バッファを纏めて管理する事が出来るのでここに記載。他にもglVertexAttribPointerやglEnableVertexAttribArrayの状態を保存することができる。
VBO(Vertex buffer object)頂点データ群、法線データ群、頂点カラー群などの頂点に関するデータ配列を管理するバッファ
IBO(Index buffer object)頂点データを、具体的にどのような順番で利用するかを、VBOの頂点データの順番を index として配列にしたもの。IBOは設定しなくても、VBOの配列順であれば、描画を行うことは可能
シェーダー変数操作UBO(Uniform buffer object)GLES3.0から利用できるユニフォームブロックを操作するためのバッファ。大量のuniform変数があっても、gl関数1つで変数に値を設定できる
ピクセル領域FBO(Frame buffer object)

Edit
VAOの利用方法

VAOはES3.0から採用された、頂点情報を纏めて管理するためのオブジェクトであり、VAOを生成しバインドすることで、それ以後のVBOやIBOなど頂点情報の受け渡しに関するバインド処理を一括して処理することができるオブジェクトである。

Edit
VAOの作成からバインド

GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

基本的にはglGenVertexArraysで必要数(このサンプルでは1つ)のVAOを作成し、カレントVAOを、glBindVertexArrayを使って切り替える。これにより、この後にバインドされるVBO、IBOやVBOに利用する、glVertexAttribPointer、glEnableVertexAttribArrayなどの設定もカレントVAOにバインドされる。

Edit
VAOの切り替えとOFF

通常VAOを使うと、描画の際の頂点情報に関する設定切り替えがこのような簡単な記述になる。

glBindVertexArray (vao);   // 切り替え
glDrawElements (GL_TRIANGLE_STRIP, num_indices, GL_UNSIGNED_SHORT, 0);
glBindVertexArray (0);  // OFF

Edit
VAOにバインドするときの注意点

VAOに、VBOやIBO、vertexPointerなどを関連付けて、一括で処理するのが高速化や可読性にも繋がる手法だが、バインドとアンバインドのタイミングには注意が必要である。

glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo );
 <ここでVBOやglVertexAttribPointerの設定>
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo );
 <ここでIBO設定>
glBindVertexArray(null); // ここでVAOをunbind
 // 上の行のVAOのunbind後にVBO,IBOの unbind を実行
glBindBuffer(GL_ARRAY_BUFFER, null);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, null);

VAOをunbindする前に、IBOなどのバッファを  unbind すると「unbind した」(IBOは使わない)という情報が保管されてしまうためである。但し厳密にはVBOはVAOのunbind前に、unbindしても、glEnableVertexAttribArrayが、VAOに保管されている場合、VertexAttribPointerなどからVBOが参照されているため VAOから、unbindされない場合もある。ここは実装によって変化する可能性がある。

Edit
VAOの削除

void glDeleteVertexArrays(GLsizei n​, const GLuint *arrays​);

Edit
VBOの利用方法

ここでは、target に GL_ARRAY_BUFFERを指定しているが、glBindBuffer(この関数にかぎらず buffer 系の定数) の target には以下の定数が指定できる。(VBO以外でも利用する為)

定数概要
GL_ARRAY_BUFFERVertex attributes ここで利用したようにVAOを対象とする
GL_COPY_READ_BUFFERBuffer copy source
GL_COPY_WRITE_BUFFERBuffer copy destination
GL_ELEMENT_ARRAY_BUFFERVertex array indices
GL_PIXEL_PACK_BUFFERPixel read target
GL_PIXEL_UNPACK_BUFFERTexture data source
GL_TEXTURE_BUFFERTexture data buffer
GL_TRANSFORM_FEEDBACK_BUFFERTransform feedback buffer
GL_UNIFORM_BUFFERUniform block storage
GL_ATOMIC_COUNTER_BUFFERAtomic counter storage
GL_DISPATCH_INDIRECT_BUFFERIndirect compute dispatch commands
GL_DRAW_INDIRECT_BUFFERIndirect command arguments
GL_QUERY_BUFFERQuery result buffer
GL_SHADER_STORAGE_BUFFERRead-write storage for shaders

<GLの領域確保とデータの転送>

VBOにデータを設定する関数概要
void glBufferData (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage)target には、GL_ARRAY_BUFFERを指定。データ領域を size だけ確保し, そこに data で指定されたデータを転送する。usage はこの頂点バッファオブジェクトがどのような使われ方をするのかを指定。詳細は下の表。値はGPUが最適化するための参考にされる
usage概要
GL_STREAM_DRAW
GL_STREAM_READ
GL_STREAM_COPY
GL_STATIC_DRAW
GL_STATIC_READ
GL_STATIC_COPY
GL_DYNAMIC_DRAW
GL_DYNAMIC_READ
GL_DYNAMIC_COPY

例:

static const GLfloat position[][2] =
{
   { -0.5f, -0.5f },
   {  0.5f, -0.5f },
   {  0.5f,  0.5f },
   { -0.5f,  0.5f }
};
static const GLuint vertices = sizeof position / sizeof position[0];
glBufferData(GL_ARRAY_BUFFER, sizeof (GLfloat) * 2 * vertices, position, GL_STATIC_DRAW);

Edit
インターリーブ配列について

VBOの頂点情報では、通常 vertex shaderの処理単位が、1頂点単位であるために、1頂点データ単位の構造体の配列で保持される。この頂点毎の配列形式のことをインターリーブ配列と呼ぶ。これはPre T&Lキャッシュ(VBO と vertex shaderの間に挟まっている、頂点情報キャッシュメモリ)をより良く活用するための方法であり、わかり易さからも採用している事例が多い。

struct Vertex {
      float position[4];
      float normal[3];
      unsigned char color[4];
}

しかし最近ではVBOの数を増やすことで、頂点のデータを種類毎にそれぞれVBOに設定して利用する場合も多い。これはインターリーブ方式では、すべての頂点が同じ構造体でなければならず、オブジェクト(プリミティブ集合)によっては、利用されない場合もあり無駄が多くなるためである。(この場合、glVertexAttribDivisorなどの関数を活用する。主にinstancing用)

これらは、それぞれが長所・短所を持っているため、操作するオブジェクトによって、最適な方法を選択するべきである。

Edit
IBOの利用方法

IBOとは、Index Buffer Object の略であり、VBOで登録する頂点の順番を index として、どの頂点をどの順番で利用するかを指定する、VBOとセットで利用する機能である。特にIBOが有効なのは、GPU内にすでにある頂点情報を利用するため、キャッシュが有効になりVBOだけのような常にストリームで新頂点を読み込むよりも高速に動作する。

Edit
IBOの設定例

GLuint ibo;
glGenBuffers( 1, &ibo );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ibo );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, num*2, indices, GL_STATIC_DRAW );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );

基本的にはVBOと同じように、バッファオブジェクトを作成し、そこにインデックス配列を割り当てるという対応になる。

ELEMENT_ARRAY_BUFFER = Index Bufferを表す定数。

Edit
描画方法の変更

VBOだけのレンダリングには glDrawArrays メソッドを使うが、IBO を使って描画を行なうためには、glrawElements メソッドを利用する必要がある。

glDrawElements(
     GL_TRIANGLES,	// プリミティブ型の指定。GL_POINTSやGL_TRIANGLESなど
     length,		// index配列の数
     GL_SHORT,		// index配列の型
     0			// index配列のオフセット値
);

Edit
描画の具体例

glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, ibo);
glBindBuffer (GL_ARRAY_BUFFER, vbo);
glUseProgram (programID);
glDrawElements (GL_TRIANGLES, length, GL_SHORT, 0);
glBindBuffer (GL_ARRAY_BUFFER, 0);
glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0);

Edit
複数のインデックスの描画

glMultiDrawElementsを利用する。基本はglMultiDrawElementsの引数を配列で指定できるようにしただけの関数。

void glMultiDrawElements(
    GLenum mode,		// プリミティブ型
    const GLsizei * count,	// index配列の数、の配列
    GLenum type,		// 
    const GLvoid ** indices,
    GLsizei drawcount		// 上記配列群の個数
);

Edit
縮退ポリゴンを使った複数描画

縮退ポリゴンとは、主にES2.0までで利用されていた、glDraw関数を減らすための手法のひとつ。三角形の頂点のうち2つを同じ点にすることで、描画されない三角形を糊にして、頂点データ配列を接続する手法。しかし当然ながら、何も表示せずとも3つの頂点処理と一連の処理が実行されるため無駄が発生する。

Edit
縮退ポリゴンを使わないES3.0のプリミティブスタート

ES3.0からはプリミティブスタートという実装が追加された。利用時に、glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);とプリミティブスタートを有効にすることで、インデックスバッファの頂点番号配列に、-1 を挟むことで、縮退ポリゴンの時のように、複数のオブジェクト(プリミティブ)を連結して描画できる上に、縮退ポリゴンと違って、頂点処理などの1ポリゴン分の無駄を省くことが出来る。

short indices[] = { 1, 2, 3, 4, -1, 2, 3, 5 };

Edit
UBOの利用方法

UBO(Uniform Buffer Object)とは、毎フレーム毎に更新されるユニフォーム情報をブロックで管理することで、大量に毎フレーム毎に呼び出される、ユニフォーム設定関数を、1つに纏めることで、gl関数のオーバーヘッドを減らす手法であり、GLES3.0 から利用できる。

Edit
UBOの作り方

VBOなどと同じようにglGenBuffers 関数から作成し、glGetUniformBlockIndexで、uniformのブロックIDを取得し、glUniformBlockBindingで、利用できるように bind する。ここでの注意点は、uniform block は特殊な存在であり、いわゆる attribute などのシェーダー入力変数などで利用できる、layout location の番号とは別に管理されるため、uniform block には専用のブロックIDという番号で uniform block を識別する。

※uniform blockではない、uniform には GL4.5 から利用できる。(ESでは予定無し)参照

glGenBuffers (1,&ubo);

Edit
シェーダーとのデータ受け渡しについて

CPU側の処理であるOpenGLの各種データを、シェーダー側に受け渡すには、シェーダー index を取得し、その index に対して操作することでデータを設定できる。

Edit
シェーダー変数 indexの取得

OpenGLでは、通常のプログラムとは名称の印象が違うため、ここでいう index とは変数IDという概念で理解すると理解が容易いだろう。内部的には変数などが配列で管理されているために、このような名称(index や、locationなど)が用いられているようだ。

Edit
programリンカー前にindexを指定する方法

programのリンク前(glLinkProgram)に、プログラムに対してシェーダー内の変数名を元に index を割り当てる。リンク前に行うため融通性が低い。

void glBindAttribLocation(GLuint program, GLuint index, const GLchar *name);

Edit
リンカーが割り振ったindexを取得する方法

シェーダー変数の index は、programのリンク(glLinkProgram)によって割り振られるため、リンク後に下記関数に変数で参照して index を取得する。

GLint glGetAttribLocation (GLuint program, const GLchar *name);

Edit
シェーダー内でindexを指定する。

シェーダー内の変数定義で以下の様に指定する。

layout (location = 0) in vec4 vPosition;
layout (location = 1) in vec3 vNormal;
layout (location = 2) in vec3 vOffset;

これによって、indexを固定にできるため、上記の2つの関数を使うことなく index を活用できる。(location の意味はここでは indexと同義)当然 gl関数コールが減るため、実際のパフォーマンスが出やすい。

ちなみに、マルチレンダーターゲット用に out 変数でも同様に index を指定することが可能になっている。

layout (location = 0) out vec4 fNormal;
layout (location = 1) out vec4 fDiffuse;

Edit
Attributeとuniformの廃止

GLSL 3.0 以前におけるsheder 変数として、attribute(頂点用)や、uniform(汎用)などの変数の大雑把な修飾子が作られていたが、GL3.0からは attribute や uniform は基本廃止(一応残ってはいるが将来削除予定)され、in/out に統一された。(上記サンプル参照)そのため、glGetAttribLocation などの、Attrib文字が含まれる関数や、glGetUniformLocationなどのuniform変数用の関数の違いは意味を持たなくなった。

Edit
シェーダー変数indexを有効化する。

indexの取得方法にかかわらず、indexを利用する場合には、有効化させる必要がある。

void glEnableVertexAttribArray(	GLuint index);

Edit
シェーダー変数index無効化

通常、GL描画(glDrawArraysや、glDrawElements)の後には、利用済の index を開放する必要がある。

void glDisableVertexAttribArray(GLuint index);

Edit
シェーダー変数への値の設定

上記の関数で indexを取得し有効化させたあとに、glVertexAttribPointerなどを利用してシェーダー変数にデータを設定することが出来るようになる。

void glVertexAttribPointer(
	GLuint index,				// 上記で取得したシェーダー変数 index
	GLint size,				// 1 vertex の構成数 vec4 = 4, vec3 = 3 など
	GLenum type,				// 構成する値の型 GL_FLOAT など。
	GLboolean normalized,		// 正規化フラグ。GL_TRUEなら(-1.0,1.0)の範囲に正規化
	GLsizei stride,				// 次のデータへの移動数(sizeofなどで管理データ1つの大きさを指定)
	const GLvoid * pointer);		// データポインタ(1データが構造体の場合時のオフセット値。バイト数)

※stride(次のデータへの加算値)には、bufferに登録した時の1つの構造体のサイズなどが指定される。例えば(struct Vertex {GLfloat pos[2]; GLubyte rgba[4];};)のような、Vertex構造体であれば、sizeof(Vertex) など。実際の値は構造体のサイズである 12 が入る。

※データポインタには、bufferに登録するデータが複数ある場合のオフセット値を入れる。例えば、上記Vertex 構造体を利用する場合などであれば、 offsetof ( Vertex, rgba )等 。ちなみに関数の評価値である、実際の数字は8が入る。これは1つ目の変数のサイズが8バイトなので。(構造体1つの変数であるposの場合は値が必ず0になる)

Edit
GLの値の型(第3引数の部分)

基本型GL定義名概要
整数型GL_BYTE1バイト形式で記号有りの値(C言語の char型)
GL_UNSIGNED_BYTE1バイト形式で記号無しの値(C言語の unsigned char型)
GL_SHORT2バイト形式で記号有りの値(C言語の short型)
GL_UNSIGNED_SHORT2バイト形式で記号無しの値(C言語の unsigned short型)
GL_INT4バイト形式で記号有りの値(C言語の int型)
GL_UNSIGNED_INT4バイト形式で記号無しの値(C言語の unsigned int型)
小数点型GL_HALF_FLOAT2バイト形式の半精度浮動小数点型
GL_FLOAT4バイト形式の単精度浮動小数点型(C言語の float型)
GL_DOUBLE8バイト形式の倍精度浮動小数点型(C言語の double型)
GL_FIXED
GL_INT_2_10_10_10_REV
GL_UNSIGNED_INT_2_10_10_10_REV
GL_UNSIGNED_INT_10F_11F_11F_REV

Edit
フレームバッファ・レンダーバッファ等について

ピクセル面積に合わせたバッファ領域には、レンダーバッファというバッファ領域を作成することができる。このレンダーバッファには、3つの種類の「機能実体バッファ」を作成することができ、それら3つの「機能実体バッファ」を、1つに纏めて管理するのが、フレームバッファと呼ぶ。(機能実体バッファはOpenGLの用語ではないが概念がわかりやすいようにここではそう呼ぶ。またフレームバッファは実体(実データ領域)を持たずステータス情報とこれら実体情報へのアタッチ(結合)情報だけを持つ)

この3つの「機能実体バッファ」には、カラーバッファ、デプスバッファ、ステンシルバッファの3つがあり、カラーバッファとは、まさに1ピクセルの色が保存されるバッファであり、デプスバッファは対応ピクセルの深度を持つことで、ポリゴンの描画優先をピクセル単位処理できるようになるバッファであり、ステンシルバッファとは、日本語では型抜き染めの意味となる、いわゆる描画のマスクを管理するバッファである。

Edit
カラーバッファ。

レンダーバッファにとって、カラーバッファを作成することは基本ではあるが、実際のコーディングでは、レンダーバッファーによって作られる場合は少ない。これはレンダーバッファでは、特にWebGLなどでは選択できるカラー・タイプが少なく、その上、テクスチャーとして利用できない。よって、通常ではカラーバッファには、レンダーバッファでカラーバッファを作るよりも、テクスチャーでカラーバッファを作ってしまうケースが多いだろう。(これは基本的にレンダーバッファは、画面への表示バッファとしての役割が設定されているためだと思われる)

もちろん、最終描画としてのカラーバッファに対してはレンダーバッファを利用する。特にデバイスに必ず1つは準備されているフレームバッファにおけるカラーバッファ(実際の描画領域)には、レンダーバッファで作成されたものが利用されている。

Edit
レンダーバッファでの作成方法

<作成>

GLint rbo
glGenRenderbuffers (1, &rbo);      // この関数で rbo = renderID を作成する。
glBindRenderbuffer (GL_RENDERBUFFER, rbo);   // この関数で操作可能に

<GPU内にピクセル分の領域の確保>

glRenderbufferStorage (GL_RENDERBUFFER, GL_RGBA, 1024, 768); // 1024x768 Pixelのカラーバッファを作成する。

カラー指定の定数以外は、GL_DEPTH_COMPONENT や GL_STENCIL, GL_DEPTH_STENCIL などの他の種別のレンダーバッファの指定もここで行う。

<管理オブジェクトであるフレームバッファに接合>

GLuint fbo;
glGenFramebuffers (1,&fbo);    // FrameBufferの作成
glFramebufferRenderbuffer (GL_DRAW_FRAMEBUFFER, fbo, GL_RENDERBUFFER, rbo); // 結合

定数部分は特に変更する必要は無い。結合したあとはFBOを利用してレンダーバッファにアクセスできる。

Edit
テクスチャーバッファでの作成方法

カラーバッファの特別設定である、テクスチャーバッファではあるが、こちらの使いみちの方が関わりは深くなるだろう。

<作成>

GLuint tbo
glGenTextures (1, &tbo);
glBindTexture (GL_TEXTURE_2D, tbo); // GL_TEXTURE_2Dにはいろいろな種類がある。通常はこれ。

<GPU内にテクスチャー扱いでの領域確保> テクスチャーの種類によって、関数が異なる。

作成関数名概要
glTexImage1D1次元ピクセル(横1列)のテクスチャーを作成する
glTexImage2D2次元ピクセル(平面)のテクスチャーを作成する。通常テクスチャーといえば、この形式となる。これは平面のポリゴンに貼り付けるため。テクスチャーも平面となる。
glTexImage2DMultisampleアンチエイリアシングなどで利用するマルチサンプル形式のテクスチャー。マルチサンプルは基本的に面積4倍のテクスチャーを計算作成(カラーのサブピクセル化)して、アンチエイリアシングをするスーパーサンプリング手法と、深度情報だけをサブピクセル化させるマルチサンプリングの手法がある
glTexImage3D3次元ピクセル(立体のテクスチャー)を作成する。正確な環境ライティングなどに活用される
glTexImage3DMultisample3次元のマルチサンプル
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);

<フレームバッファへの結合>

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);

Edit
フレームバッファ

<作成>

glGenFramebuffers フレームバッファの固有名を作成
glBindFramebuffer 与えられた固有名をもつフレームバッファを作成

Edit
テクスチャーについて。

テクスチャーを操作するにあたり、サンプル程度のものであれば、関係がないがある程度のものを作成するには、texture unit という概念の性格な理解が必要となる。いわゆる glGenTextureを用いて作成する、テクスチャーオブジェクトの上限はメモリの許す限りであり、論理的上限であるが、シェーダーが同時に扱えるテクスチャーは GPUのハード情報である、GL_Spec で表示される、GL_MAX_TEXTURE_IMAGE_UNITS 数に依存する。

実際のGLソースにおいて、この重要である texture unit の番号は、自分で管理しなければならない。基本的にはglActiveTextureを用いて管理する。

このサイトが非常にわかりやすいので一読必須

Edit
Extention

ESは組み込みとさしている通り、ハードウェアとの関係が非常に深くなる。そのため、OpenGLESで定義されるExtentionは、GPUの種類などによって非常に豊富な物が提供され、メーカーやチップによっても大きな違いが発生する。その中でも時期OpenGLのコアAPIに採用できそうな基本Extentionを、ARB

Edit
基本Extention

ExtentionはARB コアAPIに追加される前の最終ステップであるARBエクステンションに策定

Edit
その他の情報

Edit
トラブルシューティング

Edit
glEnableVertexAttribArrayの使い方。

glEnableVertexAttribArray は描画の度に呼び出す必要はない。必然的に推測できると考えるが、作成したVertexArray毎に行えばよいものである。

Edit
メモ

Edit
並行投影()

static float g_orthogonalBase[16] = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
float* glslGetOrthoMatrix(float left, float right, float bottom, float top, float near_, float far_)
{
	g_orthogonalBase[0]  = 2.0f / (right - left);
	g_orthogonalBase[5]  = 2.0f / (top - bottom);
	g_orthogonalBase[10] = -2.0f / (far_ - near_);
	g_orthogonalBase[12] = -(right + left) / (right - left);
	g_orthogonalBase[13] = -(top + bottom) / (top - bottom);
	g_orthogonalBase[14] = -(far_ + near_) / (far_ - near_);
	return g_orthogonalBase;
}