GLSLでのテクスチャの取り扱いについて.
----
#contents
----
*シェーダへのテクスチャ受け渡し [#rc1323d3]
OpenGLではglBindTextureでテクスチャをバインドし,glTexCoordでテクスチャ座標を指定して貼り付ける.このときテクスチャを表すのがglGenTexture関数に生成されたテクスチャオブジェクトである.
GLSLにもテクスチャオブジェクトを渡してテクスチャ参照したいが,
現在のAPIではテクスチャユニットという別の整数インデックスを用いてアクセスする
(将来的には直接テクスチャオブジェクトを渡せるようになるかもしれない).
カレントのテクスチャユニットはマルチテクスチャ使用時に用いる
void glActiveTexture(GLenum texture);
により指定する.例えばテクスチャユニット0の場合,以下となる.
glActiveTexture(GL_TEXTURE0);
使用するテクスチャユニットを上記命令でONにした後,glBindTextureにより対応するテクスチャをバインドする.
複数用いる場合の例は以下.
#code(C){{
GLuint texa = 0, texb = 0, texc = 0;
glActiveTexture(GL_TEXTURE0);
LoadGLTexture("texture/image0.png", texa, false, false);
glBindTexture(GL_TEXTURE_2D, texa);
glActiveTexture(GL_TEXTURE1);
LoadGLTexture("texture/image1.png", texb, false, false);
glBindTexture(GL_TEXTURE_2D, texb);
glActiveTexture(GL_TEXTURE2);
LoadGLTexture("texture/image2.png", texc, false, false);
glBindTexture(GL_TEXTURE_2D, texc);
}}
ここで,LoadGLTextureは画像を読み込んでテクスチャオブジェクトを生成,テクスチャメモリに画像を転送する関数である.
GLSLに渡すときはglUniform1iを用いる.
glUniform1i(glGetUniformLocation(g_glslTexture.Prog, "texa"), 0);
glUniform1i(glGetUniformLocation(g_glslTexture.Prog, "texb"), 1);
glUniform1i(glGetUniformLocation(g_glslTexture.Prog, "texc"), 2);
*テクスチャユニットの最大数 [#x1ed91a5]
テクスチャユニットの最大数はglGetIntegerにGL_MAX_VERTEX_TEXTURE_IMAGE_UNITS(頂点シェーダ),
GL_MAX_TEXTURE_IMAGE_UNITS(フラグメントシェーダ)を指定することで取得できる.
コード例
#code(C){{
// テクスチャ最大数
GLint num_tex_units;
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &num_tex_units);
cout << "Max texture units = " << num_tex_units << endl;
}}
*3つのテクスチャを用いる例 [#w467457a]
以下の3つのテクスチャを読み込んで重ねて描画するコードの例を示す.
|&ref(objects.jpg); | &ref(checkboard.jpg); | &ref(mask.jpg); |
|テクスチャ0|テクスチャ1|テクスチャ2|
頂点シェーダは単に頂点位置を処理して,テクスチャ座標を渡すだけである.
#code(C){{
void main(void)
{
gl_Position = gl_ModelViewProjectionMatrix*gl_Vertex; // 頂点位置
gl_TexCoord[0] = gl_MultiTexCoord0; // 頂点テクスチャ座標
}
}}
フラグメントシェーダではテクスチャを参照して,テクスチャ0の白い部分を透明にして一番上のレイヤーに置き,
テクスチャ1と2をブレンドして背景とする処理を行う.
#code(C){{
// テクスチャ
uniform sampler2D tex0;
uniform sampler2D tex1;
uniform sampler2D tex2;
void main(void)
{
// テクスチャ
vec3 color_tex0 = texture2D(tex0, gl_TexCoord[0].st).xyz;
vec3 color_tex1 = texture2D(tex1, gl_TexCoord[0].st).xyz;
vec3 color_tex2 = texture2D(tex2, gl_TexCoord[0].st).xyz;
float gray = (color_tex0.r+color_tex0.g+color_tex0.b)/3.0;
if(gray > 0.999){
gl_FragColor.rgb = color_tex1+color_tex2;
}
else{
gl_FragColor.rgb = color_tex0;
}
gl_FragColor.a = 1.0;
}
}}
***実行結果 [#h88195ab]
実行結果のスクリーンショットを以下に示す(クリックで拡大).
#ref(texture3.jpg,,50%)
***ソースコード [#k9b6f81e]
Visual Studio 2010用のソースコードを以下に置く(要GLUT,GLEW,libjpeg,libpng).
#ref(glsl_texture.zip)