D3D Shader/OpenGL」カテゴリーアーカイブ

OpenGL ES 3.0/OpenGL 4.4 Texture Object と Sampler Object

Buffer と同じように Texture を扱う場合も Bind 操作が必要です。
Texture Object の Bind は二つの意味に用いられます。

 1. Texture Object を操作する場合
 2. 描画で用いる Texture Image Unit に割り当てる場合

Texture Object の種類(タイプ)は下記の通り。

                                 ES2 ES3 GL30 GL31 GL32 GL4
------------------------------------------------------------
GL_TEXTURE_1D                     -   -   ◎   ◎   ◎   ◎
GL_TEXTURE_2D                     ◎  ◎  ◎   ◎   ◎   ◎
GL_TEXTURE_CUBE_MAP               ◎  ◎  ◎   ◎   ◎   ◎
GL_TEXTURE_3D                     -   ◎  ◎   ◎   ◎   ◎
GL_TEXTURE_1D_ARRAY               -   -   ◎   ◎   ◎   ◎
GL_TEXTURE_2D_ARRAY               -   ◎  ◎   ◎   ◎   ◎
GL_TEXTURE_2D_MULTISAMPLE         -   -   -    -    ◎   ◎
GL_TEXTURE_2D_MULTISAMPLE_ARRAY   -   -   -    -    ◎   ◎
GL_TEXTURE_CUBE_MAP_ARRAY         -   -   -    -    -    ◎
GL_TEXTURE_RECTANGLE              -   -   -    ◎   ◎   ◎
GL_TEXTURE_BUFFER                 -   -   -    ◎   ◎   ◎

glBindBuffer() と同じように glBindTexture() にタイプを指定します。
タイプの数だけ Bind 状態が保持されます。

● 1. Texture Object を操作する場合

GLuint tex_obj1= 0;
GLuint tex_obj2= 0;

glGenTextures( 1, &tex_obj1 );
glGenTextures( 2, &tex_obj2 );

glBindTexture( GL_TEXTURE_2D, tex_obj1 );
glBindTexture( GL_TEXTURE_3D, tex_obj2 );

glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );

glBindTexture( GL_TEXTURE_2D, 0 );
glBindTexture( GL_TEXTURE_3D, 0 );

異なるタイプの Texture Object は同時に Bind できます。
それぞれ glTexParameteri() や glTexImage 等の命令を実行することが可能です。

● 2. 描画で用いる Texture Image Unit に割り当てる場合

描画時にシェーダーが参照する Texture も Bind で渡します。

シェーダーは一度に複数のテクスチャにアクセスできます。
まずは割り当てたい Texture Unit (Texture Image Unit) の番号を
先に指定しておきます。

glActiveTexture( GL_TEXTURE0 ); // Texture Image Unit 0
glBindTexture( GL_TEXTURE_2D, texture_object1 );

glActiveTexture( GL_TEXTURE1 ); // Texture Image Unit 1
glBindTexture( GL_TEXTURE_2D, texture_object2 );

仮にアクセスできる Unit が 8個あるなら、glActiveTexture() の指定も
GL_TEXTURE0 ~ GL_TEXTURE7 の範囲になります。
シェーダー側では Sampler (Sampler2D 等) に設定した glUniform1i() の値で
これらのテクスチャを区別するわけです。

glActiveTexture() の動作を調べてみると、現在の Bind 状態がごっそりと
入れ替わっていることがわかります。

// (1)
glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, tex_obj1 );
glBindTexture( GL_TEXTURE_CUBE_MAP, tex_obj2 );

glActiveTexture( GL_TEXTURE1 );
glBindTexture( GL_TEXTURE_2D, tex_obj1 );
glBindTexture( GL_TEXTURE_3D, tex_obj3 );

glActiveTexture( GL_TEXTURE3 );
glBindTexture( GL_TEXTURE_3D, tex_obj4 );

例えば OpenGL ES 3.0 で Total (Combined) の Unit が 32個ある場合、
GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP,
GL_TEXTURE_2D_ARRAY の 4種類のバインド状態が
32個 (4 x 32 = 128) まで保持されることになります。
(1) の実行結果をまとめると下記の表の通り。

      glActiveTexture= 0     1     2     3     4     5     6  ... 31
