e0fdd020 | #ifndef GLSHADER_SHADER_HPP #define GLSHADER_SHADER_HPP #include <vector> #include <string> |
67ab19a4 | #include <unordered_map> |
e0fdd020 | #include <GL/glew.h> |
67ab19a4 | #include <glm/glm.hpp> #include <glm/gtc/type_ptr.hpp> |
e0fdd020 | class Shader { public: |
4e6bd516 | Shader() : |
51b42857 | program_ {}, paths_ {}, name_ {}, uniform_location_cache_ {}, uniform_block_index_cache_ {} |
4e6bd516 | { }; |
e0fdd020 | Shader(std::vector<std::string> paths, std::string name = ""); Shader(Shader &&); Shader(Shader const &); Shader & operator=(Shader &&); Shader & operator=(Shader const &); ~Shader(); Shader & use(); Shader & validate(); |
67ab19a4 | template<typename Value> |
d8d951a6 | Shader & uniform(std::string const & name, Value const & value); Shader & uniform(std::string const & name, std::string const & buffer_name); template<typename Value> static void uniform_buffer( std::string const & name, Value const & value, GLenum usage = GL_DYNAMIC_DRAW ); static void uniform_buffer_delete(std::string const & name); |
9b9a6722 | static void ubo_delete(std::string const & name); |
51b42857 | GLuint program(){return program_;} |
e0fdd020 | private: |
67ab19a4 | template<typename Value> using StringCache = std::unordered_map<std::string, Value>; |
d8d951a6 | struct UniformBuffer { GLuint buffer; GLsizeiptr size; GLenum usage; GLuint binding; }; |
e0fdd020 | void new_(); void delete_(); void ensure_current_( std::string const & operation, std::string const & name = "" ); |
67ab19a4 | GLint uniform_location_(std::string const & name); |
d8d951a6 | GLuint uniform_block_index_(std::string const & name); static GLuint uniform_buffer_( std::string const & name, GLsizeiptr size, GLenum usage ); |
e0fdd020 | GLuint program_; std::vector<std::string> paths_; std::string name_; |
67ab19a4 | StringCache<GLint> uniform_location_cache_; |
d8d951a6 | StringCache<GLuint> uniform_block_index_cache_; static StringCache<UniformBuffer> uniform_buffer_cache_; static GLuint uniform_buffer_binding_next_; |
e0fdd020 | }; #ifdef NDEBUG #define GLSHADER_ENSURE_CURRENT(OPERATION, NAME) #else #define GLSHADER_ENSURE_CURRENT(OPERATION, NAME) \ ensure_current_(OPERATION, NAME) #endif |
d8d951a6 | template<typename Value> inline Shader & Shader::uniform( std::string const & name, Value const & value ) { GLSHADER_ENSURE_CURRENT("set uniform block", name); uniform_block_index_(name); uniform_buffer(name, value); uniform(name, name); return *this; } template<typename Value> inline void Shader::uniform_buffer( std::string const & name, Value const & value, GLenum usage ) { glBindBuffer( GL_UNIFORM_BUFFER, uniform_buffer_(name, sizeof(value), usage) ); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(value), &value); } |
67ab19a4 | #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) |
e0fdd020 | #endif // GLSHADER_SHADER_HPP |