#ifndef SHADER_H #define SHADER_H #include "data/Array.h" #include "data/List.h" #include "math/Matrix.h" #include "rendering/GL.h" #include "utils/Error.h" class Shader final { static constexpr int MAX_SHADERS = 5; Array shaders; GL::Program program; public: Shader(); ~Shader(); Shader(const Shader& other) = delete; Shader(Shader&& other) = delete; Shader& operator=(const Shader& other) = delete; Shader& operator=(Shader&& other) = delete; template Error compile(Args&&... args) { const int size = sizeof...(args); const char* paths[static_cast(size)] = {args...}; static_assert(size <= MAX_SHADERS, "too much shaders paths given"); for(int i = 0; i < size; i++) { GL::ShaderType type = getShaderType(paths[i]); if(type == GL::ShaderType::INVALID) { Error error = {"'"}; error.message.append(paths[i]).append( "' is not a valid shader type"); return error; } Error error = readAndCompile(paths[i], shaders[i], type); if(error.has()) { return error; } } program = GL::createProgram(); for(GL::Shader shader : shaders) { if(shader != 0) { GL::attachShader(program, shader); } } GL::linkProgram(program); Error error = GL::getError("cannot link"); if(error.has()) { return error; } return GL::getLinkerError(program); } void use() const; void setMatrix(const char* name, const float* data); void setMatrix(const char* name, const Matrix& m); void setInt(const char* name, int data); void setFloat(const char* name, float data); void setVector(const char* name, const Vector2& v); void setVector(const char* name, const Vector3& v); void setVector(const char* name, const Vector4& v); private: GL::ShaderType getShaderType(const char* path) const; Error readAndCompile(const char* path, GL::Shader& s, GL::ShaderType st); Error readFile(List& code, const char* path) const; Error compileType(GL::Shader& s, const List& code, GL::ShaderType st); }; #endif