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

iOS7 と iPhone 5s の sRGB 対応とテクスチャフォーマット

iPhone 5s が発売されて OpenGL ES 3.0 対応端末が増えました。
OpenGL ES 3.0 に対応している入手可能な端末としては 3 種類目の GPU になります。

・Nexus 10 ( Android 4.3 + Mali-T604 )
・Nexus 7(2013)/Nexus 4 ( Android 4.3 + Adreno 320 )
・iPhone 5s ( iOS 7 + Apple A7 GPU )

Nexus 10 用に作成していた OpenGL ES 3.0 の描画コードも
iPhone 5s であっさりと動作しました。
やはり Adreno 320 にはまだ少々問題があるように思います。

● sRGB

OpenGL ES 3.0 を利用できるのは Apple A7 を搭載した iPhone 5s だけですが、
iOS 7.0 に更新することで従来の端末でも機能拡張が行われているようです。
その一つが前回の記事で触れている sRGB 対応です。

iPhone 5s の OpenGL ES 3.0 で sRGB を扱えるのは当然ですが、
iPad 4 や iPhone 5 など PowerVR SGX554MP/543MP でも extension で
同等の相互変換がサポートされました。(下記ページも更新)

OpenGL ES Extension (Mobile GPU)

例えば PVRTC でも GL_EXT_pvrtc_sRGB によって sRGB からリニアへの変換が
行われるようになっています。

・GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT
・GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT
・GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT
・GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT

前回の表↓を更新しました。

          OpenGL ES 3.0 での sRGB 対応
-----------------------------------------
ETC1         あり(ETC2)
ETC2         あり
PVRTC  (v1)  あり         (PowerVR のみ)
PVRTC2 (v2)  あり         (PowerVR のみ)
ATITC        無し         (Adreno のみ)
ASTC         あり
S3TC(DXT1)   あり

iOS が対応しているフォーマットは PVRTC (v1) だけで PVRTC2 (v2) は
含まれていないようです。
またフレームバッファに対するリニアからの変換 (GL_EXT_sRGB) も
サポートしています。

iOS はもともと Renderbuffer を直接作っていたので、EGL/WGL のような
機能選択が不要です。
さらに GLK (GLKit) なら 1行変えるだけで対応できてしまい、
Android での苦労が嘘のように簡単でした。

PowerVR SGX535 (iPhone4) は未確認ですが、SGX543MP/554MP では
iOS 7.0 で Apple A7 GPU と同じように動作していることを確認しています。

●テクスチャフォーマット

iOS でも OpenGL ES 3.0 では Android 同様 ETC2/EAC が利用できるように
なっています。
Android など他の環境と互換性を保ちやすくなりました。

                           ETC1  ETC2/EAC  DXT(S3TC)  PVRTC(v1)  ATITC
----------------------------------------------------------------------
iOS PowerVR        ES 2.0   --     --        --        ◎         --
iOS PowerVR?       ES 3.0   ◎     ◎        --        ◎         --
Android PowerVR    ES 2.0   ◎     --        --        ◎         --
Android Tegra2/3/4 ES 2.0   ◎     --        ◎        --         --
Android Adreno200  ES 2.0   ◎     --        --        --         ◎
Android Adreno300  ES 3.0   ◎     ◎        --        --         ◎
Android Mali400    ES 2.0   ◎     --        --        --         --
Android Mali600    ES 3.0   ◎     ◎        --        --         --

Android のすべての端末と iOS ES 3.0 以降は ETC1 の読み出しができます。

Android/iOS 区別なく OpenGL ES 3.0 デバイスでは、
いまのところすべて ETC2/EAC を使うことが出来ます。

関連エントリ
OpenGL と sRGB

OpenGL と sRGB

一般的な画像はモニタに合わせてガンマ補正した非線形なデータになっています。
そのまま演算に用いると正しい結果が得られないため、事前にリニア値への
変換が必要になります。
同様に出力時は元のモニタ用の色空間に戻します。

・入力時 sRGB → Linear 変換
・出力時 Linear → sRGB 変換

OpenGL (2.1/3.0) や OpenGL ES 3.0 以降は標準である sRGB 色空間に対応しており、
リニア値との相互変換ができるようになっています。
変換が行われるのは上記のようにテクスチャの読み込みと、フレームバッファへの
書き込みのタイミングです。

●入力時

intenal format に sRGB 形式であることを指定できます。
テクスチャフェッチで同時に Linear に展開されます。
圧縮フォーマットも同様です。

// Linear
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
glCompressedTexImage2D( GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB8_ETC2, w, h, 0, size, data );
glCompressedTexImage2D( GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, w, h, 0, size, data );

