opengl
シェーダのロードとコンパイル
サーチ…
前書き
これらの例は、シェーダをロードおよびコンパイルするさまざまな方法を示しています。すべての例にエラー処理コードが含まれている必要があります 。
備考
glCreateShader
から作成されたShaderオブジェクトはあまりglCreateShader
しません。それらには単一のステージ用にコンパイルされたコードが含まれていますが、そのステージ用の完全なコンパイル済みコードを含む必要はありません。多くの点で、CおよびC ++オブジェクトファイルのように動作します。
プログラムオブジェクトには、最後にリンクされたプログラムが含まれます。しかし、彼らはまた、プログラムの一様な値のための状態と、他の多くの状態データを保持します。彼らはシェーダのインターフェイスデータをイントロスペクションするためのAPIを持っています(ただしGL 4.3では包括的になっています)。プログラムオブジェクトは、レンダリング時に使用するシェーダコードを定義するものです。
シェーダオブジェクトは、一旦プログラムをリンクするために使用されると、他のプログラムをリンクするために使用しない限り、もはや必要ありません。
C ++で分離可能シェーダをロードする
このコードは、 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;
}