Qt GUIで頂点シェーダに整数を渡す:QOpenGLExtraFunctions::glVertexAttribI4iv()徹底解説


QOpenGLExtraFunctions::glVertexAttribI4iv()関数は、OpenGL Shading Language(GLSL)で定義された頂点属性に4つの整数値を割り当てるために使用されます。これは、頂点シェーダ内で使用されるデータの配列を指定するために役立ちます。

構文

void QOpenGLExtraFunctions::glVertexAttribI4iv(GLuint index, const GLint *values);

引数

  • values: 頂点属性に割り当てる4つの整数値の配列へのポインタ
  • index: 頂点属性のインデックス番号

詳細

glVertexAttribI4iv()関数は、指定されたインデックスの頂点属性にvalues配列内の4つの整数値を割り当てます。これらの値は、頂点シェーダ内でlayout(location = index)アノテーションで指定された属性変数にアクセスするために使用されます。

この関数は、頂点データの整数を効率的に設定するために使用できます。例えば、頂点の色情報などを整数の形式で格納したい場合に役立ちます。

// 頂点シェーダ
layout(location = 0) in vec3 position;
layout(location = 1) in ivec4 color;

void main() {
  gl_Position = vec4(position, 1.0);
  gl_FragColor = color;
}

// C++コード
QOpenGLExtraFunctions *functions = QOpenGLContext::currentContext()->functions();

// 頂点データの初期化
GLint vertices[] = {
  -1, -1, 0,
  1, -1, 0,
  0, 1, 0
};

GLint colors[] = {
  255, 0, 0, 255,
  0, 255, 0, 255,
  0, 0, 255, 255
};

// 頂点属性の設定
functions->glVertexAttribPointer(0, 3, GL_INT, GL_FALSE, 0, vertices);
functions->glEnableVertexAttribArray(0);

functions->glVertexAttribI4iv(1, colors);
functions->glEnableVertexAttribArray(1);

// 描画
glDrawArrays(GL_TRIANGLES, 0, 3);

この例では、頂点シェーダでpositioncolorという2つの頂点属性を定義しています。glVertexAttribPointer()関数を使用してposition属性に頂点座標データを設定し、glVertexAttribI4iv()関数を使用してcolor属性に頂点の色情報 (整数値) を設定しています。

  • 頂点属性のデータサイズは、glVertexAttribPointer()関数を使用して指定する必要があります。
  • 頂点属性のデータ型は、GL_INT, GL_UNSIGNED_INT, GL_BOOL, GL_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FLOAT, GL_DOUBLE, GL_HALF_FLOAT, GL_FIXED のいずれかである必要があります。
  • 頂点属性のインデックス番号は、0から始まり、最大値はOpenGL実装によって異なります。
  • glVertexAttribI4iv()関数は、OpenGL 3.1以降でのみ使用できます。


#include <QApplication>
#include <QGLWidget>

class MyGLWidget : public QGLWidget
{
public:
    MyGLWidget(QWidget *parent = nullptr);

protected:
    void initializeGL();
    void paintGL();

private:
    QOpenGLExtraFunctions *functions;

    // 頂点データ
    GLint vertices[] = {
        -1, -1, 0,
        1, -1, 0,
        0, 1, 0
    };

    // 頂点の色情報 (整数値)
    GLint colors[] = {
        255, 0, 0, 255,
        0, 255, 0, 255,
        0, 0, 255, 255
    };
};

MyGLWidget::MyGLWidget(QWidget *parent) : QGLWidget(parent)
{
    functions = QOpenGLContext::currentContext()->functions();
}

void MyGLWidget::initializeGL()
{
    // OpenGLの設定
    glShadeModel(GL_SMOOTH);
    glEnable(GL_DEPTH_TEST);

    // 頂点属性の設定
    functions->glVertexAttribPointer(0, 3, GL_INT, GL_FALSE, 0, vertices);
    functions->glEnableVertexAttribArray(0);

    functions->glVertexAttribI4iv(1, colors);
    functions->glEnableVertexAttribArray(1);
}

