// shader_utils.h #ifndef SHADER_UTILS_H #define SHADER_UTILS_H #include #if defined(IMGUI_IMPL_OPENGL_ES2) #include #else #include #include #endif GLuint LoadShaderProgram(const std::string& vsSource, const std::string& fsSource); GLuint LoadShaderProgramFromFiles(const std::string& vsPath, const std::string& fsPath); #endif // SHADER_UTILS_H #include #include #include #include // Function to compile a shader GLuint CompileShader(GLenum type, const std::string& source) { GLuint shader = glCreateShader(type); const char* src = source.c_str(); glShaderSource(shader, 1, &src, nullptr); glCompileShader(shader); GLint success; glGetShaderiv(shader, GL_COMPILE_STATUS, &success); if (!success) { GLint logLength; glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength); std::vector log(logLength); glGetShaderInfoLog(shader, logLength, nullptr, log.data()); std::cerr << "ERROR::SHADER::COMPILATION_FAILED\n" << (type == GL_VERTEX_SHADER ? "Vertex" : "Fragment") << "\n" << log.data() << std::endl; glDeleteShader(shader); return 0; } return shader; } // Function to link shaders into a program GLuint LinkProgram(GLuint vertexShader, GLuint fragmentShader) { GLuint program = glCreateProgram(); glAttachShader(program, vertexShader); glAttachShader(program, fragmentShader); glLinkProgram(program); GLint success; glGetProgramiv(program, GL_LINK_STATUS, &success); if (!success) { GLint logLength; glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength); std::vector log(logLength); glGetProgramInfoLog(program, logLength, nullptr, log.data()); std::cerr << "ERROR::PROGRAM::LINKING_FAILED\n" << log.data() << std::endl; glDeleteProgram(program); return 0; } return program; } GLuint LoadShaderProgram(const std::string& vsSource, const std::string& fsSource) { GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource); if (!vs) return 0; GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource); if (!fs) { glDeleteShader(vs); return 0; } GLuint program = LinkProgram(vs, fs); // Shaders can be deleted after linking glDeleteShader(vs); glDeleteShader(fs); return program; } std::string ReadFile(const std::string& path) { std::ifstream file(path); if (!file) { std::cerr << "Error opening file: " << path << std::endl; return ""; } std::stringstream buffer; buffer << file.rdbuf(); return buffer.str(); } GLuint LoadShaderProgramFromFiles(const std::string& vsPath, const std::string& fsPath) { std::string vsSource = ReadFile(vsPath); std::string fsSource = ReadFile(fsPath); if (vsSource.empty() || fsSource.empty()) { return 0; } return LoadShaderProgram(vsSource, fsSource); }