7 #include <gls/headercheck.hpp>
8 #include <gls/errorcheck.hpp>
9 #include <gls/objects/object.hpp>
10 #include <gls/objects/shader.hpp>
11 #include <initializer_list>
15 #include <unordered_map>
18 #if !defined( NDEBUG )
19 #if !defined( GLS_ERROR_STREAM )
21 #define GLS_ERROR_STREAM std::cerr
28 void create_program( GLsizei, GLuint* name ) { *name = glCreateProgram(); }
29 void delete_program( GLsizei,
const GLuint* name ) { glDeleteProgram( *name ); }
45 return m_object.name();
69 template<
typename... Shaders>
70 bool link( Shaders&&... shaders ) {
71 attach_all( shaders... );
73 check_gl_error( glLinkProgram(
name() ) );
75 detach_all( shaders... );
77 auto link_status = GL_FALSE;
78 check_gl_error( glGetProgramiv(
name(), GL_LINK_STATUS, &link_status ) );
80 #if !defined( NDEBUG )
83 if( !info_log.empty() ) {
84 GLS_ERROR_STREAM << std::move( info_log );
88 auto result = ( link_status == GL_TRUE );
109 auto info_log_length = GLint();
110 check_gl_error( glGetProgramiv(
name(), GL_INFO_LOG_LENGTH, &info_log_length ) );
112 if( !info_log_length ) {
113 return std::string();
116 auto info_log = std::vector<GLchar>(
static_cast<std::size_t
>( info_log_length ), 0 );
117 check_gl_error( glGetProgramInfoLog(
name(), info_log_length,
nullptr, info_log.data() ) );
119 return std::string( info_log.data() );
130 check_gl_error( glUseProgram(
name() ) );
140 check_gl_error( glUseProgram( 0 ) );
155 const auto iter = m_attribute_map.find( attribute_name );
157 if( iter == std::end( m_attribute_map ) ) {
161 return std::get<0>( iter->second );
174 const auto iter = m_attribute_map.find( attribute_name );
176 if( iter == std::end( m_attribute_map ) ) {
180 return std::get<1>( iter->second );
193 const auto iter = m_attribute_map.find( attribute_name );
195 if( iter == std::end( m_attribute_map ) ) {
199 return std::get<2>( iter->second );
214 const auto iter = m_uniform_map.find( uniform_name );
216 if( iter == std::end( m_uniform_map ) ) {
220 return std::get<0>( iter->second );
233 const auto iter = m_uniform_map.find( uniform_name );
235 if( iter == std::end( m_uniform_map ) ) {
239 return std::get<1>( iter->second );
252 const auto iter = m_uniform_map.find( uniform_name );
254 if( iter == std::end( m_uniform_map ) ) {
258 return std::get<2>( iter->second );
273 const auto iter = m_uniform_block_map.find( uniform_block_name );
275 if( iter == std::end( m_uniform_block_map ) ) {
276 return GL_INVALID_INDEX;
279 return std::get<0>( iter->second );
293 const auto iter = m_uniform_block_map.find( uniform_block_name );
295 if( iter == std::end( m_uniform_block_map ) ) {
299 return std::get<1>( iter->second );
304 void uniform(
const std::string& uniform_name, T v0 ) =
delete;
342 void uniform(
const std::string& uniform_name, T v0, T v1 ) =
delete;
383 void uniform(
const std::string& uniform_name, T v0, T v1, T v2 ) =
delete;
397 void uniform(
const std::string& uniform_name, GLfloat v0, GLfloat v1, GLfloat v2 ) {
use(); check_gl_error( glUniform3f(
get_uniform_location( uniform_name ), v0, v1, v2 ) );
unuse(); };
427 void uniform(
const std::string& uniform_name, T v0, T v1, T v2, T v3 ) =
delete;
442 void uniform(
const std::string& uniform_name, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3 ) {
use(); check_gl_error( glUniform4f(
get_uniform_location( uniform_name ), v0, v1, v2, v3 ) );
unuse(); };
456 void uniform(
const std::string& uniform_name, GLint v0, GLint v1, GLint v2, GLint v3 ) {
use(); check_gl_error( glUniform4i(
get_uniform_location( uniform_name ), v0, v1, v2, v3 ) );
unuse(); };
470 void uniform(
const std::string& uniform_name, GLuint v0, GLuint v1, GLuint v2, GLuint v3 ) {
use(); check_gl_error( glUniform4ui(
get_uniform_location( uniform_name ), v0, v1, v2, v3 ) );
unuse(); };
483 void uniform1(
const std::string& uniform_name, GLsizei count,
const GLfloat* value ) {
use(); check_gl_error( glUniform1fv(
get_uniform_location( uniform_name ), count, value ) );
unuse(); };
509 void uniform1(
const std::string& uniform_name, GLsizei count,
const GLuint* value ) {
use(); check_gl_error( glUniform1uiv(
get_uniform_location( uniform_name ), count, value ) );
unuse(); };
522 void uniform2(
const std::string& uniform_name, GLsizei count,
const GLfloat* value ) {
use(); check_gl_error( glUniform2fv(
get_uniform_location( uniform_name ), count, value ) );
unuse(); };
548 void uniform2(
const std::string& uniform_name, GLsizei count,
const GLuint* value ) {
use(); check_gl_error( glUniform2uiv(
get_uniform_location( uniform_name ), count, value ) );
unuse(); };
561 void uniform3(
const std::string& uniform_name, GLsizei count,
const GLfloat* value ) {
use(); check_gl_error( glUniform3fv(
get_uniform_location( uniform_name ), count, value ) );
unuse(); };
587 void uniform3(
const std::string& uniform_name, GLsizei count,
const GLuint* value ) {
use(); check_gl_error( glUniform3uiv(
get_uniform_location( uniform_name ), count, value ) );
unuse(); };
600 void uniform4(
const std::string& uniform_name, GLsizei count,
const GLfloat* value ) {
use(); check_gl_error( glUniform4fv(
get_uniform_location( uniform_name ), count, value ) );
unuse(); };
626 void uniform4(
const std::string& uniform_name, GLsizei count,
const GLuint* value ) {
use(); check_gl_error( glUniform4uiv(
get_uniform_location( uniform_name ), count, value ) );
unuse(); };
640 void uniform_matrix2(
const std::string& uniform_name, GLsizei count, GLboolean transpose,
const GLfloat* value ) {
use(); check_gl_error( glUniformMatrix2fv(
get_uniform_location( uniform_name ), count, transpose, value ) );
unuse(); };
654 void uniform_matrix3(
const std::string& uniform_name, GLsizei count, GLboolean transpose,
const GLfloat* value ) {
use(); check_gl_error( glUniformMatrix3fv(
get_uniform_location( uniform_name ), count, transpose, value ) );
unuse(); };
668 void uniform_matrix4(
const std::string& uniform_name, GLsizei count, GLboolean transpose,
const GLfloat* value ) {
use(); check_gl_error( glUniformMatrix4fv(
get_uniform_location( uniform_name ), count, transpose, value ) );
unuse(); };
682 void uniform_matrix2x3(
const std::string& uniform_name, GLsizei count, GLboolean transpose,
const GLfloat* value ) {
use(); check_gl_error( glUniformMatrix2x3fv(
get_uniform_location( uniform_name ), count, transpose, value ) );
unuse(); };
696 void uniform_matrix3x2(
const std::string& uniform_name, GLsizei count, GLboolean transpose,
const GLfloat* value ) {
use(); check_gl_error( glUniformMatrix3x2fv(
get_uniform_location( uniform_name ), count, transpose, value ) );
unuse(); };
710 void uniform_matrix2x4(
const std::string& uniform_name, GLsizei count, GLboolean transpose,
const GLfloat* value ) {
use(); check_gl_error( glUniformMatrix2x4fv(
get_uniform_location( uniform_name ), count, transpose, value ) );
unuse(); };
724 void uniform_matrix4x2(
const std::string& uniform_name, GLsizei count, GLboolean transpose,
const GLfloat* value ) {
use(); check_gl_error( glUniformMatrix4x2fv(
get_uniform_location( uniform_name ), count, transpose, value ) );
unuse(); };
738 void uniform_matrix3x4(
const std::string& uniform_name, GLsizei count, GLboolean transpose,
const GLfloat* value ) {
use(); check_gl_error( glUniformMatrix3x4fv(
get_uniform_location( uniform_name ), count, transpose, value ) );
unuse(); };
752 void uniform_matrix4x3(
const std::string& uniform_name, GLsizei count, GLboolean transpose,
const GLfloat* value ) {
use(); check_gl_error( glUniformMatrix4x3fv(
get_uniform_location( uniform_name ), count, transpose, value ) );
unuse(); };
757 template<
typename ...T>
763 template<
typename... Args>
764 void attach_all( Args&&... args ) {
765 pass( ( attach( args ), 1 )... );
768 template<GLenum ShaderType>
769 void attach(
const shader<ShaderType>& shader_object ) {
770 check_gl_error( glAttachShader(
name(), shader_object.name() ) );
773 template<
typename... Args>
774 void detach_all( Args&&... args ) {
775 pass( ( detach( args ), 1 )... );
778 template<GLenum ShaderType>
779 void detach(
const shader<ShaderType>& shader_object ) {
780 check_gl_error( glDetachShader(
name(), shader_object.name() ) );
786 m_attribute_map.clear();
788 auto active_attributes = GLint();
789 check_gl_error( glGetProgramiv(
name(), GL_ACTIVE_ATTRIBUTES, &active_attributes ) );
791 auto active_attribute_max_length = GLint();
792 check_gl_error( glGetProgramiv(
name(), GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &active_attribute_max_length ) );
794 auto attribute_name = std::vector<GLchar>(
static_cast<std::size_t
>( active_attribute_max_length ), 0 );
796 for( GLuint index = 0; index < static_cast<GLuint>( active_attributes ); ++index ) {
797 auto attribute_type = GLenum();
798 auto attribute_size = GLint();
800 check_gl_error( glGetActiveAttrib(
name(), index, active_attribute_max_length,
nullptr, &attribute_size, &attribute_type, attribute_name.data() ) );
802 auto attribute_location = GLint();
804 attribute_location = check_gl_error( glGetAttribLocation(
name(), attribute_name.data() ) );
806 assert( attribute_location >= 0 );
808 m_attribute_map.emplace( std::string( attribute_name.data() ), std::make_tuple( attribute_location, attribute_type, attribute_size ) );
814 m_uniform_map.clear();
816 auto active_uniforms = GLint();
817 check_gl_error( glGetProgramiv(
name(), GL_ACTIVE_UNIFORMS, &active_uniforms ) );
819 auto active_uniform_max_length = GLint();
820 check_gl_error( glGetProgramiv(
name(), GL_ACTIVE_UNIFORM_MAX_LENGTH, &active_uniform_max_length ) );
822 auto uniform_name = std::vector<GLchar>(
static_cast<std::size_t
>( active_uniform_max_length ), 0 );
824 for( GLuint index = 0; index < static_cast<GLuint>( active_uniforms ); ++index ) {
825 auto uniform_type = GLint();
826 auto uniform_size = GLint();
828 check_gl_error( glGetActiveUniformName(
name(), index, active_uniform_max_length,
nullptr, uniform_name.data() ) );
829 check_gl_error( glGetActiveUniformsiv(
name(), 1, &index, GL_UNIFORM_TYPE, &uniform_type ) );
830 check_gl_error( glGetActiveUniformsiv(
name(), 1, &index, GL_UNIFORM_SIZE, &uniform_size ) );
832 auto uniform_location = GLint();
834 uniform_location = check_gl_error( glGetUniformLocation(
name(), uniform_name.data() ) );
836 assert( uniform_location >= 0 );
838 m_uniform_map.emplace( std::string( uniform_name.data() ), std::make_tuple( uniform_location, static_cast<GLenum>( uniform_type ), uniform_size ) );
844 m_uniform_block_map.clear();
846 auto active_uniform_blocks = GLint();
847 check_gl_error( glGetProgramiv(
name(), GL_ACTIVE_UNIFORM_BLOCKS, &active_uniform_blocks ) );
849 auto active_uniform_block_max_name_length = GLint();
850 check_gl_error( glGetProgramiv(
name(), GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &active_uniform_block_max_name_length ) );
852 auto uniform_block_name = std::vector<GLchar>(
static_cast<std::size_t
>( active_uniform_block_max_name_length ), 0 );
854 for( GLuint index = 0; index < static_cast<GLuint>( active_uniform_blocks ); ++index ) {
855 auto uniform_block_size = GLint();
857 check_gl_error( glGetActiveUniformBlockName(
name(), index, active_uniform_block_max_name_length,
nullptr, uniform_block_name.data() ) );
858 check_gl_error( glGetActiveUniformBlockiv(
name(), index, GL_UNIFORM_BLOCK_DATA_SIZE, &uniform_block_size ) );
860 m_uniform_block_map.emplace( std::string( uniform_block_name.data() ), std::make_tuple( index, uniform_block_size ) );
865 object<priv::create_program, priv::delete_program> m_object;
866 std::unordered_map<std::string, std::tuple<GLint, GLenum, GLint>> m_attribute_map;
867 std::unordered_map<std::string, std::tuple<GLint, GLenum, GLint>> m_uniform_map;
868 std::unordered_map<std::string, std::tuple<GLuint, GLint>> m_uniform_block_map;
GLint get_uniform_block_size(const std::string &uniform_block_name) const
Get the size of a uniform block.
Definition: program.hpp:292
void uniform_matrix3x4(const std::string &uniform_name, GLsizei count, GLboolean transpose, const GLfloat *value)
Set an array of 3x4 uniform matrix values.
Definition: program.hpp:738
static void unuse()
No longer use a program.
Definition: program.hpp:139
GLint get_attribute_location(const std::string &attribute_name) const
Get the location of an attribute.
Definition: program.hpp:154
void uniform(const std::string &uniform_name, GLint v0)
Set a 1-component uniform value.
Definition: program.hpp:327
void uniform(const std::string &uniform_name, GLfloat v0)
Set a 1-component uniform value.
Definition: program.hpp:316
void uniform3(const std::string &uniform_name, GLsizei count, const GLfloat *value)
Set an array of 3-component uniform values.
Definition: program.hpp:561
GLint get_uniform_size(const std::string &uniform_name) const
Get the size of a uniform.
Definition: program.hpp:251
Class encapsulating an OpenGL program object.
Definition: program.hpp:36
void uniform(const std::string &uniform_name, GLuint v0)
Set a 1-component uniform value.
Definition: program.hpp:338
void uniform(const std::string &uniform_name, GLfloat v0, GLfloat v1)
Set a 2-component uniform value.
Definition: program.hpp:355
void uniform3(const std::string &uniform_name, GLsizei count, const GLuint *value)
Set an array of 3-component uniform values.
Definition: program.hpp:587
void uniform_matrix3(const std::string &uniform_name, GLsizei count, GLboolean transpose, const GLfloat *value)
Set an array of 3x3 uniform matrix values.
Definition: program.hpp:654
void uniform(const std::string &uniform_name, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
Set a 4-component uniform value.
Definition: program.hpp:470
void uniform(const std::string &uniform_name, GLint v0, GLint v1, GLint v2, GLint v3)
Set a 4-component uniform value.
Definition: program.hpp:456
void uniform4(const std::string &uniform_name, GLsizei count, const GLuint *value)
Set an array of 4-component uniform values.
Definition: program.hpp:626
void uniform3(const std::string &uniform_name, GLsizei count, const GLint *value)
Set an array of 3-component uniform values.
Definition: program.hpp:574
void uniform(const std::string &uniform_name, GLuint v0, GLuint v1, GLuint v2)
Set a 3-component uniform value.
Definition: program.hpp:423
void uniform(const std::string &uniform_name, GLuint v0, GLuint v1)
Set a 2-component uniform value.
Definition: program.hpp:379
void uniform_matrix2x3(const std::string &uniform_name, GLsizei count, GLboolean transpose, const GLfloat *value)
Set an array of 2x3 uniform matrix values.
Definition: program.hpp:682
void uniform_matrix4x2(const std::string &uniform_name, GLsizei count, GLboolean transpose, const GLfloat *value)
Set an array of 4x2 uniform matrix values.
Definition: program.hpp:724
std::string get_info_log() const
Get the link information log.
Definition: program.hpp:108
void uniform_matrix4(const std::string &uniform_name, GLsizei count, GLboolean transpose, const GLfloat *value)
Set an array of 4x4 uniform matrix values.
Definition: program.hpp:668
void uniform(const std::string &uniform_name, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
Set a 4-component uniform value.
Definition: program.hpp:442
void uniform_matrix3x2(const std::string &uniform_name, GLsizei count, GLboolean transpose, const GLfloat *value)
Set an array of 3x2 uniform matrix values.
Definition: program.hpp:696
void uniform_matrix2x4(const std::string &uniform_name, GLsizei count, GLboolean transpose, const GLfloat *value)
Set an array of 2x4 uniform matrix values.
Definition: program.hpp:710
void uniform(const std::string &uniform_name, GLfloat v0, GLfloat v1, GLfloat v2)
Set a 3-component uniform value.
Definition: program.hpp:397
void uniform(const std::string &uniform_name, GLint v0, GLint v1)
Set a 2-component uniform value.
Definition: program.hpp:367
GLenum get_uniform_type(const std::string &uniform_name) const
Get the type of a uniform.
Definition: program.hpp:232
void uniform4(const std::string &uniform_name, GLsizei count, const GLint *value)
Set an array of 4-component uniform values.
Definition: program.hpp:613
void uniform1(const std::string &uniform_name, GLsizei count, const GLfloat *value)
Set an array of 1-component uniform values.
Definition: program.hpp:483
void uniform2(const std::string &uniform_name, GLsizei count, const GLfloat *value)
Set an array of 2-component uniform values.
Definition: program.hpp:522
void uniform1(const std::string &uniform_name, GLsizei count, const GLuint *value)
Set an array of 1-component uniform values.
Definition: program.hpp:509
void uniform_matrix2(const std::string &uniform_name, GLsizei count, GLboolean transpose, const GLfloat *value)
Set an array of 2x2 uniform matrix values.
Definition: program.hpp:640
void uniform_matrix4x3(const std::string &uniform_name, GLsizei count, GLboolean transpose, const GLfloat *value)
Set an array of 4x3 uniform matrix values.
Definition: program.hpp:752
void uniform(const std::string &uniform_name, GLint v0, GLint v1, GLint v2)
Set a 3-component uniform value.
Definition: program.hpp:410
void use()
Use this program.
Definition: program.hpp:129
GLint get_uniform_location(const std::string &uniform_name) const
Get the location of a uniform.
Definition: program.hpp:213
GLenum get_attribute_type(const std::string &attribute_name) const
Get the type of an attribute.
Definition: program.hpp:173
GLuint get_uniform_block_index(const std::string &uniform_block_name) const
Get the index of a uniform block.
Definition: program.hpp:272
void uniform1(const std::string &uniform_name, GLsizei count, const GLint *value)
Set an array of 1-component uniform values.
Definition: program.hpp:496
void uniform2(const std::string &uniform_name, GLsizei count, const GLint *value)
Set an array of 2-component uniform values.
Definition: program.hpp:535
Definition: buffer.hpp:12
GLint get_attribute_size(const std::string &attribute_name) const
Get the size of an attribute.
Definition: program.hpp:192
void uniform4(const std::string &uniform_name, GLsizei count, const GLfloat *value)
Set an array of 4-component uniform values.
Definition: program.hpp:600
void uniform2(const std::string &uniform_name, GLsizei count, const GLuint *value)
Set an array of 2-component uniform values.
Definition: program.hpp:548
GLuint name() const
Retrieve the OpenGL name of this program.
Definition: program.hpp:44
bool link(Shaders &&...shaders)
Link a set of compiled shaders into this program.
Definition: program.hpp:70