サーチ…


前書き

これらの例は、シェーダをロードおよびコンパイルするさまざまな方法を示しています。すべての例にエラー処理コードが含まれている必要があります

備考

glCreateShaderから作成されたShaderオブジェクトはあまりglCreateShaderしません。それらには単一のステージ用にコンパイルされたコードが含まれていますが、そのステージ用の完全なコンパイル済みコードを含む必要はありません。多くの点で、CおよびC ++オブジェクトファイルのように動作します。

プログラムオブジェクトには、最後にリンクされたプログラムが含まれます。しかし、彼らはまた、プログラムの一様な値のための状態と、他の多くの状態データを保持します。彼らはシェーダのインターフェイスデータをイントロスペクションするためのAPIを持っています(ただしGL 4.3では包括的になっています)。プログラムオブジェクトは、レンダリング時に使用するシェーダコードを定義するものです。

シェーダオブジェクトは、一旦プログラムをリンクするために使用されると、他のプログラムをリンクするために使用しない限り、もはや必要ありません。

C ++で分離可能シェーダをロードする

4.1

このコードは、 1つのステージに対して別々のシェーダプログラムを作成する1つのファイルをロード、コンパイル、リンクします。エラーがある場合、それらのエラーの情報ログを取得します。

このコードでは、一般的に利用可能なC ++ 11の機能をいくつか使用しています。

#include <string>
#include <fstream>

//In C++17, we could take a `std::filesystem::path` instead of a std::string
//for the filename.
GLuint CreateSeparateProgram(GLenum stage, const std::string &filename)
{
    std::ifstream input(filename.c_str(), std::ios::in | std::ios::binary | std::ios::ate);
    
    //Figure out how big the file is.
    auto fileSize = input.tellg();
    input.seekg(0, ios::beg);
    
    //Read the whole file.
    std::string fileData(fileSize);
    input.read(&fileData[0], fileSize);
    input.close();
    
    //Compile&link the file
    auto fileCstr = (const GLchar *)fileData.c_str();
    auto program = glCreateShaderProgramv(stage, 1, &fileCstr);

    //Check for errors
    GLint isLinked = 0;
    glGetProgramiv(program, GL_LINK_STATUS, &isLinked);
    if(isLinked == GL_FALSE)
    {
        //Note: maxLength includes the NUL terminator.
        GLint maxLength = 0;
        glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);        

        //C++11 does not permit you to overwrite the NUL terminator,
        //even if you are overwriting it with the NUL terminator.
        //C++17 does, so you could subtract 1 from the length and skip the `pop_back`.
        std::basic_string<GLchar> infoLog(maxLength);
        glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);
        infoLog.pop_back();

        //The program is useless now. So delete it.
        glDeleteProgram(program);

        //Use the infoLog in whatever manner you deem best.

        //Exit with failure.
        return 0;
    }
    
    return program;
}

C ++での個々のシェーダオブジェクトのコンパイル

従来のGLSLコンパイルモデルでは、シェーダステージのコードをシェーダオブジェクトにコンパイルし、複数のシェーダオブジェクト(使用するすべてのステージをカバーする)を1つのプログラムオブジェクトにリンクします。

4.2以降、1つのシェーダステージのみを持つプログラムオブジェクトを作成できます。このメソッドは、すべてのシェーダステージを1つのプログラムにリンクします。

シェーダオブジェクトのコンパイル

#include <string>
#include <fstream>

//In C++17, we could take a `std::filesystem::path` instead of a std::string
//for the filename.
GLuint CreateShaderObject(GLenum stage, const std::string &filename)
{
    std::ifstream input(filename.c_str(), std::ios::in | std::ios::binary | std::ios::ate);
    
    //Figure out how big the file is.
    auto fileSize = input.tellg();
    input.seekg(0, ios::beg);
    
    //Read the whole file.
    std::string fileData(fileSize);
    input.read(&fileData[0], fileSize);
    input.close();
    
    //Create a shader name
    auto shader = glCreateShader(stage);

    //Send the shader source code to GL
    auto fileCstr = (const GLchar *)fileData.c_str();
    glShaderSource(shader, 1, &fileCstr, nullptr);

    //Compile the shader
    glCompileShader(shader);

    GLint isCompiled = 0;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled);
    if(isCompiled == GL_FALSE)
    {
        GLint maxLength = 0;
        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);

        //C++11 does not permit you to overwrite the NUL terminator,
        //even if you are overwriting it with the NUL terminator.
        //C++17 does, so you could subtract 1 from the length and skip the `pop_back`.
        std::basic_string<GLchar> infoLog(maxLength);
        glGetShaderInfoLog(shader, maxLength, &maxLength, &infoLog[0]);
        infoLog.pop_back();

        //We don't need the shader anymore.
        glDeleteShader(shader);

        //Use the infoLog as you see fit.
        
        //Exit with failure.
        return 0;
    }

    return shader;
}

プログラムオブジェクトのリンク

#include <string>

GLuint LinkProgramObject(vector<GLuint> shaders)
{
    //Get a program object.
    auto program = glCreateProgram();

    //Attach our shaders to our program
    for(auto shader : shaders)
        glAttachShader(program, shader);

    //Link our program
    glLinkProgram(program);

    //Note the different functions here: glGetProgram* instead of glGetShader*.
    GLint isLinked = 0;
    glGetProgramiv(program, GL_LINK_STATUS, (int *)&isLinked);
    if(isLinked == GL_FALSE)
    {
        GLint maxLength = 0;
        glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);

        //C++11 does not permit you to overwrite the NUL terminator,
        //even if you are overwriting it with the NUL terminator.
        //C++17 does, so you could subtract 1 from the length and skip the `pop_back`.
        std::basic_string<GLchar> infoLog(maxLength);
        glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);
        infoLog.pop_back();
        
        //We don't need the program anymore.
        glDeleteProgram(program);

        //Use the infoLog as you see fit.
        
        //Exit with failure
        return 0;
    }

    //Always detach shaders after a successful link.
    for(auto shader : shaders)
        gldetachShader(program, shader);
        
    return program;
}


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow