opengl
Shader-laddning och kompilering
Sök…
Introduktion
Dessa exempel visar olika sätt att ladda och sammanställa skuggmaskiner. Alla exempel måste innehålla felhanteringskod .
Anmärkningar
Shader-objekt, som skapats från glCreateShader
gör inte mycket. De innehåller den sammanställda koden för ett enda steg, men de behöver inte ens innehålla den fullständiga kompilerade koden för det steget. På många sätt fungerar de som C- och C ++ -objektfiler.
Programobjekt innehåller det slutliga länkade programmet. Men de har också tillståndet för programmets enhetliga värden, liksom ett antal andra tillståndsdata. De har API: er för introspektering av skuggarens gränssnittsdata (även om de bara blev omfattande i GL 4.3). Programobjekt är det som definierar skuggningskoden som du använder vid rendering.
Shader-objekt, som en gång har använts för att länka ett program, behövs inte längre om du inte tänker använda dem för att länka andra program.
Ladda Separable Shader i C ++
Denna kod laddar, sammanställer och länkar en enda fil som skapar ett separat skuggningsprogram för ett enda steg . Om det finns fel, kommer det att få infologgen för dessa fel.
Koden använder någon vanligt tillgänglig C ++ 11-funktionalitet.
#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;
}
Individuell Shader Object Compilation i C ++
Den traditionella GLSL-kompilationsmodellen innebär att man sammanställer kod för ett shader-steg till ett shader-objekt och kopplar sedan flera shader-objekt (som täcker alla de steg du vill använda) till ett enda programobjekt.
Sedan 4.2 kan programobjekt skapas som bara har ett skuggningssteg. Denna metod länkar alla skuggningssteg till ett enda program.
Shader Object Compilation
#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;
}
Programobjektlänk
#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;
}