---------------------------------------------------------------------
GL_TEXTURE_2D         obj1  obj1   --    --    --    --    --     --
GL_TEXTURE_CUBE_MAP   obj2   --    --    --    --    --    --     --
GL_TEXTURE_3D          --   obj3   --   obj4   --    --    --     --
GL_TEXTURE_2D_ARRAY    --    --    --    --    --    --    --     --

ただし、実際の描画で Shader が参照できる Texture Object は
各 Unit 1つにつき 1つだけです。

例えば上の状態でシェーダー内の uniform Sampler2D と SamplerCube の両方が、
Unit 0 ( glActiveTexture( GL_TEXTURE0 ) ) の obj1 と obj2 を
それぞれ参照することはできません。
同じ Unit を参照している場合 glValidateProgram() が失敗します。

まとめると、
1. の用途では同時に複数の Texture Object を Bind することがありますが、
2. の用途では、現在の ActiveTexture (Texture Image Unit) に対して複数
Texture を Bind することはありません。

Bind は複数の用途に用いられるので注意が必要です。
2. の用途で Bind している間に、画像サイズを調べようとして 1. の
つもりで Bind してしまうと状態を破壊してしまうことになります。

● Texture Image Unit

GPU には複数の Image Unit が搭載されています。
シェーダーは Unit の数だけ、同時に異なるテクスチャから画像を
読み込むことができます。

各 Unit には Sampler と Texture Object の二つの状態を割り当てます。

 ・Sampler : データの読み込み方法
 ・Texture Object : データそのもの

例えば Fragment Shader (PixelShader) の Texture Image Unit 数
(GL_MAX_TEXTURE_IMAGE_UNITS) が 16個なら、FragmentShader は同時に 16種類の
異なるテクスチャマップにアクセスできます。

uv を変更して同じテクスチャを何度も読み込む場合は特に回数制限はありません。
ShaderModel 2.0 (D3D9) 以降は Sampler と Texture の Load 命令の実行が
分離されているからです。(ShaderModel 1.x までは同一でした)

最小 Unit 数
                 vsh   fsh   gsh   tcsh  tesh  csh  total
----------------------------------------------------------
OpenGL   2.0      0     2     -     -     -     -     2
OpenGL   2.1      0     2     -     -     -     -     2
OpenGLES 2.0      0     8     -     -     -     -     8
OpenGL   3.0     16    16     -     -     -     -    16
OpenGLES 3.0     16    16     -     -     -     -    32
OpenGL   3.1     16    16     -     -     -     -    32
OpenGL   3.2     16    16    16     -     -     -    48
OpenGL   3.3     16    16    16     -     -     -    48
OpenGL   4.0     16    16    16    16    16     -    80
OpenGL   4.1     16    16    16    16    16     -    80
OpenGL   4.2     16    16    16    16    16     -    80
OpenGL   4.3     16    16    16    16    16    16    96
OpenGL   4.4     16    16    16    16    16    16    96
----------------------------------------------------------
・total = GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS

少なくても上記個数は使用可能となっています。
ただ実際に調べたところ、GPU によっては GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
(total) が必ずしも上記表の最低個数を満たしているとは限らないようです。

                         OpenGL     v/ f/ g/tc/te/csh    total
------------------------------------------------------------
Adreno 320(Android4.1)   ES 2.0     4/16/--/--/--/--    20
Mali-T604 (Android4.3)   ES 3.0    16/16/--/--/--/--    32
Intel HD 4000 x86           4.0    16/16/16/16/16/--    80
RADEON HD 6750M x64         4.2    16/16/16/16/16/--    32 *
GeForce GTX 650 x64         4.4    32/32/32/32/32/32   192

描画に使うテクスチャは、glDrawElements() 等の描画命令発行時に Bind された
状態になります。
Fragment Shader だけでなく、Vertex, Geometry 等の各シェーダーがそれぞれ
異なる Texture にアクセスすることが可能です。

例えば vsh, fsh, gsh が 16種類のすべて異なるテクスチャを参照する場合は
48個の Bind 状態が必要になります。