// sRGB
glTexImage2D( GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
glCompressedTexImage2D( GL_TEXTURE_2D, 0, GL_COMPRESSED_SRGB8_ETC2, w, h, 0, size, data );
glCompressedTexImage2D( GL_TEXTURE_2D, 0, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, w, h, 0, size, data );

変換は RGB のみで Alpha は含まれません。
OpenGL 4.x RADEON/GeForce/Intel HD 4000、OpenGL ES 3.0 Mali-T604 で
動作を確認しています。

OpenGL ES 2.0 で用いられていた GPU 固有の圧縮フォーマットには sRGB 形式が
定義されていないものがあります。
現在わかっている情報からまとめると下記の通り。

          OpenGL ES 3.0 での sRGB
----------------------------------------
ETC1         あり(ETC2)
ETC2         あり
PVRTC        無し         (PowerVR のみ)
PVRTC2       無し         (PowerVR のみ)
ATITC        無し         (Adreno のみ)
ASTC         あり
S3TC(DXT1)   あり

ETC1 に対応する sRGB フォーマットがありませんが、ETC2 が上位互換なので
GL_COMPRESSED_SRGB8_ETC2 で読み込むことが出来ます。
OpenGL ES 3.0 GPU は ETC2/EAC に対応しているので、SRGB 形式が必要なら
ETC2 を選択することになるかと思います。

フィルタリングに関与できないので厳密ではありませんが、
シェーダーで Linear に変換することも可能です。
ガンマ補正はデータ圧縮の一種といえるので、sRGB 8bit を展開すると
リニア値は 8bit 以上の精度が必要となります。

●出力時

フレームバッファが sRGB 形式で作られている場合、書き込み時に変換が行われます。
自分で作る場合は簡単で、Texture 同様に internal format に sRGB 形式を指定します。

// Renderbuffer
glGenRenderbuffers( 1, &ColorBuffer );
glBindRenderbuffer( GL_RENDERBUFFER, ColorBuffer );
glRenderbufferStorage( GL_RENDERBUFFER, GL_SRGB8_ALPHA8, w, h );
glBindRenderbuffer( GL_RENDERBUFFER, 0 );

glBindFramebuffer( GL_DRAW_FRAMEBUFFER, FrameBuffer );
glFramebufferRenderbuffer( GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, ColorBuffer );
glBindFramebuffer( GL_DRAW_FRAMEBUFFER, 0 );

// Texture
glGenTextures( 1, &ColorTexture );
glBindTexture( GL_TEXTURE_2D, ColorTexture );
glTexImage2D( GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
glBindTexture( GL_TEXTURE_2D, 0 );

glBindFramebuffer( GL_DRAW_FRAMEBUFFER, FrameBuffer );
glFramebufferTexture2D( GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ColorTexture, 0 );
glBindFramebuffer( GL_DRAW_FRAMEBUFFER, 0 );

OS が用意する Default Framebuffer の場合は wgl や egl を用いて
SRGB 対応のフォーマットを選んでおく必要があります。

ただし Windows 7/8 + RADEON/GeForce では、特に何もしなくても SRGB 形式となっており
glEnable( GL_FRAMEBUFFER_SRGB ) だけで意図した結果が得られるようです。
逆に Intel HD 4000 (9.18.10.3165) では、下記の方法で SRGB バッファを選択しても
Default Framebuffer での変換がうまく出来ませんでした。

wgl を使った選択手段は下記のとおり。

1. wgl extension の wglChoosePixelFormatARB() を取得
2. 必要なパラメータ(attribute) を指定して wglChoosePixelFormatARB() で候補を選ぶ
3. 得られた Config 値を SetPixelFormat() に渡す

static const int PixelFormat_Attr[]= {
    WGL_DRAW_TO_WINDOW_ARB,  TRUE,
    WGL_SUPPORT_OPENGL_ARB,  TRUE,
    WGL_DOUBLE_BUFFER_ARB,   TRUE,
    WGL_PIXEL_TYPE_ARB,      WGL_TYPE_RGBA_ARB,
    WGL_COLOR_BITS_ARB,      32,
    WGL_RED_BITS_ARB,        8,
    WGL_GREEN_BITS_ARB,      8,
    WGL_BLUE_BITS_ARB,       8,
    WGL_ALPHA_BITS_ARB,      8,
    WGL_DEPTH_BITS_ARB,      24,
    WGL_STENCIL_BITS_ARB,    8,
    WGL_ACCELERATION_ARB,    WGL_FULL_ACCELERATION_ARB,
    WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB,   TRUE,
    0
};

int ChooseConfig()
{
    int  pixelformat= 0;
    if( !p_wglChoosePixelFormatARB ){ // extension の確認
        return	ChoosePixelFormat( hDC, &PixelFormat_Default );
    }
    const unsigned int	FORMAT_ARRAY_SIZE= 16;
    int	FormatArray[FORMAT_ARRAY_SIZE];
    unsigned int    array_size= 0;
    if( !wglChoosePixelFormatARB( hDC, PixelFormat_Attr, NULL, FORMAT_ARRAY_SIZE, FormatArray, &array_size ) ){
        return  0;
    }
    return  FormatArray[0];
}

void SetPixelFormat()
{
   int pixelformat= ChooseConfig();
   if( !pixelformat ){
      // error
   }
   SetPixelFormat( hDC, pixelformat, NULL );
}

Intel HD 4000 でも自分で Framebuffer を用意した場合は
glEnable( GL_FRAMEBUFFER_SRGB ) の設定が結果に影響を与えていることを確認できます。
ただし OpenGL 4.0 では結果をそのまま出力する手段が見つかりませんでした。

glBlitFramebuffer() や Texture としての読み込みは、ソースが sRGB の場合に
リニア変換されてしまうので、元が Linear か sRGB か区別出来ないからです。
よって Default Framebuffer に転送する場合にシェーダーでもう一度再エンコードが
必要となります。
OpenGL 4.2 以降ならメモリイメージとして転送できるので、もっと良い方法が
あるかもしれません。

OpenGL ES 3.0 (Mali-T604) では GL_FRAMEBUFFER_SRGB による切り替えが
できないので、Framebuffer に対して正しく変換されているかどうか確認できませんでした。
SRGB はブレンドの結果に影響を与えるので、ブレンド結果を比べれば
機能していること確認できるのではないかと思っています。

入力側は容易でしたが、出力側は必ずしも統一した挙動になってくれないようです。
Framebuffer が HDR の場合リニアのまま格納できるので、互換性を考えると
最終的にシェーダーで変換するのが一番なのかもしれません。

// GLSL
const float  SCALE_0= 1.0/12.92;
const float  SCALE_1= 1.0/1.055;
const float  OFFSET_1= 0.055 * SCALE_1;

float SRGBToLinear_F( float color )
{
    if( color <= 0.04045 ){
        return  color * SCALE_0;
    }
    return  pow( color * SCALE_1 + OFFSET_1, 2.4 );
}
float LinearToSRGB_F( float color )
{
    color= clamp( color, 0.0, 1.0 );
    if( color < 0.0031308 ){
        return  color * 12.92;
    }
    return  1.055 * pow( color, 0.41666 ) - 0.055;
}
vec3 LinearToSRGB_V( vec3 color )
{
    return  vec3(
        LinearToSRGB_F( color.x ),
        LinearToSRGB_F( color.y ),
        LinearToSRGB_F( color.z ) );
}
vec3 SRGBToLinear_V( vec3 color )
{
    return  vec3(
        SRGBToLinear_F( color.x ),
        SRGBToLinear_F( color.y ),
        SRGBToLinear_F( color.z ) );
}

関連エントリ
OpenGL 3.x/4.x のシェーダー GLSL とメモリアクセス命令
OpenGL 4.x Program Pipeline Object (Separate Shader Object)
OpenGL 4.2/4.3 Shader Resource と Buffer API
OpenGL ES 3.0/OpenGL 4.x Uniform Block
OpenGL の各バージョンと GLSL の互換性
OpenGL のエラー判定と OpenGL 4.3 Debug Output
OpenGL ES 3.0/OpenGL 4.4 Texture Object と Sampler Object
OpenGL ES 3.0 と Vertex Array Object

Adreno 320 の OpenGL ES 3.0 と Uniform Block

前回 Nexus 7 の Adreno 320 で OpenGL ES 3.0 のシェーダーが正しく動作しないと
書いたのですが、条件が絞れてきました。

UniformBlock の変数を直接演算に用いると Shader Compiler の
glLinkProgram() で Internal Error が発生するか直後にクラッシュします。

#version 300 es

// GLSL: VertexShader

precision highp float;

uniform SceneBlock {
    mat4   PView;
    mat4   ViewMatrix;
};

in vec3 POSITION;
in vec3 NORMAL;
in vec2 TEXCOORD;

out vec3 onormal;
out vec2 otexcoord;

void main()
{
    vec4 opos= vec4( POSITION.xyz, 1.0 ) * PView; // ← ここ

    opos.z= 2.0 * opos.z - opos.w;
    gl_Position= opos;
    onormal= vec3( 0.0, 0.0, -1.0 );
    otexcoord= TEXCOORD.xy;
}

下記のように、Uniform Block 内の変数を一旦ローカル変数にコピーすると
問題なく動くようになります。

void main()
{
    mat4 pv= PView;  // Uniform Block の変数をローカルにコピー
    vec4 opos= vec4( POSITION.xyz,1.0 ) * pv;

    opos.z= 2.0 * opos.z - opos.w;
    gl_Position= opos;
    onormal= vec3( 0.0, 0.0, -1.0 );
    otexcoord= TEXCOORD.xy;
}

Fragment Shader も同じです。

OpenGL ES 2.0 では Uniform Block が無いので問題ありません。

OpenGL ES 3.0 でも Uniform Block を使わない ( default Uniform Block だけ使う)
場合も問題ありませんでした。

Adreno 320 以外ではどちらのコードも動きます。
Mali-T604 実機, Adreno SDK の OpenGL ES 3.0 Emulator,
Mali Developer Tools の OpenGL ES 3.0 Emulator いずれも問題ありませんでした。

症状を確認した本体

・Nexus 7 (2013)
・Android 4.3 JSS15Q

GL_VERSION: OpenGL ES 3.0 V@14.0 AU@  (CL@)
GL_RENDERER: Adreno (TM) 320
GL_VENDOR: Qualcomm
GL_SHADING_LANGUAGE_VERSION: OpenGL ES GLSL ES 3.00

購入直後一度システムソフトウエアの更新があり、GL_VERSION の内容が
置き換わっています。上記は更新後です。
更新後も同じ症状が出ています。

回避方法がわかったので、とりあえず Adreno 320 でも OpenGL ES 3.0 用
シェーダーの動作確認ができました。

他に Intel HD 4000 (9.18.10.3165) でも Uniform Block で問題が出ています。
Uniform Block 内で mat3x4 の配列を宣言すると、index の計算を間違えるようです。
(layout std140 指定済み)
すべて vec4 宣言し、自分で matrix に組み立てることで回避できます。

関連エントリ
Nexus 7 (2013) の Adreno 320 と OpenGL ES 3.0 (Android 4.3)

Nexus 7 (2013) の Adreno 320 と OpenGL ES 3.0 (Android 4.3)

Nexus 7 (2013) が発売されたので、
Adreno 320 上でも OpenGL ES 3.0 のテストができるようになりました。
現時点で OpenGL ES 3.0 を走らせるには、
Android 4.3 と OpenGL ES 3.0 対応 GPU が必要です。

                 SoC                 CPU             GPU
---------------------------------------------------------------
Nexus 10         Exynos5 Dual        Cortex-A15 x2   Mali-T604
Nexus 7 (2013)   Snapdragon APQ8064  Krait x4        Adreno 320

現在 OpenGL ES 3.0 + Android 4.3 に対応しているのは上記 2機種です。
(おそらく明後日 30日発売の Nexus 4 も可能だと思われます)

新しい Nexus 7 を下記ページに追加しました。

CPU/GPU OpenGL ES Extension (Mobile GPU)

Qualcomm Snapdragon APQ8064 自体は、昨年末から採用端末が多数
登場しているので、今となってはあまり目新しいものではないかもしれません。
ですが、AQP8064 は CPU core, GPU core の両方が世代交代した
アーキテクチャとなっており、開発用途では非常に興味深い内容となっています。

当初から ETC2 など OpenGL ES 3.0 の仕様が部分的に含まれていましたし、
3DMark でもかなり優秀な成績を収めています。
でもこれはまだ DX10 対応 GPU で DX9 のデモを走らせているようなもの。

Android 4.3 + OpenGL ES 3.0 でようやく GPU の世代に一致したシェーダーを
走らせることができるようになります。

以下 Nexus 7 (2013) からの抜粋L

GL_VERSION: OpenGL ES 3.0 V@14.0 AU@  (CL@)
GL_RENDERER: Adreno (TM) 320
GL_VENDOR: Qualcomm
GL_SHADING_LANGUAGE_VERSION: OpenGL ES GLSL ES 3.00

Extension:
GL_AMD_compressed_ATC_texture
GL_AMD_performance_monitor
GL_AMD_program_binary_Z400
GL_EXT_debug_label
GL_EXT_debug_marker
GL_EXT_robustness
GL_EXT_texture_format_BGRA8888
GL_EXT_texture_type_2_10_10_10_REV
GL_NV_fence
GL_OES_compressed_ETC1_RGB8_texture
GL_OES_depth_texture
GL_OES_depth24
GL_OES_EGL_image
GL_OES_EGL_image_external
GL_OES_element_index_uint
GL_OES_fbo_render_mipmap
GL_OES_fragment_precision_high
GL_OES_get_program_binary
GL_OES_packed_depth_stencil
GL_OES_depth_texture_cube_map
GL_OES_rgb8_rgba8
GL_OES_standard_derivatives
GL_OES_texture_3D
GL_OES_texture_float
GL_OES_texture_half_float
GL_OES_texture_half_float_linear
GL_OES_texture_npot
GL_OES_vertex_half_float
GL_OES_vertex_type_10_10_10_2
GL_OES_vertex_array_object
GL_QCOM_alpha_test
GL_QCOM_binning_control
GL_QCOM_driver_control
GL_QCOM_perfmon_global_mode
GL_QCOM_extended_get
GL_QCOM_extended_get2
GL_QCOM_tiled_rendering
GL_QCOM_writeonly_rendering
GL_EXT_sRGB
GL_EXT_texture_filter_anisotropic
GL_EXT_color_buffer_float
GL_EXT_color_buffer_half_float

下記は Nexus 10 の Mali-T604 との比較

				        Nexus 7 (2013)  Nexus 10
                                         Adreno 320     Mali-T604
-----------------------------------------------------------------
=== GL3:texture
GL_MAX_3D_TEXTURE_SIZE                      1024          4096
GL_MAX_TEXTURE_SIZE                         4096          4096
GL_MAX_ARRAY_TEXTURE_LAYERS                 256           4096
GL_MAX_TEXTURE_LOD_BIAS                     15.984375     255.996094
GL_MAX_CUBE_MAP_TEXTURE_SIZE                4096          4096
GL_MAX_RENDERBUFFER_SIZE                    4096          4096
GL_MAX_DRAW_BUFFERS                         4             4
GL_MAX_COLOR_ATTACHMENTS                    4             4
GL_MAX_VIEWPORT_DIMS                        4096          4096
=== GL3:elements
GL_MAX_ELEMENTS_INDICES                     -1            16777216
GL_MAX_ELEMENTS_VERTICES                    -1            16777216
=== GL3:vertex
GL_MAX_VERTEX_ATTRIBS                       16            16
GL_MAX_VERTEX_OUTPUT_COMPONENTS             69            64
=== GL3:pixel
GL_MAX_FRAGMENT_INPUT_COMPONENTS            71            60
=== GL3:program
GL_MIN_PROGRAM_TEXEL_OFFSET                 -8            -8
GL_MAX_PROGRAM_TEXEL_OFFSET                 7             7
GL_MAX_VARYING_COMPONENTS                   64            60
GL_MAX_VARYING_VECTORS                      16            15
=== GL3:output stream
GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 64       64
GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS       4        4
GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS    4        4
GL_MAX_SAMPLES                                   4        4
=== GL3:uniform block
GL_MAX_VERTEX_UNIFORM_COMPONENTS            1024          1024
GL_MAX_VERTEX_UNIFORM_VECTORS               256           256
GL_MAX_VERTEX_UNIFORM_BLOCKS                12            12
GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS   --            50176
GL_MAX_FRAGMENT_UNIFORM_COMPONENTS          896           4096
GL_MAX_FRAGMENT_UNIFORM_VECTORS             224           1024
GL_MAX_FRAGMENT_UNIFORM_BLOCKS              12
GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 197504        53248
GL_MAX_UNIFORM_BUFFER_BINDINGS              24            36
GL_MAX_UNIFORM_BLOCK_SIZE                   65536         16384
GL_MAX_COMBINED_UNIFORM_BLOCKS              24            24
=== GL3:tex
GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS           16            16
GL_MAX_TEXTURE_IMAGE_UNITS                  16            16
GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS         32            32

Mali では Fragment で使える Uniform 数の方が Vertex よりも多いですが
Adreno では少なくなっているようです。
少々特殊な 896 / 224 という数値は OpenGL ES 3.0 の仕様を満たしています。
むしろ Adreno に合わせた数値(仕様)だと思われます。

実際にプログラムを走らせてみたのですが、残念ながら
Adreno 320 の OpenGL ES 3.0 ではまだ複雑なシェーダーが正しく動いていません。
簡単なシェーダーと、OpenGL ES 2.0 互換モードでは動作を確認できました。
Shader の Link 時に Internal error が発生しているので、
原因を調べているところです。

関連エントリ
Android 4.3 と OpenGL ES 3.0
Nexus 10 CPU Cortex-A15 の速度
Nexus 10 GPU Mali-T604
3DMark Android 版の結果から

OpenGL 3.x/4.x のシェーダー GLSL とメモリアクセス命令

OpenGL のシェーダーはバージョンごとに機能が拡張されています。
バッファやメモリ周りの命令は似たようなものが複数存在しており、
複雑なのでまとめてみました。

● texelFetch()

OpenGL 3.0 以降対応。OpenGL ES 3.0 対応。

指定は通常の glBindTexture() と sampler 宣言ですが、
読み取り命令が違います。

// OpenGL
glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, Texture );
#version 430
// GLSL: fsh
layout(binding=0) uniform sampler2D ColorMap;

in vec2  otexcoord;
out vec4 out_FragColor;

void main()
{
    ivec2 iuv= ivec2( otexcoord.x * 255, otexcoord.y * 255 );
    vec4  color= texelFetch( ColorMap, iuv, 0 );
    out_FragColor= color;
}

uv ではなく整数座標で直接画素値を読み取ります。
圧縮テクスチャを bind した場合は展開後の画素を読み取ります。
Texture と同じ bind point を使います。
Direct3D HLSL で Sampler を指定しない Load 系命令に相当します。

● Uniform Block

OpenGL 3.1 以降対応。OpenGL ES 3.0 でも利用できます。

GLSL の Uniform 変数を buffer として割り当てます。
詳しくは下記でまとめています。

OpenGL ES 3.0/OpenGL 4.x Uniform Block

// OpenGL
glBindBufferBase( GL_UNIFORM_BUFFER, 0, Uniform );
glUniformBlockBinding( program, 0, 0 );
#version 430
// GLSL: vsh

layout(std140,column_major) uniform MatData {
    mat4x4  PVW;
};
in vec3 POSITION;

void main()
{
    vec4  opos= vec4( POSITION.xyz, 1.0f ) * PVW;
    opos.z= 2.0f * opos.z - opos.w;
    gl_Position= opos;
}

Uniform Block は専用の bind point が割り当てられています。

● Texture Buffer

OpenGL 3.1 以降対応です。
OpenGL ES 3.0 では利用できません。

Buffer を Texture として bind できるようにします。
例えば Transform Feedback (Stream Output) の結果をシェーダーから参照する
場合などに利用できます。

// OpenGL init
struct MatData {
    math::Matrix4  PView;
    math::Matrix4  World;
    math::Vect4    UVOffset;
};
// Uniform Buffer を作る
GLuint  MatData_Uniform= 0;
glGenBuffers( 1, &MatData_Uniform );
glBindBuffer( GL_UNIFORM_BUFFER, sizeof(MatData), NULL, GL_DYNAMIC_DRAW );

// Texture Buffer を作る
GLuint  MatData_Texture= 0;
glGenTextures( 1, &MatData_Texture );
glBindTexture( GL_TEXTURE_BUFFER, MatData_Texture );
glTexBuffer( GL_TEXTURE_BUFFER, GL_RGBA32F, MatData_Uniform );
glUniformBlockBinding( program, 0, 0 );
// OpenGL render
// uniform の更新
MatData data;
data.PView.MulCopy( GetProjectionMatrix(), GetViewMatrix() );
data.Wrold.SetIdentity();
data.Wrold.RotationY( rotate_angle );
data.UVOffset.Set( 0.5f, 0.7f, 0.0f, 0.0f );
glBindBuffer( GL_UNIFORM_BUFFER, MatData_Uniform );
glBufferSubData( GL_UNIFORM_BUFFER, 0, sizeof(MatData), &data );

glUserProgram( program );
glBindVertexArray( input_layout );

// Uniform Buffer
glBindBufferBase( GL_UNIFORM_BUFFER, 0, MatData_Uniform );

// Texture
glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, Texture1 );

// Texture Buffer
glActiveTexture( GL_TEXTURE1 );
glBindTexture( GL_TEXTURE_BUFFER, MatData_Texture );

glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0 );

Vertex Shader にはそのまま Uniform Block を割り当てます。

#version 430
// GLSL: vsh
layout(std140,column_major,binding=0) uniform MatData {
    mat4x4  PView;
    mat4x4  World;
    vec4    UVOffset;
};

in vec3 POSITION;
in vec3 NORMAL;
in vec2 TEXCOORD;
out vec3 onormal;
out vec2 otexcoord;

void main()
{
    vec4  opos= vec4( POSITION.xyz, 1.0f ) * (World * PView);
    opos.z= 2.0f * opos.z - opos.w;
    gl_Position= opos;
    onormal= NORMAL.xyz * mat3x3( World );
    otexcoord= TEXCOORD.xy + UVOffset.xy;
}

Fragment Shader には Uniform Block を Texture Buffer として渡してみます。

#version 430
// GLSL: fsh

in vec3 onormal;
in vec2 otexcoord;
out vec4 out_FragColor;

layout(binding=0) uniform sampler2D     ColorMap;
layout(binding=1) uniform samplerBuffer BufferMap;

void main()
{
    float  diff= clamp( dot( vec3( 0.0f, 0.0f, -1.0f ), normalize( onormal.xyz ) ), 0.0f, 1.0f );
    vec4   uvoffset= texelFetch( BufferMap, 8 );
    vec2   uv= otexcoord.xy - uvoffset.xy;
    out_FragColor.xyz= texture( ColorMap, uv ).xyz * diff;
    out_FragColor.w= 1.0f;
}

全く同じバッファの値を、Vertex Shader は Uniform としてアクセスし、
Fragment Shader は texelFetch() を使って読み取っています。
Texture と同じ bind point です。

● Atomic Counter Buffer

OpenGL 4.2 以降で使えます。

uniform 変数のように宣言しますが特殊な型です。バッファを割り当てて使います。
この型にアクセスできるのは組み込みの関数だけです。
下記でページでも解説しています。

OpenGL 4.2/4.3 Shader Resource と Buffer API

// OpenGL init
glBindBuffer( GL_ATOMIC_COUNTER_BUFFER, CounterBlock );
glBufferData( GL_ATOMIC_COUNTER_BUFFER, sizeof(CounterData), NULL, GL_DYNAMIC_DRAW );
// OpenGL render
CounterData data;
memset( &data, 0, sizeof(CounterData) );
glBindBuffer( GL_ATOMIC_COUNTER_BUFFER, CounterBlock );
glBufferSubData( GL_ATOMIC_COUNTER_BUFFER, 0, sozeof(CounterData), &data );
~
glBindBufferBase( GL_ATOMIC_COUNTER_BUFFER, 0, CounterBlock );
~
// GLSL: psh
layout(binding=0, offset=0) uniform atomic_uint  Counter;

void main()
{
    uint  c= atomicCounter( Counter );
    ~
    atomicCounterIncrement( Counter );
}

