この節では前準備として、シェーダに与えるデータ内容の準備をします。
まずは今まで使っていたシェーダのコードをあらためて見てみましょう。
#version 450
#extension GL_ARB_separate_shader_objects : enable
void main() {
if(gl_VertexIndex == 0)
{
gl_Position = vec4(0.0, -0.5, 0.0, 1.0);
}
else if(gl_VertexIndex == 1)
{
gl_Position = vec4(0.5, 0.5, 0.0, 1.0);
}
else if(gl_VertexIndex == 2)
{
gl_Position = vec4(-0.5, 0.5, 0.0, 1.0);
}
}
gl_VertexIndexというのは頂点の番号です。今まではこれだけを頼りに無理やり頂点の座標を出力していました。これからは外部からデータがもらえるので、頂点番号などを参照しなくてもよくなります。
新しい頂点シェーダはこちらです。
#version 450
#extension GL_ARB_separate_shader_objects : enable
layout(location = 0) in vec2 inPos;
void main() {
gl_Position = vec4(inPos, 0.0, 1.0);
}
inPosというのが増えていますね。ここに適宜頂点データが入ってきます。
頂点シェーダは頂点の数だけ呼ばれるシェーダですが、それぞれの頂点の演算ごとに、それぞれの頂点の座標データがinPosへ入ってきます。そのデータを使ってgl_Positionを出しているわけです。これでもうシェーダ内で頂点番号などを考える必要はありませんね。
さて、inPosに入れるデータを準備するのも勿論我々です。inPosにはどんなデータが入ってくればいいか考えてみましょう。
前のコードと同じ出力をするためには、inPosに以下のデータを与える必要があります。
- 0番目→(0.0, -0.5)
- 1番目→(0.5, 0.5)
- 2番目→(-0.5, 0.5)
このようにデータを与えれば、各頂点では前と同じく以下のような座標を出力してくれますね。
- 0番目→ gl_Position = vec4(inPos, 0.0, 1.0) → (0.0, -0.5, 0.0, 1.0)
- 1番目→ gl_Position = vec4(inPos, 0.0, 1.0) → (0.5, 0.5, 0.0, 1.0)
- 2番目→ gl_Position = vec4(inPos, 0.0, 1.0) → (-0.5, 0.5, 0.0, 1.0)
頂点データを準備します。とりあえず適当な変数配列を作ってそこに格納してあげましょう。
struct Vertex {
float x, y;
};
std::vector<Vertex> vertices = {
Vertex{ 0.0f, -0.5f },
Vertex{ 0.5f, 0.5f },
Vertex{-0.5f, 0.5f }
};
後々便利なのでstd::vectorにしました。
この節では新しい頂点シェーダのコード、および頂点のデータを用意しました。
次節では頂点データをシェーダに渡すためのバッファを作成します。
注意ですが、4章までのメインプログラムのコードと今回のシェーダのコードを組み合わせてはいけません。エラーが出ます。4章までのコードにはシェーダにデータを与えるような仕組みは無いためです。
今回は説明のためにシェーダのコードを示しました。5-5節までこのシェーダのコードを使うのは待ってください。