oFで3次元のattribute変数へのデータを送る際につまずいたこと


始めに

こんにちは、最近は開発しながらyoutubeでPerfumeのライブ動画とか見てるんですけど、演出がマジでかっこいいですね。。さすがライゾマ。。見ているだけでモチベが上がります.はいでは本題に入りましょう。
この記事では、shader(VertexShader)内の三次元のattribute変数にC++コードからデータを転送する際につまずいたことを書いていこうと思います.この記事を読んでご意見などありましたらお願いします.

そもそもattribute変数とは??

この記事について検索をかけている方ならわかっていると思いますが、一応説明させていただきます.attribute変数とは頂点ごとに違うデータを格納できる変数になります.代表的な例とするならば、頂点情報、法線情報、色情報とか.わざわざ送らなくてもglsl内の組み込み変数で取得できる物もあるんですね.

今回すること

vboにデータを格納した後、その法線情報をVertexShaderへ渡して、数値を確認するためにvarying変数を用いてFragmentShaderへ渡して色を確認していこうと思います.今回は簡略化のため面ではなく点の法線?ちょっと変な感じがしなくもないですが、それを使っていこうとおもいます.
以下のコードは attribute変数周りの処理を書いているコードで全体の一部となります.

shader.vert
#version120
attribute vec3 normal;
varying   vec4 vColor;
void main()
{
    vColor = vec4(normal, 1.0);
    vec4 eyeCoord  = gl_ModelViewMatrix * gl_Vertex;
    gl_Position    = gl_ProjectionMatrix * eyeCoord;  
}

shader.frag
#version120
varying vec4 vColor;
void main()
{
    gl_FragColor = vec4(vColor);
}


ofApp.h
float attNormal[Num*3];//法線情報を格納した転送用配列

ofApp.cpp

for(int i = 0; i < WIDTH; i++){
        for(int j = 0; j < HEIGHT; j++){

            attNormal[(j * WIDTH + i)*3] = 0.0f;
            attNormal[(j * WIDTH + i)*3 + 1] = 0.0f;
            attNormal[(j * WIDTH + i)*3 + 2] = 1.0f;     
        }
    }



shader.begin();

attLocation[1]  = shader.getAttributeLocation("normal");
glEnableVertexAttribArray(attLocation[1]);
glVertexAttribPointer(attLocation[1] ,3, GL_FLOAT, 0, 0, attNormal);
cout << attLocation[1] << endl;

shader.end();

結果

はい、法線情報をattNormal(0.0, 0.0, 1.0)としていてそれをrgbに変換していたので、ちゃんと青として出ていますね.成功です.(やった!)

つまずきやすい部分

自分がつまづいた部分ではあるんですが、今回のポイントは転送先のattribute変数が3次元ベクトルであるからと言って、転送元のattNormalは3次元ベクトルにしてはいけないってことなんですね。。。。float型の1次元配列で法線情報を保管しておいて、glVertexAttribPointer関数の第二引数でデータ要素数を指定すればいいってことでした.ふむふむって感じですねぇ。。。。