Я сделал свой собственный загрузчик шейдеров OpenGL для C ++. Скажите, пожалуйста, я что-то делаю неправильно или что-то нужно улучшить. Я тестировал это, и он отлично работает.
main.cc
std::vector<ShaderInfo> shader_info {
{GL_VERTEX_SHADER, "shader.vert"},
{GL_FRAGMENT_SHADER, "shader.frag"}
};
GLuint shader_program {LoadShaders(shader_info)};
glUseProgram(shader_program);
шейдер-загрузчик.hh
struct ShaderInfo {
GLenum type;
std::string file;
};
GLuint LoadShaders(const std::vector<ShaderInfo>&);
shader-loader.cc
GLuint LoadShaders(const std::vector<ShaderInfo>& shader_info) {
GLuint program {glCreateProgram()};
std::vector<GLuint> detach;
for (auto info : shader_info) {
std::ifstream file {info.file, std::ios_base::in};
file.seekg(0, std::ios_base::end);
std::string source(file.tellg(), ' ');
file.seekg(0, std::ios_base::beg);
file.read(&source[0], source.size());
file.close();
GLuint shader {glCreateShader(info.type)};
GLchar* source_ptr {&source[0]};
glShaderSource(shader, 1, &source_ptr, nullptr);
glCompileShader(shader);
glAttachShader(program, shader);
glDeleteShader(shader);
detach.push_back(shader);
GLint status;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE) {
GLint length;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
std::string log(length, ' ');
glGetShaderInfoLog(shader, length, nullptr, &log[0]);
glDeleteProgram(program);
throw std::runtime_error(log);
}
}
glLinkProgram(program);
for (auto shader : detach)
glDetachShader(program, shader);
GLint status;
glGetProgramiv(program, GL_LINK_STATUS, &status);
if (status == GL_FALSE) {
GLint length;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
std::string log(length, ' ');
glGetProgramInfoLog(program, length, nullptr, &log[0]);
glDeleteProgram(program);
throw std::runtime_error(log);
}
return program;
}
`````
1 ответ
for (auto info : shader_info)->for (auto const& info : shader_info)чтобы избежать копирования строки.Считывание исходного файла в строку, вероятно, должно быть отдельной функцией.
Мы должны выдать ошибку, если файл не открывается. (
tellgвернусь-1в таком случае).Я считаю, что часто бывает полезно вывести более одного журнала объектов шейдера перед остановкой компиляции (например, если у нас есть небольшая ошибка в вершинном шейдере и еще одна в шейдере фрагмента, мы можем увидеть и исправить обе сразу, а не только наличие ошибки вершинного шейдера в журнале).
например:
GLuint LoadShaders(const std::vector<ShaderInfo>& shader_info) {
// ...
bool compiled = true; // flag to indicate overall compile status
for (auto const& info : shader_info) {
// ... read file and compile shader
GLint status;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE) {
// ... get log string
// log the error (if you have an existing logging system, or print to std::cerr)
LogError("glCompileShader() failed for shader object: " + info.file);
LogError(log);
compiled = false; // set the overall flag to false
}
}
// and now we throw!
if (!compiled) {
glDeleteProgram(program);
throw std::runtime_error("Shader compilation failed!");
}
// ... link program etc. as before
}

Как мне объединить логи компиляции двух шейдеров?
— Десмонд Роудс
Отредактировано, чтобы показать, что я имею в виду. Это зависит от того, как вы регистрируете вещи. Это действительно просто перемещение
throwнемного позже.— user673679