glActiveTexture() に指定する GL_TEXTRE0~ のシンボルは OpenGL 4.4 の
ヘッダを見ても GL_TEXTRE0 ~ GL_TEXTRE31 の 32個しか定義されていません。

OpenGL では GL_TEXTRE0 のオフセット指定が有効だと明記されているので、
32以上も下記の方法でアクセスすることが出来ます。

glActiveTexture( GL_TEXTURE0 + 32 );
...
glActiveTexture( GL_TEXTURE0 + 47 );

ちなみに OpenGL 4.2 (GLSL 4.2) 以降は Shader 内でも直接 Texture Image Unit
の番号を設定できるようになっています。

// GLSL
layout(binding=1) uniform sampler2D    ColorMap;
layout(binding=2) uniform sampler2D    NormalMap;
layout(binding=0) uniform samplerCube  ReflectionMap;

layout の binding は、今まで外部から glUniform1i() で与えていた番号に相当します。

● Sampler Object

Texture の Wrap や Filter mode 等の Sampler State は、Direct3D の場合は
Texture Stage (Sampler) 側の設定値でした。
OpenGL ES 2.0 の場合は Texture Object がこれらのステートを所有します。

例えば下記のように同じオブジェクトを 0,1 の Unit に割り当てます。

// OpenGL ES 2.0
glBindTexture( GL_TEXTURE_2D, tex_obj1 );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );

glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, tex_obj1 );

glActiveTexture( GL_TEXTURE1 );
glBindTexture( GL_TEXTURE_2D, tex_obj1 );

// -- (2)
glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, tex_obj1 );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

(2) で Unit 0 にバインドされたテクスチャの、Filter mode を変更すると、
Unit 1 の設定値も GL_LINEAR に書き換わります。

OpenGL ES 3.0/OpenGL 3.0 以降は Sampler Object が導入され、D3D のように
Image Unit に直接これらのステートを設定できるようになりました。

各パラメータは Sampler Object 優先です。
Image Unit に Sampler Object が設定されていない場合のみ
Texture Object の値が用いられます。

GLuint sampler_obj= 0;
glGenSamplers( 1, &sampler_obj );
glSamplerParameteri( sampler_obj, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glSamplerParameteri( sampler_obj, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

~
glBindSampler( 0, sampler_obj );

Sampler API は、パラメータの設定時は glActiveTexture() の影響を受けません。
また GL_TEXTURE0 ~ ではなく、直接 Unit 番号 0~ を指定しています。

Texture Object と違い、Object 操作のための Bind (1. 相当) が不要です。
Bind するのは実際に Image Unit に割り当てる場合だけ (2. 相当) なので、
わかりやすくてミスしづらい構造となっています。

OpenGL 4.4 ではさらに、複数の Sampler Object をまとめて Bind できる
glBindSamplers() 命令が追加されました。
これは Direct3D 10/11 の SetSamplers() 系命令によく似ています。

GL_SAMPLER_BINDING を用いて現在の Bind 状態を参照する場合は
glActiveTexture() も影響しています。

glActiveTexture( GL_TEXTURE0 + 0 );
GLint sampler= 0;
glGetIntegerv( GL_SAMPLER_BINDING, &sampler );

この値は glActiveTexture() で切り替わるのですが、RADEON だけ
値が取れませんでした。

Mali-T604         ES 3.0   取れる
Intel HD 4000        4.0   取れる
RADEON HD 6750M      4.2   取れない (追記 driver 更新で正常動作を確認)
GeForce GTX 650      4.4   取れる

2013/08/11 追記: RADEON HD 6750M でも Catalyst 13.8(beta) OpenGL 4.3 で正しく状態を取れることを確認しました。

関連エントリ
OpenGL ES 3.0 / OpenGL 4.3 VertexArrayObject と VertexAttribBinding

OpenGL ES 3.0 / OpenGL 4.3 VertexArrayObject と VertexAttribBinding

OpenGL API のオブジェクト操作は、必ずライブラリ内の global な変数を
経由して行います。
例えば Buffer Size を調べる場合も、現在の context のステートに
オブジェクトを bind してから対応するメソッドを呼び出します。

// GL2
glBindBuffer( GL_ARRAY_BUFFER, vertex_object );
GLint	param[1];
glGetBufferParameteriv( GL_ARRAY_BUFFER, GL_BUFFER_SIZE, param );
glBindBuffer( GL_ARRAY_BUFFER, 0 );

オブジェクトが導入される前の API と互換性を保つことができる反面、
どのオブジェクトを対象としているのかコードを見ただけではわからなく
なっています。

どのオブジェクトが必要なのか、どこまで影響を与えるのかは、それぞれ
命令仕様をマニュアル等で確認する必要があります。

例えば OpenGL ES 2.0 の描画のコードは下記の通りです。

// GL2 -- (1)
glUseProgram( program );
glUniform4fv( location, 4, matrix );
glBindBuffer( GL_ARRAY_BUFFER, vertex_object );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, index_object );
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 24, (void*)0 );
glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, 24, (void*)12 );
glEnableVertexAttribArray( 0 );
glEnableVertexAttribArray( 1 );
glDrawElements( GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0 );

