図 2.57: 画像例(その7、三角形を30度回転させた場合)
ホストプログラム
バーテックス シェーダー プログラム
フラグメント シェーダー プログラム
画像出力
CPU
GPU
ラスタ ライザ
uniform 変数 attribute 変数
図2.58: attribute変数とuniform変数の関係
uniform変数の具体的な利用法を以下に解説する。
1
2.11.1 Shaderクラスの拡張
2
まず、ホストプログラムからfloat型uniform変数に値を代入するためのメンバー関数
3
void setFloat(const char* vname, float val);
4
をShaderクラスに新たに追加する。ここに、第1引数がuniform変数名、第2引数が代
5
入する値である。その実装は図2.59の通りである。関数本体の代入文:
6
GLint p = glGetUniformLocation(program, vname);39
7
は、バーテックスシェーダープログラムおよび(または)フラグメントシェーダープログラ
8
ム中からvnameと同じ変数名のuniform変数を見つけ、その場所(location)を変数pへ
9
代入する。関数glGetUniformLocation()は2.2節に出てきたglGetAttribLocation()
10
に類似の機能であるが、前者はuniform変数の、後者はattribute変数の場所を見つける
11
✓ ✏ void Shader::setFloat(const char* vname, float val){
GLint p = glGetUniformLocation(program, vname);
if(p < 0) {
cerr << "uniform name error: " << vname << endl;
exit(1);
}
glUniform1f(p,val);
✒} ✑
図2.59: Shader::setFloat()の実装
✓ ✏
void display(void) {
sp->setFloat("theta",30*M_PI/180.0);
glClear(GL_COLOR_BUFFER_BIT);
sp->run(GL_TRIANGLES,NUM_POINTS);
✒} ✑
図2.60: uniform変数へ回転角度を代入するdisplay()
関数である。もしpの値が負値ならば、その変数名がバーテックスシェーダープログラム
1
とフラグメントシェーダープログラムのどちらにも宣言されていないことを意味する。そ
2
の場合、図2.59の関数ではエラーメッセージを出力し、プログラム全体を強制終了する。
3
関数呼び出し:
4
glUniform1f(p,val)40
5
はuniform変数の場所に実際にfloat値valを代入する。glUniform1f()と類似した関
6
数として、glUniform2f()41、glUniform3f()42、glUniform4f()43などもある。これら
7
はそれぞれvec2、vec3、vec4型のuniform変数へ値を代入する関数である。また、別の
8
類似関数 glUniform1i()44 はint型uniform変数へ値を代入する。
9
2.11.2 ホストプログラムの変更
10
すぐ後に述べるが、図2.61のバーテックスシェーダープログラムに回転角を保持する
11
uniform変数theta(角度θのつもり)を導入する。そこで、図2.60のホストプログラム
12
40void glUniform1f(GLint location, GLfloat v0);
41void glUniform2f(GLint location, GLfloat v0, GLfloat v1);
42void glUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
43void glUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
44void glUniform1i(GLint location, GLint v0);
✓ ✏
#version 120
attribute vec2 position;
attribute vec3 in_color;
varying vec3 out_color;
uniform float theta; // 追加 void main(void)
{
float x = cos(theta)*position.x-sin(theta)*position.y; // 回転変換 float y = sin(theta)*position.x+cos(theta)*position.y; // 回転変換 gl_Position = vec4(x,y,0.0,1.0);
out_color = in_color;
✒} ✑
図2.61: 入力座標を回転させるバーテックスシェーダープログラム
の描画関数display()では、そのthetaへ角度30度(ラジアンモードでは= 30◦·π/180)
1
を代入する関数呼び出し:
2
sp->setFloat("theta",30*M PI/180.0)
3
を実行する。この関数呼び出しはinitData()に追加してもよいが、後節で三角形の回転
4
するCGアニメーションを行うことを想定し、ここではdisplay()に追加しておく。
5
2.11.3 バーテックスシェーダープログラムの変更
6
図2.61がバーテックスシェーダープログラムである。回転角に対応する変数 thetaを
7
uniform宣言している。その変数を用いて、attribute変数として入力された2次元座標
8
positionを回転させ、回転後の座標値を gl Position へ代入している45。
9
フラグメントシェーダープログラムは変更しない。
10
2.11.4 実行結果
11
図2.62が実行の様子である。attribute変数として入力された座標値はバーテックスシェー
12
ダーでuniform変数thetaの値だけ回転される。その回転された座標値がラスタライザ
13
V.S.
V.S. ラスタ
ライザ
V.S.
F.S.
F.S.
attribute 変数
uniform 変数 theta
図2.62: 三角形が回転する場合の動作例
へ入力されて、回転された三角形の画素が求められる。
1