Qt GUIにおける頂点属性操作:QOpenGLExtraFunctions::glVertexAttribI4i()徹底解説


QOpenGLExtraFunctions::glVertexAttribI4i() 関数は、OpenGL Shading Language (GLSL) プログラム内で頂点属性に整数値 4 つを設定するために使用されます。これは、Qt GUI アプリケーションで OpenGL 3.x または 4.x を使用する際に役立ちます。

関数詳細

void QOpenGLExtraFunctions::glVertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w);
  • x, y, z, w: 設定する 4 つの整数値
  • index: 設定する頂点属性のインデックス

使い方

  1. QOpenGLContext オブジェクトを作成し、現在のコンテキストとして設定します。
  2. QOpenGLExtraFunctions オブジェクトを作成し、initializeOpenGLFunctions() 関数を呼び出してコンテキストを初期化します。
  3. glVertexAttribI4i() 関数を呼び出して、頂点属性に値を設定します。

QOpenGLContext context;
context.create();
context.makeCurrent();

QOpenGLExtraFunctions functions;
functions.initializeOpenGLFunctions(&context);

functions.glVertexAttribI4i(0, 1, 2, 3, 4);

この例では、index 0 の頂点属性に (1, 2, 3, 4) という整数値 4 つが設定されます。

  • 頂点属性のデータ型は GLint であり、-2^31 から 2^31 - 1 までの範囲の整数値を格納できます。
  • 頂点属性は、シェーダー内で layout(location = index) で宣言する必要があります。
  • glVertexAttribI4i() 関数は OpenGL ES 3.x または OpenGL 3.x 以上のコンテキストでのみ使用できます。
  • OpenGL は複雑な API であり、習得するには時間がかかります。詳細については、公式ドキュメントを参照することをお勧めします。
  • この説明は、Qt GUI 6.7.1 を基にしています。他のバージョンでは、関数の名前や引数が異なる場合があります。


コード

#include <QApplication>
#include <QOpenGLWidget>
#include <QOpenGLExtraFunctions>

class MyGLWidget : public QOpenGLWidget {
public:
    MyGLWidget() {
        setFormat(QOpenGLWidget::OpenGL30Format);
    }

protected:
    void initializeGL() override {
        QOpenGLExtraFunctions functions;
        functions.initializeOpenGLFunctions();

        // 頂点シェーダー
        const char *vertexShaderSource =
            "#version 330\n"
            "layout(location = 0) in vec3 vertexPosition;\n"
            "layout(location = 1) in vec4 vertexColor;\n"
            "out vec4 fragColor;\n"
            "void main() {\n"
            "    fragColor = vertexColor;\n"
            "    gl_Position = vec4(vertexPosition, 1.0);\n"
            "}\n";

        // フラグメントシェーダー
        const char *fragmentShaderSource =
            "#version 330\n"
            "out vec4 FragColor;\n"
            "void main() {\n"
            "    FragColor = vec4(1.0, 0.5, 0.25, 1.0);\n"
            "}\n";

        // シェーダープログラムの作成
        GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
        glCompileShader(vertexShader);

        GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
        glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
        glCompileShader(fragmentShader);

        GLuint shaderProgram = glCreateProgram();
        glAttachShader(shaderProgram, vertexShader);
        glAttachShader(shaderProgram, fragmentShader);
        glLinkProgram(shaderProgram);

        glUseProgram(shaderProgram);

        // 頂点バッファの作成
        GLfloat vertices[] = {
            0.0f, 0.5f, 0.0f, // 頂点 1 (赤)
            0.5f, -0.5f, 0.0f, // 頂点 2 (緑)
            -0.5f, -0.5f, 0.0f  // 頂点 3 (青)
        };

        GLuint vbo;
        glGenBuffers(1, &vbo);
        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

        // 頂点属性の設定
        functions.glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (void*)0);
        glEnableVertexAttribArray(0);

        // 頂点色の設定
        GLfloat colors[] = {
            1.0f, 0.0f, 0.0f, 1.0f, // 赤
            0.0f, 1.0f, 0.0f, 1.0f, // 緑
            0.0f, 0.0f, 1.0f, 1.0f  // 青
        };

        GLuint cbo;
        glGenBuffers(1, &cbo);
        glBindBuffer(GL_ARRAY_BUFFER, cbo);
        glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);

        functions.glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (void*)0);
        glEnableVertexAttribArray(1);
    }

    void paintGL() override {
        glDrawArrays(GL_TRIANGLES, 0, 3);
    }
};

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

    MyGLWidget widget;
    widget.show();

    return app.exec();
}
  1. MyGLWidget クラスを定義します。このクラスは QOpenGLWidget を継承し、


代替方法

  1. glVertexAttribI4bv() 関数を使用する

glVertexAttribI4bv() 関数は、glVertexAttribI4i() 関数とほぼ同じ機能を備えていますが、整数値を配列として渡すことができます。これは、複数の頂点属性に同時に値を設定する場合に便利です。

void QOpenGLExtraFunctions::glVertexAttribI4bv(GLuint index, const GLint *values);
  1. glUniform4i() 関数を使用する

glUniform4i() 関数は、ユニフォーム変数に 4 つの整数値を設定するために使用されます。頂点属性に値を設定するには、まずユニフォーム変数を宣言し、glVertexAttribPointer() 関数を使用して頂点属性とユニフォーム変数を関連付ける必要があります。

GLint values[] = { 1, 2, 3, 4 };

glUniform4i(uniformLocation, values[0], values[1], values[2], values[3]);
  1. glVertexAttribPointer() 関数と glVertexAttrib1i() 関数を使用する

この方法は、より複雑ですが、より古いバージョンの OpenGL でも使用できます。まず、glVertexAttribPointer() 関数を使用して頂点属性をデータ配列に関連付けます。次に、glVertexAttrib1i() 関数を使用して、各頂点属性に個別に整数値を設定します。

GLint values[] = { 1, 2, 3, 4 };

glVertexAttribPointer(0, 1, GL_INT, GL_FALSE, 0, values);

glEnableVertexAttribArray(0);

for (int i = 0; i < 3; i++) {
    glVertexAttrib1i(0, values[i]);
    glDrawArrays(GL_TRIANGLES, i, 1);
}
  • 古いバージョンの OpenGL では、すべての機能がサポートされない場合があります。
  • これらの代替方法は、glVertexAttribI4i() 関数よりもパフォーマンスが低いかもしれません。