GLSLのQualifier変数タイプ
GLSLは日本語の教科書がまだ少ないので、分かったことを書いておこうと思っていました。今回は、GLSLで初めてプログラムする場合、分かりにくい点の一つに変数のQuailifierプリフィックスがあるので、簡単に説明します。GLSLで使用される変数タイプにおいて、C言語等にはない種類としてQualifier(日本語でなんと訳せばよいのかよく分かりません)があります。C言語にないのは当たり前で、シェーダ間、及びシェーダ-OpenGL間で渡す変数のタイプ宣言だからです。GLSLの仕様書や分厚い英語のリファレンスを見ると、次に示す4種類のQualifier変数があります。
| attribute | OpenGLプログラムから渡す変数です。 頂点ごとに変化する値を渡すことができます。ビルトインのattribute変数としては、gl_Vertex, gl_Normalなどがあります。ユーザ独自の頂点ごとに変化するデータを用意し、シェーダに渡すことが可能です。 バーテックスシェーダでしか使用できません。 |
| uniform | OpenGLプログラムから渡す変数です。 描画プリミティブごとに渡すことができます。ビルトインのuniform変数としては、sampler2D, samplerCubeなどがあります。 バーテックスシェーダ、フラグメントシェーダの両方で使用できます。 |
| varing | バーテックスシェーダからフラグメントシェーダに渡す変数です。 バーテックスシェーダとフラグメントシェーダの両方で宣言します。 |
| const | コンパイル時に定数として処理されるコンスタント変数です。 シェーダの中で変数の値を変更することはできません。 |
使い方ですが、シェーダプログラムにおいて、Qualifier変数は関数の外で宣言するため、C言語で言うところのグローバル変数のような感じです。
// vertex shader
attribute vec3 tangent;
uniform float angle;
varying vec3 normal;
const int numLights = 3;
void main(void)
{
position = vec3(gl_ModelViewMatrix * gl_Vertex);
normal = gl_NormalMatrix * gl_Normal;
: : 途中略 : :
}
// fragment shader
uniform sampler2D texture;
varying vec3 normal;
void main(void)
{
vec4 color = texture2D(texture, gl_TexCoord[0].st);
vec3 fnormal = normalize(normal);
: : 途中略 : :
}
uniform変数のOpenGLからの渡し方は次のようになります。uniform変数の場合、glGetUniformLocationを使用して、シェーダプログラムから変数名によりその変数番号を取得し、glUniform関数で値をセットすることでシェーダに渡すことが可能です。変数の要素数や型に応じて、glUniform**の**の部分を変える必要があります。
/* シェーダプログラムの適用 */ glUseProgram(shdProg); /* バーテックスシェーダのunform変数angleに値をセット */ angleIdx = glGetUniformLocation(shdProg, "angle"); glUniform1f(angleIdx, 20.0f); <- float変数のため、glUniform1fを使用 /* フラグメントシェーダのunform変数textureに値をセット */ textureIdx = glGetUniformLocation(shdProg, "texture"); glUniform1i(textureIdx, 0); <- テクスチャの場合、ユニット番号を指定
一方、attriubte変数の場合、次のようにglGetAttribLocationを使用します。uniform変数同様、シェーダプログラムから変数名によりその変数番号を取得します。その後、頂点配列や頂点バッファを使用してデータを渡す場合、glEnableVertexAttribArrayで有効にし、glVertexAttribPointerで要素数、型、ストライド、データへのポインタ等を指定します。
/* シェーダプログラムの適用 */ glUseProgram(shdProg); /* バーテックスシェーダのattribute変数tangentに頂点データを渡す */ tangentLoc = glGetAttribLocation(shdProg, "tangent"); glEnableVertexAttribArray(tangentLoc); glVertexAttribPointer(tangentLoc, 3, GL_FLOAT, GL_FALSE, 0, lpData);
glVertexAttribPointerは引数が多くややこしいですが、次のような関数プロトタイプです。
void glVertexAttribPointer(
GLuint index, /* glGetAttributeLocationで得られる変数番号 */
GLint size, /* 要素数 1,2,3,4のいずれか */
GLenum type, /* データの型 */
GLboolean normalized, /* 整数型データの場合、正規化するかどうか */
GLsizei stride, /* 頂点データのストライド */
const GLvoid *pointer /* 頂点データへのポインタ(オフセット) */
);
4番目の引数normalizedは、glVertexPointer等でも見慣れない引数ですが、頂点データが整数型の場合に、正規化([-1,1]や[0,1]への正規化)して渡すか、そのまま渡すかを指定するものです。例えば、データを節約するために、float型ではなく、short型のデータで[-1,1]の範囲の座標を渡したい場合に有効です。また、頂点配列や頂点バッファを使用せずに頂点データを渡す場合、glVertexAttribを使用します。詳しくはリファレンスを見てください。
最新の7件
OpenGL
電子工作
玄箱HG
- ClamAVのアップデート
- Smartyも入れてみる
- etchでPHP4->PHP5
- etchでのSamba設定
- etchでのメール設定
- 玄箱HGのetch化
- Webdruidでログ解析
- PEARも入れてみる
- 玄箱WEBのUTF-8化
- phpMyAdminでMySQL
- postmasterの変更
- ウィルスメール対策
- SPAMメール対策
- メールサーバ(IMAP)
- メールサーバ(Postfix)
- 猫にXOOPS
- PHPも入れてみる
- MySQLを入れてみる
- Subversion導入
- WebDav導入
- Apacheのrewrite機能
- Apacheディレクトリ設定
- Apache1.3->2.0
- ddclientの設定
- 静かな玄箱
- ユーザ追加