Skip to main content
Rollback to Revision 1
Source Link
std::stringGLuint LoadFileLoadShaders(const std::string const&vector<ShaderInfo>& nameshader_info) {
    GLuint program {glCreateProgram()};
    std::ifstreamvector<GLuint> file;detach;

    file.exceptionsfor (std:auto info :ios_base shader_info) {
        std::failbitifstream |file {info.file, std::ios_base::badbit)in};
 
    file.open(name);
    file.seekg(0, std::ios_base::end);
        std::string contentsource(file.tellg(), '\0');

        file.seekg(0, std::ios_base::beg);
    file.read(&content[0], content.size());
    file.closeread();

    return content;
}

GLuint&source[0], LoadShaderssource.size(std::vector<ShaderInfo> const& shader_info) {
    GLuint program {glCreateProgram()};
    if (!program)
        throw std::runtime_errorfile.close("cannot acquire id for shader program");

    std::vector<GLuint> detach;
    std::string log;

    for (auto const& info : shader_info) {
        GLuint shader {glCreateShader(info.type)};
        if (glGetError()GLchar* ==source_ptr GL_INVALID_ENUM){&source[0]};
            log += "[" + info.file + "] invalid glShaderSource(shader type\n";
       , else1, if&source_ptr, (!shadernullptr);
            log += "[" + info.file + "] cannot acquire id\n";
        else try {glCompileShader(shader);
            glAttachShader(program, shader);
            glDeleteShader(shader);
            detach.push_back(shader);

            std::string source {LoadFile(info.file)};
            GLchar* source_ptr(&source[0]);
            glShaderSource(shader, 1, &source_ptr, nullptr);

            glCompileShader(shader);
            GLint status;
            glGetShaderiv(shader, GL_COMPILE_STATUS, &status);

            if (status == GL_FALSE) {
                GLint length;
                glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);

                log += "[" + info.file + "]\n";
                auto offset {log.size()};

               std::string log.resize(offset + length, '\0');
                glGetShaderInfoLog(shader, length, nullptr, &log[offset]&log[0]);
     
            log.resize(log.sizeglDeleteProgram() - 1program);
            }
        }
        catchthrow (std::ios_base::failure const&) {
            runtime_error(log += "[" + info.file + "] cannot process file\n";);
        }
    }

    if (log.size()) {
        glDeleteProgramglLinkProgram(program);
      for (auto throwshader std::runtime_error(log detach);
    }

    glLinkProgramglDetachShader(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.resize(length, '\0');
        glGetProgramInfoLog(program, length, nullptr, &log[0]);

        glDeleteProgram(program);
        throw std::runtime_error(log);
    }

    for (auto shader : detach)
        glDetachShader(program, shader);
    return program;
}
`````

EDIT 1: Incorporated user673679 suggestions.

  • Split reading source file into another function.
  • Error on failure opening a file.
  • Combine logs from multiple shader objects compilation attempts.
  • Plus added some extra OpenGL error checks.

I tried my best to make the code not too messy to read.

std::string LoadFile(std::string const& name) {
    std::ifstream file;
    file.exceptions(std::ios_base::failbit | std::ios_base::badbit);
 
    file.open(name);
    file.seekg(0, std::ios_base::end);
    std::string content(file.tellg(), '\0');

    file.seekg(0, std::ios_base::beg);
    file.read(&content[0], content.size());
    file.close();

    return content;
}

GLuint LoadShaders(std::vector<ShaderInfo> const& shader_info) {
    GLuint program {glCreateProgram()};
    if (!program)
        throw std::runtime_error("cannot acquire id for shader program");

    std::vector<GLuint> detach;
    std::string log;

    for (auto const& info : shader_info) {
        GLuint shader {glCreateShader(info.type)};
        if (glGetError() == GL_INVALID_ENUM)
            log += "[" + info.file + "] invalid shader type\n";
        else if (!shader)
            log += "[" + info.file + "] cannot acquire id\n";
        else try {
            glAttachShader(program, shader);
            glDeleteShader(shader);
            detach.push_back(shader);

            std::string source {LoadFile(info.file)};
            GLchar* source_ptr(&source[0]);
            glShaderSource(shader, 1, &source_ptr, nullptr);

            glCompileShader(shader);
            GLint status;
            glGetShaderiv(shader, GL_COMPILE_STATUS, &status);

            if (status == GL_FALSE) {
                GLint length;
                glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);

                log += "[" + info.file + "]\n";
                auto offset {log.size()};

                log.resize(offset + length);
                glGetShaderInfoLog(shader, length, nullptr, &log[offset]);
                log.resize(log.size() - 1);
            }
        }
        catch (std::ios_base::failure const&) {
            log += "[" + info.file + "] cannot process file\n";
        }
    }

    if (log.size()) {
        glDeleteProgram(program);
        throw std::runtime_error(log);
    }

    glLinkProgram(program);
    GLint status;
    glGetProgramiv(program, GL_LINK_STATUS, &status);

    if (status == GL_FALSE) {
        GLint length;
        glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);

        log.resize(length);
        glGetProgramInfoLog(program, length, nullptr, &log[0]);

        glDeleteProgram(program);
        throw std::runtime_error(log);
    }

    for (auto shader : detach)
        glDetachShader(program, shader);
    return program;
}

EDIT 1: Incorporated user673679 suggestions.

  • Split reading source file into another function.
  • Error on failure opening a file.
  • Combine logs from multiple shader objects compilation attempts.
  • Plus added some extra OpenGL error checks.

I tried my best to make the code not too messy to read.

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(), '\0');

        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, '\0');
            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, '\0');
        glGetProgramInfoLog(program, length, nullptr, &log[0]);

        glDeleteProgram(program);
        throw std::runtime_error(log);
    }

    return program;
}
`````
added 1137 characters in body
Source Link
GLuintstd::string LoadShadersLoadFile(const std::vector<ShaderInfo>&string shader_infoconst& name) {
    GLuint program {glCreateProgram()};
    std::vector<GLuint>ifstream detach;
file;
    for file.exceptions(auto info : shader_info) {
        std::ifstream fileios_base::failbit {info.file,| std::ios_base::in}badbit); 

    file.open(name);
    file.seekg(0, std::ios_base::end);
        std::string sourcecontent(file.tellg(), '\0');

        file.seekg(0, std::ios_base::beg);
        file.read(&source[0]&content[0], sourcecontent.size());
    file.close();

    file.closereturn content;
}

