opengl
셰이더로드 및 컴파일
수색…
소개
이 예제는 셰이더를로드하고 컴파일하는 다양한 방법을 보여줍니다. 모든 예제 에는 오류 처리 코드가 포함되어야합니다 .
비고
glCreateShader
에서 생성 된 Shader 객체는 그다지 glCreateShader
이지 않습니다. 단일 스테이지에 대해 컴파일 된 코드가 포함되어 있지만 해당 스테이지의 전체 컴파일 된 코드를 포함 할 필요조차 없습니다. 여러면에서 C 및 C ++ 오브젝트 파일과 같이 작동합니다.
프로그램 개체에는 마지막으로 링크 된 프로그램이 들어 있습니다. 그러나 그들은 또한 프로그램의 유니폼 값에 대한 상태뿐만 아니라 여러 다른 상태 데이터를 보유합니다. 그들은 셰이더의 인터페이스 데이터를 인트로 스팅하기위한 API를 가지고 있습니다 (GL 4.3에서 포괄적으로되었지만). 프로그램 개체는 렌더링 할 때 사용하는 셰이더 코드를 정의합니다.
한 번 프로그램을 연결하는 데 사용 된 셰이더 개체는 다른 프로그램을 연결하는 데 사용하지 않으면 더 이상 필요하지 않습니다.
C ++에서 분리 가능한 셰이더로드
이 코드 는 단일 스테이지에 대해 별도의 셰이더 프로그램을 만드는 단일 파일을로드, 컴파일 및 연결합니다. 오류가 있으면 해당 오류에 대한 정보 로그를 얻습니다.
이 코드는 일반적으로 사용 가능한 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 컴파일 모델은 셰이더 스테이지에 대한 코드를 셰이더 개체로 컴파일 한 다음 여러 셰이더 개체 (사용하려는 모든 스테이지를 포함)를 단일 프로그램 개체로 연결하는 작업을 포함합니다.
4.2부터 하나의 셰이더 단계 만있는 프로그램 개체를 만들 수 있습니다. 이 메서드는 모든 쉐이더 스테이지를 단일 프로그램에 연결합니다.
셰이더 개체 컴파일
#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;
}