Pynote

Python、機械学習、画像処理について

Qt - OpenGL の GLSL で描画する。 その2 シェーダーを OpenGL パイプラインにインストールする。

概要

Qt アプリケーション上で OpenGL の GLSL でシェーダーを作成し、描画を行う方法について紹介する。
今回はコンパイルしたシェーダーを OpenGL パイプラインにインストールする部分を紹介する。

試した環境

  • Qt 5.10

資料

手順

プログラムオブジェクトを作成する。

glCreateProgram() でプログラムオブジェクトを作成する。

GLuint glCreateProgram()
  • 返り値
    • 作成したプログラムオブジェクトのハンドラ
    • 成功した場合は 0 以外の整数、失敗した場合は 0
// プログラムオブジェクトを作成する。
programHandle_ = glCreateProgram();
if (programHandle_ == 0) {
    std::cerr << "failed to create the program object." << std::endl;
    exit(1);
}

シェーダーオブジェクトをプログラムオブジェクトにアタッチする。

glAttachShader() でシェーダーオブジェクトをプログラムオブジェクトにアタッチする。

void glAttachShader(GLuint program, GLuint shader)
  • 引数
    • program: プログラムオブジェクトのハンドラ
    • shader: アタッチするシェーダーオブジェクトのハンドラ
// プログラムオブジェクトに頂点シェーダーオブジェクトを追加する。
glAttachShader(programHandle_, vertexShaderHandle);
// プログラムオブジェクトにフラグメントシェーダーオブジェクトを追加する。
glAttachShader(programHandle_, fragmentShaderHandle);

プログラムオブジェクトをリンクする。

glLinkProgram() でプログラムオブジェクトをリンクする。

void glLinkProgram(GLuint program)
  • 引数
    • program: プログラムオブジェクトのハンドラ

リンクに成功したかどうかはプログラムオブジェクトのステータスに設定される。
glGetProgramiv() でこのステータスを取得できる。

void glGetShaderiv(GLuint program, GLenum pname, GLint *params)
  • 引数
    • program: プログラムオブジェクトのハンドラ
    • pname: 取得するパラメータの種類
    • params: 取得するパラメータの値を格納するバッファ

リンクに成功したかどうかのステータスは pname 引数に GL_LINK_STATUS を指定することで取得できる。
result にコンパイルに成功している場合 GL_TRUE、失敗している場合 GL_FALSE が入っている。

シェーダーのコンパイル同様、glGetProgramInfoLog() で詳しいログを取得できる。

void glGetProgramInfoLog(
    GLuint program, GLsizei maxLength, GLsizei *length, GLchar *infoLog)
  • 引数
    • shader: シェーダーオブジェクトのハンドラ
    • maxLength: バッファの長さ
    • length: 取得するログの長さ (\0 を含めない) を格納するバッファ
    • infoLog: 取得するログを格納するバッファ
// プログラムオブジェクトをリンクする。
glLinkProgram(programHandle_);

// リンクに成功したかどうかを取得する。
GLint status;
glGetProgramiv(programHandle_, GL_LINK_STATUS, &status);

// リンクに失敗した場合
if (status == GL_FALSE) {
    std::cerr << "Failed to link the program." << std::endl;

    // ログのある場合、文字列の長さを取得する。
    GLint logLen;
    glGetProgramiv(programHandle_, GL_INFO_LOG_LENGTH, &logLen);

    // ログがある場合
    if (logLen > 0) {
        // ログを格納するバッファを作成する。
        char *log = new char[logLen];
        glGetProgramInfoLog(programHandle_, logLen, NULL, log);

        // ログを取得し、表示する。
        std::cerr << log << std::endl;

        // ログを格納するバッファを削除する。
        delete log;
    }
    exit(1);
}

プログラムオブジェクトをインストールする。

glUseProgram() でプログラムオブジェクトを OpenGL パイプラインにインストールする。

void glUseProgram(GLuint program);
  • 引数
    • program: プログラムオブジェクトのハンドラ
// プログラムオブジェクトをインストールする。
glUseProgram(programHandle_);