void MyGLWidget::paintGL()
{
    // 描画処理
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // 三角形の描画
    glDrawArrays(GL_TRIANGLES, 0, 3);
}

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    MyGLWidget widget;
    widget.resize(500, 500);
    widget.show();

    return app.exec();
}

このコードでは、MyGLWidgetクラスを定義し、initializeGL()paintGL()という2つの仮想関数を実装しています。

  • paintGL()関数では、描画処理を行います。
  • initializeGL()関数では、OpenGLの設定と頂点属性の設定を行います。

このコードを実行すると、赤い、緑色、青色の三角形がウィンドウに描画されます。



glVertexAttribI4v()関数を使用する

glVertexAttribI4v()関数は、glVertexAttribI4iv()関数とほぼ同じですが、整数値の配列をconst GLint *ではなくconst GLint *として渡します。この関数は、古いバージョンのOpenGLでサポートされている可能性があります。

void QOpenGLExtraFunctions::glVertexAttribI4v(GLuint index, const GLint *values);

glVertexAttribPointer()とglVertexAttribIPointer()関数を組み合わせる

glVertexAttribPointer()関数を使用して頂点属性のデータポインタを設定し、glVertexAttribIPointer()関数を使用して頂点属性の整数値を設定することができます。この方法は、古いバージョンのOpenGLでも確実に動作しますが、glVertexAttribI4iv()関数よりも冗長になります。

// 頂点属性のデータポインタを設定
functions->glVertexAttribPointer(0, 3, GL_INT, GL_FALSE, 0, vertices);
functions->glEnableVertexAttribArray(0);

// 頂点属性の整数値を設定
functions->glVertexAttribIPointer(1, 1, GL_INT, GL_FALSE, 0, colors);
functions->glEnableVertexAttribArray(1);

glUniformI4iv()関数を使用する

glUniformI4iv()関数は、ユニフォーム変数に4つの整数値を割り当てるために使用することができます。この関数は、頂点シェーダ内で使用されるデータの配列を指定するために役立ちます。

GLint colors[] = {
  255, 0, 0, 255,
  0, 255, 0, 255,
  0, 0, 255, 255
};

// ユニフォーム変数に整数値を割り当てる
functions->glUniformI4iv(1, 3, colors);

この方法は、頂点属性を使用する代わりに、ユニフォーム変数を使用して頂点シェーダにデータを渡す場合に役立ちます。

頂点データをハードコーディングする

頂点データをシェーダソースコードに直接ハードコーディングすることもできます。これは、頂点データが静的である場合に役立ちますが、頂点データが動的に変化する場合は避けるべきです。

layout(location = 0) in vec3 position;
layout(location = 1) in ivec4 color;

void main() {
  gl_Position = vec4(position, 1.0);
  gl_FragColor = color;
}

// 頂点データ
const GLfloat vertices[] = {
  -1.0f, -1.0f, 0.0f,
  1.0f, -1.0f, 0.0f,
  0.0f, 1.0f, 0.0f
};

const GLint colors[] = {
  255, 0, 0, 255,
  0, 255, 0, 255,
  0, 0, 255, 255
};

この方法は、最も単純な方法ですが、コードの可読性と保守性を低下させる可能性があります。

最適な代替方法の選択

使用する代替方法は、使用しているOpenGLのバージョンと、アプリケーションの要件によって異なります。

  • 頂点データが静的である場合は、頂点データをハードコーディングすることが最良の選択肢となる場合があります。
  • 頂点データをシェーダに動的に渡す必要がある場合は、glUniformI4iv()関数を使用する必要があります。
  • 新しいバージョンのOpenGLを使用している場合は、glVertexAttribI4iv()関数が最適な選択肢です。
  • 古いバージョンのOpenGLを使用している場合は、glVertexAttribI4v()またはglVertexAttribPointer()glVertexAttribIPointer()関数の組み合わせを使用する必要があります。
  • OpenGL Shading Language - Uniform Variables [無効な