もし仮に D3D API のような書き方ができるとしたらこんな↓感じになるでしょうか。

// GL2 -- 擬似コード (2)
program->SetConstant( location, 4, matrix );
device_context->SetProgram( program );
device_context->SetIndexBuffer( index_object );
device_context->SetVertexAttrib( 0, 3, GL_FLOAT, GL_FALSE, 24,  0, vertex_object);
device_context->SetVertexAttrib( 1, 3, GL_FLOAT, GL_FALSE, 24, 12, vertex_object);
device_context->DrawIndexed( GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0 );

「擬似コード (2)」を見ると device_context に SetVertexBuffer() 命令が無く、
SetVertexAttrib() の方に vertex_object を渡していることがわかるかと思います。

実際に (1) の glDrawElements() は glBindBuffer( GL_ARRAY_BUFFER ) を
見ておらず、直前に glBindBuffer( GL_ARRAY_BUFFER, 0 ) があっても動作します。

glBindBuffer( GL_ARRAY_BUFFER ) を必要とするのは glVertexAttribPointer()
の方で、各 Vertex Attribute が頂点バッファの情報を保持しています。
Attribute それぞれが異なる Vertex Buffer を参照している可能性があるからです。

やはり (1) のコードを見ただけではこのような内部構造がわからないので、
OpenGL 命令の仕様はきちんと確認した方が良いようです。

● Vertex Array Object

頂点のバインドは複雑で情報も多いので、OpenGL 3.x 以降や OpenGL ES 3.0 では
Vertex Array Object (VAO) が導入されています。

// GL3 -- Vertex Array Object の作成 (3)
GLuint input_layout= 0;
glGenVertexArrays( 1, &input_layout );

glBindVertexArray( input_layout );
glBindBuffer( GL_ARRAY_BUFFER, vertex_object );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, index_object );
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 24, (void*)0 );
glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, 24, (void*)12 );
glEnableVertexAttribArray( 0 );
glEnableVertexAttribArray( 1 );
glBindVertexArray( 0 );

VAO は頂点 Attribute の情報を保存し、描画時に利用することができます。

// GL3 -- VAO を使った Rendering (4)
glUseProgram( program );
glUniform4fv( location, 4, matrix );
glBindVertexArray( input_layout );
glDrawElements( GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0 );

OpenGL 3.x (core profile) 以降は VAO が必須で、glBindVertexArray() が無いと
glVertexAttribPointer() がエラーになります。

つまり glVertexAttribPointer() は GL2 までは device_context のメソッドでしたが、
GL3 からは Vertex Array Object のメソッドに相当します。
擬似コードで表現してみます。

// GL3 -- VAO 作成 擬似コード (5)
IInputLayout* input_layout= device->CreateInputLayout( 2 );
input_layout->SetIndexBuffer( index_object );
input_layout->SetVertexAttrib( 0, 3, GL_FLOAT, GL_FALSE, 24,  0, vertex_object );
input_layout->SetVertexAttrib( 1, 3, GL_FLOAT, GL_FALSE, 24, 12, vertex_object );
// GL3 -- VAO を使った Rendering 擬似コード (6)
program->SetConstant( location, 4, matrix );
device_context->SetProgram( program );
device_context->SetInputLayout( input_layout );
device_context->DrawIndexed( GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0 );

OpenGL ES 3.0 では OpenGL ES 2.0 互換性のために VAO 無しでも
glVertexAttribPointer() が使えるようになっています。
bind == 0 時にデフォルトの VAO が割り当てられていると考えられます。
OpenGL 3.x でも、RADEON など一部 GPU では default VAO が有効なものが
あるようです。

Vertex Array Object は Direct3D の InputLayout や VertexDeclaration に
相当しますが、上記のように vertex_object や index_object が含まれている点で
異なっています。
D3D では頂点のバインド情報とバッファの割り当ては別の命令でした。
OpenGL でも 4.3 で D3D 同様の仕組みが導入されているようです。
(後述: Vertex Attrib Binding)

● GL_ELEMENT_ARRAY_BUFFER の扱い

VAO の index_object に対する挙動は vertex_object の場合とは異なっています。

glDrawElements() は glBindBuffer( GL_ARRAY_BUFFER ) を参照しないし
VAO も glBindBuffer( GL_ARRAY_BUFFER ) に影響を与えません。

ですが、glDrawElements() は glBindBuffer( GL_ELEMENT_ARRAY_BUFFER ) を
参照し、VAO は glBindBuffer( GL_ELEMENT_ARRAY_BUFFER ) を置き換えます。

よって直前で glBindBuffer( GL_ELEMENT_ARRAY_BUFFER ) に 0 が
書き込まれると glDrawElements() は失敗します。

GLuint  input_layout;
GLuint  vertex_object1;
GLuint  index_object1;

// ** Bind: Vertex=[0]  Index=[0]

glBindVertexArray( input_layout );
glBindBuffer( GL_ARRAY_BUFFER, vertex_object1 );

// ↓ ここでの bind は VAO input_layout に対して行う
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, index_object1 );

// ** Bind: Vertex=[vertex_object1]  Index=[index_object1]

glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 12, 0 );
glEnableVertexAttribArray( 0 );

glBindVertexArray( 0 );

// ↑VAO の bind を解除したので index_object1 のバインドも消える↓

// ** Bind: Vertex=[vertex_object1]  Index=[0]

// VAO の変更によって GL_ELEMENT_ARRAY_BUFFER (index) の bind は
// 元に戻るが、GL_ARRAY_BUFFER (vertex) には影響がでない。

同じ glBindBuffer() 命令でも動作が異なっていることがわかるかと思います。

GL_ELEMENT_ARRAY_BUFFER のバインド情報
 ・VAO が 0 の時は Default の Bind 情報が保持される。
 ・VAO が割り当てられている場合は VAO に格納する。

例えば下記 (7) のようなコードがあった場合、(A) は描画やオブジェクトに影響を
与えませんが (B) は VAO (input_layout) の内容を置き換えています。

// GL3 -- (7)
glUseProgram( program );
glUniform4fv( location, 4, matrix );
glBindVertexArray( input_layout );

glBindBuffer( GL_ARRAY_BUFFER, vertex_object );        // -- (A)
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, index_object ); // -- (B)

glDrawElements( GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0 );

glBindVertexArray( 0 );

● Vertex Attribute Binding

(7) にあるように、描画時の (A) glBindBuffer( GL_ARRAY_BUFFER ) は直接
影響を与えません。

もし描画に使用する頂点バッファを置き換えたい場合は、Attribute 毎に
glVertexAttribPointer() を呼び直すことになります。
glVertexAttribPointer() に渡す TYPE などの情報が必要になりますし、
同じバッファを見ている Attribute の数だけ命令を実行しなければなりません。

OpenGL 4.3 では Vertex Buffer と Vertex Attribute を分けて管理できる
仕組みが追加されています。

glVertexAttribBinding( attrib_index, bind_index );
glBindVertexBuffer( bind_index, buffer_object, offset, stride );
glVertexAttribFormat( attrib_index, size, type, normalized, offset );

各 Attribute の頂点フォーマットは、これまでの
glVertexAttribPointer() 同様に glVertexAttribFormat() で定義します。

ただし各 Attribute が参照するバッファの情報は別で、bind_index を用いた
間接参照となります。
bind_index が指しているのは VertexBuffer の情報が入ったテーブルです。
実際のバッファの情報はこの VertexBuffer のテーブルの方に格納されます。

◎ GL3.x/4.x
・頂点 Attribute が持つ情報
    Type, Size, Offset, NormalizeFlag, VertexBuffer, Stride


◎ GL4.3/4.4 VertexAttribBinding
・頂点 Attribute が持つ情報
    Type, Size, Offset, NormalizeFlag, BindIndex (BindVertexBuffer を参照する)

・BindVertexBuffer のテーブルが持つ情報
    VertexBuffer, Stride

bind_index を通して、Attribute 毎に個別に持っていたバッファ情報を共有する
ことができます。

bind_index の値は glGetVertexAttribiv( GL_VERTEX_ATTRIB_BINDING ) で確認
することができます。
また実装上は Vertex Attribute の Table と Vertex Buffer の Table は
同一のもので、bind_index は自分自身への 2段階間接参照であることもわかります。

// GL3 --- (8)
GLuint input_layout= 0;

glGenVertexArrays( 1, &input_layout );
glBindVertexArray( input_layout );

glBindBuffer( GL_ARRAY_BUFFER, vertex_object );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, index_object );

glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 24, (void*)0 );
glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, 24, (void*)12 );

glEnableVertexAttribArray( 0 );
glEnableVertexAttribArray( 1 );

glBindVertexArray( 0 );

(8) を VertexAttribBinding を使って置き換えると下記の通り。

// GL4.3/4.4 --- (9)
GLuint input_layout= 0;

glGenVertexArrays( 1, &input_layout );
glBindVertexArray( input_layout );

glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, index_object );

glBindVertexBuffer( 0, vertex_object, 0, 24 );
glVertexAttribBinding( 0, 0 );
glVertexAttribBinding( 1, 0 );

glVertexAttribFormat( 0, 3, GL_FLOAT, GL_FALSE,  0 );
glVertexAttribFormat( 1, 3, GL_FLOAT, GL_FALSE, 12 );

glEnableVertexAttribArray( 0 );
glEnableVertexAttribArray( 1 );

glBindVertexArray( 0 );

VertexAttribBinding を使うと、下記のように glBindVertexBuffer() 一つで
頂点が参照する Vertex Buffer を置き換えることができます。

// GL4.3/4.4 -- (10)
glBindVertexArray( input_layout );
glBindVertexBuffer( 0, vertex_object2, 0, 64 );
glBindVertexArray( 0 );

試してみると glBindVertexBuffer() は glBindBuffer( GL_ARRAY_BUFFER )
を経由しないし全く変更もしないことがわかります。
これで描画に glBindBuffer( GL_ARRAY_BUFFER ) は必要なくなりました。

関連エントリ
OpenGL ES 3.0 と Vertex Array Object

OpenGL ES 3.0 と Vertex Array Object

OpenGL ES 3.0 は OpenGL 3.x に相当します。
DirectX でいえば Direct3D 10 相当で、この時期に API も GPU 機能も大きな
仕様変更がありました。

Direct3D 11 は今でこそ Mobile 向けの用途もあって、Direct3D 9 相当の GPU
でも使えるよう API が拡張されています。
ですが Vista と共にリリースされた Direct3D 10.0 は GPU も API も
下位互換性が無く D3D10 対応 GPU 以外では使えませんでした。

GPU 年表

Direct3D 10 から少々遅れて OpenGL 3.x でも大きな変更が入っています。
Direct3D ほど極端ではありませんが、徐々にレガシー機能を排除して API の
古い仕様が置き換えられていきました。
従来のアプリは互換性用の Compatible Profile を選択することで対応可能と
なっています。

両者ともに Desktop 向け GPU では互換性より新機能を重視していたのですが、
その後 Mobile 向けの用途が広がったことで方向性が変わってきたようです。
Direct3D 11 では制限付きながら FeatureLevel で下位互換性が復活しています。

