#ifndef GLSHADER_SHADER_HPP #define GLSHADER_SHADER_HPP #include #include #include #include #include #include class Shader { public: Shader(std::vector paths, std::string name = ""); Shader(Shader &&); Shader(Shader const &); Shader & operator=(Shader &&); Shader & operator=(Shader const &); ~Shader(); Shader & use(); Shader & validate(); template Shader & uniform(std::string const & name, Value const & value) = delete; private: template using StringCache = std::unordered_map; void new_(); void delete_(); void ensure_current_( std::string const & operation, std::string const & name = "" ); GLint uniform_location_(std::string const & name); GLuint program_; std::vector paths_; std::string name_; StringCache uniform_location_cache_; }; #ifdef NDEBUG #define GLSHADER_ENSURE_CURRENT(OPERATION, NAME) #else #define GLSHADER_ENSURE_CURRENT(OPERATION, NAME) \ ensure_current_(OPERATION, NAME) #endif #define GLSHADER_UNIFORM(VALUE_TYPE, CODE) \ template<> \ inline Shader & Shader::uniform( \ std::string const & name, VALUE_TYPE const & value \ ) { \ GLSHADER_ENSURE_CURRENT("set uniform", name); \ CODE; \ return *this; \ } #define GLSHADER_UNIFORM_SCALAR(VALUE_TYPE, GL_TYPE) \ GLSHADER_UNIFORM( \ VALUE_TYPE, \ glUniform1##GL_TYPE( \ uniform_location_(name), value \ ) \ ) #define GLSHADER_UNIFORM_N(N, GLM_VALUE_TYPE, GL_TYPE) \ GLSHADER_UNIFORM( \ glm::GLM_VALUE_TYPE##N, \ glUniform##N##GL_TYPE##v( \ uniform_location_(name), 1, glm::value_ptr(value) \ ) \ ) #define GLSHADER_UNIFORM_N_BOOL(N) \ GLSHADER_UNIFORM( \ glm::bvec##N, \ GLint int_value[N]; \ for (auto i = 0; i < N; ++i) \ int_value[i] = value[i]; \ glUniform##N##iv( \ uniform_location_(name), 1, &int_value[0] \ ) \ ) #define GLSHADER_UNIFORM_MATRIX_N(N) \ GLSHADER_UNIFORM( \ glm::mat##N, \ glUniformMatrix##N##fv( \ uniform_location_(name), 1, GL_FALSE, glm::value_ptr(value) \ ) \ ) #define GLSHADER_UNIFORM_MATRIX_N_M(N, M) \ GLSHADER_UNIFORM( \ glm::mat##N##x##M, \ glUniformMatrix##N##x##M##fv( \ uniform_location_(name), 1, GL_FALSE, glm::value_ptr(value) \ ) \ ) GLSHADER_UNIFORM_SCALAR(bool, i) GLSHADER_UNIFORM_SCALAR(int, i) GLSHADER_UNIFORM_SCALAR(glm::uint, ui) GLSHADER_UNIFORM_SCALAR(float, f) GLSHADER_UNIFORM_SCALAR(double, f) GLSHADER_UNIFORM_N_BOOL(2) GLSHADER_UNIFORM_N_BOOL(3) GLSHADER_UNIFORM_N_BOOL(4) GLSHADER_UNIFORM_N(2, ivec, i) GLSHADER_UNIFORM_N(3, ivec, i) GLSHADER_UNIFORM_N(4, ivec, i) GLSHADER_UNIFORM_N(2, uvec, ui) GLSHADER_UNIFORM_N(3, uvec, ui) GLSHADER_UNIFORM_N(4, uvec, ui) GLSHADER_UNIFORM_N(2, vec, f) GLSHADER_UNIFORM_N(3, vec, f) GLSHADER_UNIFORM_N(4, vec, f) GLSHADER_UNIFORM_MATRIX_N(2) GLSHADER_UNIFORM_MATRIX_N(3) GLSHADER_UNIFORM_MATRIX_N(4) GLSHADER_UNIFORM_MATRIX_N_M(2, 3) GLSHADER_UNIFORM_MATRIX_N_M(2, 4) GLSHADER_UNIFORM_MATRIX_N_M(3, 2) GLSHADER_UNIFORM_MATRIX_N_M(3, 4) GLSHADER_UNIFORM_MATRIX_N_M(4, 2) GLSHADER_UNIFORM_MATRIX_N_M(4, 3) #endif // GLSHADER_SHADER_HPP