WebGLではWebGLRenderingContext.vertexAttribPointer()でバッファーオブジェクトの使用方法を指定します。vertexAttribPointer
のtype
引数にはgl.SHORT
など整数のデータ型を指定できますが、シェーダー側では浮動小数点数としてしか受け取れないので、使用する際には以下のようにシェーダー側で型変換する必要があります。
gl.bufferData(gl.ARRAY_BUFFER, new Int16Array([0, 1, 2]), gl.STATIC_DRAW);
...
gl.vertexAttribPointer(0, 1, gl.SHORT, false, 0, 0);
頂点シェーダー
#version 300 es
layout (location = 0) in float i_index;
vec3[3] POSITIONS = vec3[](
vec3(-0.5, -0.5, 0.0),
vec3(0.5, -0.5, 0.0),
vec3(0.0, 0.5, 0.0)
);
void main(void) {
gl_Position = vec4(POSITIONS[int(i_index)], 1.0);
}
WebGL2からはWebGL2RenderingContext.vertexAttribIPointer()を使用すれば以下のようにシェーダー側で整数として受け取れるようになるので、型変換の必要がなくなります。(わかりづらいですがAttrib
の後にI
があります)
layout (location = 0) in int i_index;
型付き配列の精度に応じてvertexAttribIPointer
のtype
を決定します。例えば、Int16Array
の場合はgl.SHORT
を、Int32Array
の場合はgl.INT
を使用することになります。
gl.bufferData(gl.ARRAY_BUFFER, new Int16Array([0, 1, 2]), gl.STATIC_DRAW);
...
gl.vertexAttribIPointer(0, 1, gl.SHORT, 0, 0);
gl.bufferData(gl.ARRAY_BUFFER, new Int32Array([0, 1, 2]), gl.STATIC_DRAW);
...
gl.vertexAttribIPointer(0, 1, gl.INT, 0, 0);
符号なし整数を使用する場合は16bit、32bitそれぞれ以下のようになります。
gl.bufferData(gl.ARRAY_BUFFER, new Uint16Array([0, 1, 2]), gl.STATIC_DRAW);
...
gl.vertexAttribIPointer(0, 1, gl.UNSIGNED_SHORT, 0, 0);
gl.bufferData(gl.ARRAY_BUFFER, new Uint32Array([0, 1, 2]), gl.STATIC_DRAW);
...
gl.vertexAttribIPointer(0, 1, gl.UNSIGNED_INT, 0, 0);
シェーダー側では次のようにuint
で受け取ることができます。
layout (location = 0) in uint i_index;
サンプルのソースコードをgistに置いておきました。
https://gist.github.com/aadebdeb/5f2e70095762e24ab5f132925f67e3cd