GLuint LoadShaders(std::vector<ShaderInfo> const& shader_info) {
    GLuint program {glCreateProgram()};
    if (!program)
        throw std::runtime_error("cannot acquire id for shader program");

    std::vector<GLuint> detach;
    std::string log;

    for (auto const& info : shader_info) {
        GLuint shader {glCreateShader(info.type)};
        GLchar*if source_ptr(glGetError() {&source[0]};== GL_INVALID_ENUM)
        glShaderSource(shader, 1, &source_ptr, nullptr);
 log += "[" + info.file + "] invalid shader type\n";
        glCompileShaderelse if (!shader);
            log += "[" + info.file + "] cannot acquire id\n";
        else try {
            glAttachShader(program, shader);
            glDeleteShader(shader);
            detach.push_back(shader);

            std::string source {LoadFile(info.file)};
            GLchar* source_ptr(&source[0]);
            glShaderSource(shader, 1, &source_ptr, nullptr);

            glCompileShader(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 += "[" + info.file + "]\n";
                auto offset {log.size(length,)};

 '\0'               log.resize(offset + length);
                glGetShaderInfoLog(shader, length, nullptr, &log[0]&log[offset]);
 
            glDeleteProgram    log.resize(programlog.size() - 1);
            throw}
        }
        catch (std::runtime_error(logios_base::failure const&); {
            log += "[" + info.file + "] cannot process file\n";
        }
    }

    glLinkProgramif (log.size()) {
        glDeleteProgram(program);
    for (auto shader : detachthrow std::runtime_error(log);
    }

    glDetachShaderglLinkProgram(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.resize(length, '\0');
        glGetProgramInfoLog(program, length, nullptr, &log[0]);

        glDeleteProgram(program);
        throw std::runtime_error(log);
    }

    for (auto shader : detach)
        glDetachShader(program, shader);
    return program;
}
`````

EDIT 1: Incorporated user673679 suggestions.

  • Split reading source file into another function.
  • Error on failure opening a file.
  • Combine logs from multiple shader objects compilation attempts.
  • Plus added some extra OpenGL error checks.

I tried my best to make the code not too messy to read.

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(), '\0');

        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, '\0');
            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, '\0');
        glGetProgramInfoLog(program, length, nullptr, &log[0]);

        glDeleteProgram(program);
        throw std::runtime_error(log);
    }

    return program;
}
`````
std::string LoadFile(std::string const& name) {
    std::ifstream file;
    file.exceptions(std::ios_base::failbit | std::ios_base::badbit); 

    file.open(name);
    file.seekg(0, std::ios_base::end);
    std::string content(file.tellg(), '\0');

    file.seekg(0, std::ios_base::beg);
    file.read(&content[0], content.size());
    file.close();

    return content;
}

GLuint LoadShaders(std::vector<ShaderInfo> const& shader_info) {
    GLuint program {glCreateProgram()};
    if (!program)
        throw std::runtime_error("cannot acquire id for shader program");

    std::vector<GLuint> detach;
    std::string log;

    for (auto const& info : shader_info) {
        GLuint shader {glCreateShader(info.type)};
        if (glGetError() == GL_INVALID_ENUM)
            log += "[" + info.file + "] invalid shader type\n";
        else if (!shader)
            log += "[" + info.file + "] cannot acquire id\n";
        else try {
            glAttachShader(program, shader);
            glDeleteShader(shader);
            detach.push_back(shader);

            std::string source {LoadFile(info.file)};
            GLchar* source_ptr(&source[0]);
            glShaderSource(shader, 1, &source_ptr, nullptr);

            glCompileShader(shader);
            GLint status;
            glGetShaderiv(shader, GL_COMPILE_STATUS, &status);

            if (status == GL_FALSE) {
                GLint length;
                glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);

                log += "[" + info.file + "]\n";
                auto offset {log.size()};

                log.resize(offset + length);
                glGetShaderInfoLog(shader, length, nullptr, &log[offset]);
                log.resize(log.size() - 1);
            }
        }
        catch (std::ios_base::failure const&) {
            log += "[" + info.file + "] cannot process file\n";
        }
    }

    if (log.size()) {
        glDeleteProgram(program);
        throw std::runtime_error(log);
    }

    glLinkProgram(program);
    GLint status;
    glGetProgramiv(program, GL_LINK_STATUS, &status);

    if (status == GL_FALSE) {
        GLint length;
        glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);

        log.resize(length);
        glGetProgramInfoLog(program, length, nullptr, &log[0]);

        glDeleteProgram(program);
        throw std::runtime_error(log);
    }

    for (auto shader : detach)
        glDetachShader(program, shader);
    return program;
}

EDIT 1: Incorporated user673679 suggestions.

  • Split reading source file into another function.
  • Error on failure opening a file.
  • Combine logs from multiple shader objects compilation attempts.
  • Plus added some extra OpenGL error checks.

I tried my best to make the code not too messy to read.

Source Link

OpenGL Shader Loader in C++

I made my own custom OpenGL shader loader for C++. Please tell me is I'm doing anything incorrectly or anything to improve on. I've tested this and it works perfectly fine.

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);

shader-loader.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(), '\0');

        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, '\0');
            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, '\0');
        glGetProgramInfoLog(program, length, nullptr, &log[0]);

        glDeleteProgram(program);
        throw std::runtime_error(log);
    }

    return program;
}
`````