OpenGL ES 3.0 では今回、OpenGL 3.0 で捨てたはずの互換性が維持されたままの
上位互換となっています。
そのため OpenGL 2.x (GLES 2.0) 世代の命令が OpenGL 3.0 ではエラーに
なるが、OpenGL ES 3.0 ではエラーにならないことがあるようです。

その一つが Vertex Array Object (VAO) です。
OpenGL 3.0 では VAO を Bind していない (default object == 0) 場合の
glVertexAttributePointer() がエラーに
なりますが OpenGL ES 3.0 では OpenGL ES 2.0 と同じように通ります。

OpenGL でも GPU の Driver によっては Core Profile でもレガシー API を
混在できるものがあるので、エラー判定の範囲が違うだけなのかもしれません。

0 の時に default object が割り当てられるかどうかだけだと思うのですが、
きちんと把握していなかったのでこの辺りの挙動はもう少し詳しく調べたいと
思っています。

Android 4.3 Android NDK r9

Android NDK r9 がリリースされています。
Android 4.3 (API Level 18) の OpenGL ES 3.0 が使えるようになりました。

toolchain も更新されており、少々問題がありました。
C++11 を有効にしている場合 (-std=c++11) エラーが出るようです。

android-ndk-r9/platforms/android-18/arch-arm/usr/include/sys/cdefs_elf.h:35:28:
error: invalid suffix on literal; C++11 requires a space between literal
and identifier [-Werror=literal-suffix]
 #define _C_LABEL_STRING(x) "_"x
                            ^

cdefs_elf.h の _C_LABEL_STRING の定義中 “_” と x の間にスペースを入れると
回避出来ます。

 #define _C_LABEL_STRING(x) "_" x

cdefs_elf.h は下記 3箇所にあります。

android-ndk-r9/platforms/android-18/arch-arm/usr/include/sys
android-ndk-r9/platforms/android-18/arch-mips/usr/include/sys
android-ndk-r9/platforms/android-18/arch-x86/usr/include/sys

関連エントリ
Android 4.3 と OpenGL ES 3.0

Android 4.3 と OpenGL ES 3.0

Android 4.3 がリリースされ OpenGL ES 3.0 対応になりました。
OpenGL ES 3.0 は OpenGL 3.x 世代に対応する API セットで、
DirectX では Direct3D 10 に相当します。

GeometryShader はないものの、ES 2.0 世代ではオプションだった多くの
項目が標準となり、PC 向け GPU と比べて機能差が無くなりつつあります。
また D3D10 (ShaderModel 4) 世代の大きな特徴として、データフォーマットの
拡大や GPU リソースの汎用化があげられます。
OpenGL ES 3.0 の登場は、描画以外の GPU 活用につながる
第一歩といえるかもしれません。

実際に Nexus 10 (Android 4.3) で試してみました。

GL_VERSION: OpenGL ES 3.0
GL_RENDERER: Mali-T604
GL_VENDOR: ARM
GL_SHADING_LANGUAGE_VERSION: OpenGL ES GLSL ES 3.00

API=300 Shader=300 (VConst=256 PConst=1024)
pconst=1024 vconst=256 vin=16 vout=15 ptex=16 vtex=16 combotex=32 maxrender=4096 maxtexsize=4096 cubetexsize=4096 viewdims=4096

Extension:
GL_EXT_debug_marker
GL_ARM_rgba8
GL_ARM_mali_shader_binary
GL_OES_depth24
GL_OES_depth_texture
GL_OES_depth_texture_cube_map
GL_OES_packed_depth_stencil
GL_OES_rgb8_rgba8
GL_EXT_read_format_bgra
GL_OES_compressed_paletted_texture
GL_OES_compressed_ETC1_RGB8_texture
GL_OES_standard_derivatives
GL_OES_EGL_image
GL_OES_EGL_image_external
GL_OES_EGL_sync
GL_OES_texture_npot
GL_OES_vertex_half_float
GL_OES_required_internalformat
GL_OES_vertex_array_object
GL_OES_mapbuffer
GL_EXT_texture_format_BGRA8888
GL_EXT_texture_rg
GL_EXT_texture_type_2_10_10_10_REV
GL_OES_fbo_render_mipmap
GL_OES_element_index_uint
GL_EXT_shadow_samplers
GL_KHR_debug
GL_EXT_occlusion_query_boolean
GL_EXT_blend_minmax
GL_EXT_discard_framebuffer
GL_OES_get_program_binary
GL_OES_texture_3D
GL_EXT_texture_storage
GL_EXT_multisampled_render_to_texture
GL_OES_surfaceless_context
GL_ARM_mali_program_binary

Precision:
 0: [15 15] 10
 1: [15 15] 10
 2: [127 127] 23
 3: [15 14] 0
 4: [15 14] 0
 5: [31 30] 0
 6: [15 15] 10
 7: [15 15] 10
 8: [127 127] 23
 9: [15 14] 0
10: [15 14] 0
11: [31 30] 0

TextureFormat
00=8b90  GL_PALETTE4_RGB8_OES
01=8b91  GL_PALETTE4_RGBA8_OES
02=8b92  GL_PALETTE4_R5_G6_B5_OES
03=8b93  GL_PALETTE4_RGBA4_OES
04=8b94  GL_PALETTE4_RGB5_A1_OES
05=8b95  GL_PALETTE8_RGB8_OES
06=8b96  GL_PALETTE8_RGBA8_OES
07=8b97  GL_PALETTE8_R5_G6_B5_OES
08=8b98  GL_PALETTE8_RGBA4_OES
09=8b99  GL_PALETTE8_RGB5_A1_OES
10=8d64  GL_ETC1_RGB8_OES
11=9274  GL_COMPRESSED_RGB8_ETC2
12=9275  GL_COMPRESSED_SRGB8_ETC2
13=9278  GL_COMPRESSED_RGBA8_ETC2_EAC
14=9279  GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
15=9276  GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
16=9276  GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
17=9270  GL_COMPRESSED_R11_EAC
18=9272  GL_COMPRESSED_RG11_EAC
19=9271  GL_COMPRESSED_SIGNED_R11_EAC
20=9273  GL_COMPRESSED_SIGNED_RG11_EAC

新しい Texture format ETC2/EAC が使えるようになっています。
ASTC はありませんでした。
core 機能が大幅に増えているため Extension 自体は控えめです。
下記ページで ES 2.0 と比べることができます。

CPU/GPU OpenGL ES Extension (Mobile GPU)

Android NDK が更新されていないので今のところ Java API のみとなっているようです。
OpenGL ES 3.0 は OpenGL ES 2.0 と互換性があるので 3.0 の context 上でも
ES 2.0 の NDK アプリケーションがそのまま動作しました。

API に互換性はあるものの、GLSL ES 1.0 と GLSL ES 3.0 では shader の書式が
異なっています。
OpenGL ES 2.0 (GLSL ES 1.0) 用であることを明確に宣言するには shader の
先頭に “#version 100” を追加しておきます。

同様に Nexus 7 にも Android 4.3 を入れてみましたが、
Tegra3 なのでやはり OpenGL ES 3.0 は動きませんでした。

おそらく現時点入手で可能な端末に使われていて OpenGL ES 3.0 対応と思われる
GPU は下記の通りです。

・Snapdragon S4 Pro APQ8064 Adreno 320
・Snapdragon 600 APQ8064T Adreno 320
・Exynos 5 Dual (5250) ARM Mali-T604

関連エントリ
VIDIA Tegra4 の OpenGL ES 2.0 Extension
OpenGL ES 3.0 / OpenGL 4.3 ASTC 圧縮テクスチャの比較
OpenGL 4.3/GLES 3.0 次の圧縮テクスチャ ASTC
OpenGL ES 3.0 / OpenGL 4.3 ETC2 テクスチャ圧縮の比較
OpenGL ES 3.0 と Shader Model の関係、まとめ wiki の更新
OpenGL ES 3.0 と OpenGL ES 2.0 の互換性
OpenGL 4.3/ES 3.0 ETC2 Texture 圧縮の仕組み (PVRTC2,ASTC)
OpenGL ES 2.0/3.0 Emulator
OpenGL 4.3 と GL_ARB_ES3_compatibility