1
代入が確認できたから、次にテクスチャ間でデータの単純なコピーを確認する。Cのプ
2
ログラムに表すならば、2次元配列 x、zについて
3
z[i][j] = x[i][j];
4
という実行である。
5
GPU内のデータの流れを図4.17のように設定する。まず、ホストプログラムによって
6
フラグメントシェーダープログラム内のテクスチャ x を適当な初期値でセットアップす
7
る。この方法は前章の通りであり、4.1.4節の入出力兼用テクスチャRWTexture2Dでそれ
8
を行う。次に、そのテクスチャの内容を出力テクスチャへ画素毎に格納すればよい。具体
9
的には以下の通りである。
10
4.3.1 ホストプログラムの変更
11
まず、プログラムの構成上、以下の大域変数を追加宣言しておく。
12
✓ ✏ RWTexture2D *texXp;
RGBA x[height][width];
void initData() {
Position2D pos[NUM_POINTS];
pos[0].x = -1.0; pos[0].y = -1.0;
pos[1].x = +1.0; pos[1].y = -1.0;
pos[2].x = +1.0; pos[2].y = +1.0;
pos[3].x = -1.0; pos[3].y = +1.0;
ArrayBuffer ab((float*)pos,2,NUM_POINTS);
sp->bindArrayBuffer("position",&ab);
for(int h = height-1; h >= 0; h--){
for(int w = 0; w < width; w++){
x[h][w].r = w+h+0.1; // 設定値は任意でよい。
x[h][w].g = w+h+0.2;
x[h][w].b = w+h+0.3;
x[h][w].a = w+h+0.4;
} }
texXp = new RWTexture2D(1,x,width,height); // 入力用テクスチャ texZp = new RWTexture2D(0,NULL,width,height); // 出力用テクスチャ sp->bindTextureR("tx",texXp); // GPUへデータを転送
sp->bindTextureW(texZp); // テクスチャをフレームバッファと接続 sp->setFloat("width",width); // テクスチャの幅をシェーダーに渡す sp->setFloat("height",height); // テクスチャの高さをシェーダーに渡す
✒} ✑
図4.18: コピーのためのinitData() これを用いて、図4.18のinitData()では、
1
1. 配列 xの適当な初期値を代入し、
2
2. 入力用テクスチャオブジェクトを xを用いて生成し、
3
3. このオブジェクトをポインタtexXp に保持する。
4
4. さらにこのオブジェクトをテクスチャunifrom変数 tx に結びつける。
5
また、フラグメントシェーダー内での処理にテクスチャの幅、高さが必要になるため、
6
sp->setFloat("width",width);
7
sp->setFloat("height",height);
8
✓ ✏ void showResults()
{
RGBA result[height][width];
texZp->readData(result,width,height);
for(int h = height-1; h >= 0; h--){
for(int w = 0; w < width; w++){
printf("%d %d r : %7.3f %7.3f\n",
w, h, x[h][w].r, result[h][w].r);
printf("%d %d g : %7.3f %7.3f\n",
w, h, x[h][w].g, result[h][w].g);
printf("%d %d b : %7.3f %7.3f\n",
w, h, x[h][w].b, result[h][w].b);
printf("%d %d a : %7.3f %7.3f\n",
w, h, x[h][w].a, result[h][w].a);
} }
✒} ✑
図4.19: コピー確認のためのshowResults()
で、それらをシェーダー内のunifrom変数 width、heightへ渡しておく。
1
次に、関数showResults()を図4.19のように作り、入力テクスチャの各配列要素の値
2
と出力用テクスチャから得られた各配列要素の値の比較を行うこととする。
3
4.3.2 フラグメントシェーダープログラムの変更
4
フラグメントシェーダープログラムは図4.20のように変更する。ここに、テクスチャ
5
tx にアクセスするときの座標値の計算式が以下であることに注意する。
6
vec2(gl FragCoord.x/width, gl FragCoord.y/height)
7
既に述べたように、gl FragCoordの値の範囲は以下 [0,width]×[0,height]
であり、前章で述べたように、テクスチャ座標の範囲は [0,1]×[0,1]
✓ ✏
#version 120
uniform sampler2D tx;
uniform float width;
uniform float height;
void main(void) {
vec2 texCoord = vec2(gl_FragCoord.x/width,gl_FragCoord.y/height);
gl_FragColor = texture2D(tx,texCoord);
✒} ✑
図 4.20: コピーのためのフラグメントシェーダープログラム
4.3.3 実行結果
1
showResults()の実行結果は以下の通りとなり、コピーは正しく行われていることが分
2
かる。
3
0 6 r : 6.100 6.100
4
0 6 g : 6.200 6.200
5
0 6 b : 6.300 6.300
6
0 6 a : 6.400 6.400
7
1 6 r : 7.100 7.100
8
中略
9
3 0 a : 3.400 3.400
10
4 0 r : 4.100 4.100
11
4 0 g : 4.200 4.200
12
4 0 b : 4.300 4.300
13
4 0 a : 4.400 4.400
14
ホストプログラム
バーテックス シェーダー プログラム
フラグメント シェーダー プログラム
画像出力
CPU
GPU
ラスタ ライザ
テクスチャ : z attribute 変数
フレームバッファ オブジェクト テクスチャ : y テクスチャ : x
float:alpha
図4.21: saxpy計算の経路