利用可能なカウンタの個数はハードウエアで決められています。
他の書き込み可能なリソースにも atomic なオペレーション命令が複数存在しますが、
Counter は increment/decrement に特化した機能となっているようです。
専用の bind point です。

● Texture Image Load and Store

OpenGL 4.2 以降での対応です。

読み書き可能なテクスチャ命令です。

GLSL の sampler* の代わりに image* 宣言を用い、
専用の imageLoad() / imageStore() 命令で読み書きします。
Direct3D の UAV に相当します。

#version 430
// GLSL: psh

in vec2   otexcoord;
out vec4  out_FragColor;

layout(binding=3,rgba8) uniform readonly image2D  ColorMap2;

void main()
{
    ivec2 iuv= ivec2( otexcoord.x * 255, otexcoord.y * 255 );
    out_FragColor= imageLoad( ColorMap2, ivec2( xp, yp ) );
}
// OpenGL render
glUseProgram( program1 );
glBindVertexArray( input_layout );
~

glBindImageTexture( 3, texture1, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8 );

glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0 );

Texture Object の生成や初期化は通常のテクスチャと全く同じです。
Bind のみ専用の glBindImageTexture() 命令を使います。
Bind Point は新規に用意されており、通常の画像テクスチャとは別の
番号付けが行われます。

Image Load/Store が利用できる Unit の数は GL_MAX_IMAGE_UNITS です。
これまでの Texture で使われていた Texture Image Unit
(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS) とよく似ていますが別のものです。

GL_MAX_*_IMAGE_UNIFORMS
                           vsh  fsh tcsh tesh  gsh  csh combined unit
---------------------------------------------------------------------
GeForce GTX 650      4.4    8    8    8    8    8    8    48      8
RADEON HD7750(GCN)   4.3    0   32    0    0    0   32    32     32
RADEON HD6750M(VLIW) 4.3    0    8    0    0    0    8     8      8

画素フォーマットを指定するので、メモリ配置と一致しない場合は正しく読み取る
ことが出来ないようです。
texelFetch() では圧縮テクスチャの展開が可能でしたが、
image 系命令ではそのままでは出来ませんでした。
メモリイメージがそのまま読み込まれているのかもしれません。
RADEON では bind error となります。

● Shader Storage Buffer

OpenGL 4.3 以降に対応します。

読み書き可能な点では Texture Image Load and Store によく似ていますが、
Uniform Block のように変数としてアクセスすることができます。

#version 430
// GLSL: csh
layout(std140,binding=0) buffer CopyBlock {
    writeonly uint   Color[];
};

layout(binding=3,rgba8) uniform readonly image2D   ColorMap2;

layout(local_size_x=1,local_size_y=1) in;

void main()
{
    uvec2   pos= gl_GlobalInvocationID.xy;
    vec4    param= imageLoad( ColorMap2, ivec2( pos.x, pos.y ) );
    uint    index= gl_GlobalInvocationID.y * 256 + gl_GlobalInvocationID.x;
    param.xyzw= param.yxzw;
    Color[index]= packUnorm4x8( param );
}
#version 430
// GLSL: psh

in vec3   onormal;
in vec2	  otexcoord;
out vec4  out_FragColor;

layout(std140,binding=0) buffer CopyBlock {
    readonly uint   Color[];
};

void main()
{
    float diff= clamp( dot( vec3( 0.0f, 0.0f, -1.0f ), normalize( onormal.xyz ) ), 0.0f, 1.0f );
    vec2  uv= otexcoord.xy;
    uint  xp= uint( uv.x * 255.0f );
    uint  yp= uint( uv.y * 255.0f );
    uint  index= yp * 256 + xp;
    vec4  color2= unpackUnorm4x8( Color[index] );
    out_FragColor.xyz= color2.xyz * diff;
    out_FragColor.w= 1.0f;
}
// OpenGL init
struct Packed8888 {
    unsigned char  color[4];
};
glGenBuffers( 1, &Color_SSB );
glBindBuffer( GL_SHADER_STORAGE_BUFFER, Color_SSB );
glBufferData( GL_SHADER_STORAGE_BUFFER, sizeof(Packed8888) * 256 * 256 * 4, NULL, GL_DYNAMIC_DRAW );
// OpenGL render

// Compute Shader
glUseProgram( csh_program );

glBindImageTexture( 3, texture1, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8 );
glBindBufferBase( GL_SHADER_STORAGE_BUFFER, 0, Color_SSB );

glDispatchCompute( 256, 256, 1 );


// Render
glUseProgram( program1 );
glBindVertexArray( input_layout );
glBindBufferBase( GL_UNIFORM_BUFFER, 2, MatData_Uniform );
glBindBufferBase( GL_SHADER_STORAGE_BUFFER, 0, Color_SSB );

glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0 );

Compute Shader を使って、Image (Texture Image Load and Store) から
Shader Storage Buffer に画像をコピーしてるだけです。

Fragment Shader では Shader Storage Buffer の内容をテクスチャとして描画します。
少々手抜きで、Shader Storage Buffer は 4倍のメモリを確保していることになります。

RADEON の場合 Image 命令と Shader Storage Buffer の共存がうまくいっておりません。

過去記事 でも書いたように bind point は独自のものになっています。

GL_MAX_*_SHADER_STORAGE_BLOCKS
                           vsh  fsh tcsh tesh  gsh  csh combined size
----------------------------------------------------------------------
GeForce GTX 650      4.4   16   16   16   16   16   16    96      2GB
RADEON HD7750(GCN)   4.3   16   16   16   16   16   16    16     16MB
RADEON HD6750M(VLIW) 4.3    8    8    8    8    8    8     8     16MB

Texture Image Load and Store と機能が似ていますが上記のように違いが見られます。
RADEON の場合 Image Unit は fsh/csh だけでした。
Shader Storage はどのシェーダーでも有効になっています。

● Shared Memory

OpenGL 4.3 以降で利用できます。

Shared Memory は Compute Shader だけが利用できるローカルメモリです。
GLSL 内で shared 宣言します。

#version 430
// GLSL: csh
~
shared uint flags[1024];
GL_COMPUTE_SHARED_MEMORY_SIZE
                             csh
---------------------------------------
GeForce GTX 650      4.4     49152 byte
RADEON HD7750(GCN)   4.3     32768 byte
RADEON HD6750M(VLIW) 4.3     32768 byte

種類も多いので、機能の違いや使い方を理解するまでは大変かもしれません。
実際に使ってみると思ったよりも扱いやすい印象でした。
特に OpenGL 4.3 以降は bind 値を全部 Shader 側で指定できるので
手間がかなり減っています。

関連エントリ
OpenGL 4.x Program Pipeline Object (Separate Shader Object)
OpenGL 4.2/4.3 Shader Resource と Buffer API
OpenGL ES 3.0/OpenGL 4.x Uniform Block
OpenGL の各バージョンと GLSL の互換性
OpenGL のエラー判定と OpenGL 4.3 Debug Output
OpenGL ES 3.0/OpenGL 4.4 Texture Object と Sampler Object
OpenGL ES 3.0 と Vertex Array Object