Загрузчик шейдеров OpenGL в C ++

Я сделал свой собственный загрузчик шейдеров 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 ответ
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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *