opengl
Ładowanie i kompilacja modułu cieniującego
Szukaj…
Wprowadzenie
Te przykłady pokazują różne sposoby ładowania i kompilacji shaderów. Wszystkie przykłady muszą zawierać kod obsługi błędów .
Uwagi
Obiekty glCreateShader
utworzone z glCreateShader
niewiele robią. Zawierają skompilowany kod dla jednego etapu, ale nie muszą nawet zawierać pełnego skompilowanego kodu dla tego etapu. Pod wieloma względami działają jak pliki obiektowe C i C ++.
Obiekty programu zawierają ostatni połączony program. Ale przechowują także stan dla jednolitych wartości programu, a także wielu innych danych stanu. Posiadają interfejsy API do introspekcji danych interfejsu modułu cieniującego (chociaż stało się to kompleksowe w GL 4.3). Obiekty programu definiują kod modułu cieniującego, którego używasz podczas renderowania.
Obiekty modułu cieniującego, kiedyś używane do łączenia programów, nie są już potrzebne, chyba że zamierzasz używać ich do łączenia innych programów.
Załaduj oddzielny moduł cieniujący w C ++
Ten kod ładuje, kompiluje i łączy pojedynczy plik, który tworzy osobny program do cieniowania dla jednego etapu . Jeśli wystąpią błędy, otrzyma dziennik informacji o tych błędach.
Kod wykorzystuje niektóre powszechnie dostępne funkcje 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;
}
Indywidualna kompilacja obiektów cieniujących w C ++
Tradycyjny model kompilacji GLSL polega na kompilowaniu kodu etapu modułu cieniującego w obiekt modułu cieniującego, a następnie łączeniu wielu obiektów modułu cieniującego (obejmujących wszystkie etapy, których chcesz użyć) w jeden obiekt programu.
Od wersji 4.2 można tworzyć obiekty programu, które mają tylko jeden stopień modułu cieniującego. Ta metoda łączy wszystkie etapy modułu cieniującego w jeden program.
Kompilacja obiektów Shader
#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;
}
Łączenie obiektów programu
#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;
}