opengl
Shader-Laden und Zusammenstellung
Suche…
Einführung
Diese Beispiele zeigen verschiedene Möglichkeiten zum Laden und Kompilieren von Shadern. Alle Beispiele müssen Fehlerbehandlungscode enthalten .
Bemerkungen
Shader-Objekte, wie sie mit glCreateShader
sind nicht besonders glCreateShader
. Sie enthalten den kompilierten Code für eine einzelne Stufe, aber sie müssen nicht einmal den vollständigen kompilierten Code für diese Stufe enthalten. In vielerlei Hinsicht funktionieren sie wie C- und C ++ - Objektdateien.
Programmobjekte enthalten das endgültige verknüpfte Programm. Sie enthalten aber auch den Status für die einheitlichen Werte des Programms sowie eine Reihe anderer Statusdaten. Sie verfügen über APIs für die Introspektion der Schnittstellendaten des Shaders (obwohl sie erst in GL 4.3 umfassend wurden). Programmobjekte definieren den Shader-Code, den Sie beim Rendern verwenden.
Shader-Objekte, die einmal zum Verknüpfen eines Programms verwendet wurden, werden nicht mehr benötigt, es sei denn, Sie möchten damit andere Programme verknüpfen.
Separable Shader in C ++ laden
Dieser Code lädt, kompiliert und verknüpft eine einzelne Datei, die ein separates Shader-Programm für eine einzelne Stufe erstellt . Bei Fehlern wird das Info-Protokoll für diese Fehler abgerufen.
Der Code verwendet einige allgemein verfügbare C ++ 11-Funktionen.
#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;
}
Einzelne Shader-Objekt-Kompilierung in C ++
Das traditionelle GLSL-Kompilierungsmodell umfasst das Kompilieren von Code für eine Shader-Stufe in ein Shader-Objekt. Anschließend werden mehrere Shader-Objekte (die alle zu verwendenden Stufen umfassen) in einem einzigen Programmobjekt verknüpft.
Seit 4.2 können Programmobjekte erstellt werden, die nur eine Shader-Stufe haben. Diese Methode verknüpft alle Shader-Stufen in einem einzigen Programm.
Shader-Objektzusammenstellung
#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;
}
Programmobjektverknüpfung
#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;
}