source: trunk/src/gl/gl_program.cc @ 300

Last change on this file since 300 was 300, checked in by epyon, 11 years ago
  • removed gl_names - too much bloat for too little gain
File size: 7.7 KB
RevLine 
[36]1// Copyright (C) 2012-2013 Kornel Kisielewicz
2// This file is part of NV Libraries.
3// For conditions of distribution and use, see copyright notice in nv.hh
4
5#include "nv/gl/gl_program.hh"
6
7#include "nv/gl/gl_enum.hh"
8#include "nv/logging.hh"
9#include "nv/lib/gl.hh"
10
[41]11#include <glm/glm.hpp>
12#include <glm/gtc/type_ptr.hpp>
13
[36]14using namespace nv;
15
[121]16gl_shader::gl_shader( uint32 sh_type )
17        : shader_type( sh_type ), object_id(0)
[36]18{
19        // no op
20}
21
[121]22gl_shader::gl_shader( uint32 sh_type, const string& shader_code )
23        : shader_type( sh_type ), object_id(0)
[36]24{
25        compile( shader_code );
26}
27
28gl_shader::~gl_shader()
29{
30        free();
31}
32
33bool gl_shader::compile( const string& shader_code )
34{
35        generate();
36
37        const char* pc = shader_code.c_str();
38
39        glShaderSource( object_id,   1, &pc, 0 );
40        glCompileShader( object_id );
41
42        return validate();
43}
44
45void gl_shader::generate()
46{
47        if ( is_valid() )
48        {
49                free();
50        }
51        object_id = glCreateShader( shader_type );
52}
53
54void gl_shader::free()
55{
56        glDeleteShader( object_id );
57        object_id = 0;
58}
59
60bool gl_shader::validate()
61{
62        const uint32 buffer_size = 1024;
63        char buffer[ buffer_size ] = { 0 };
64        int length;
[40]65        int compile_ok = GL_FALSE;
66        glGetShaderiv(object_id, GL_COMPILE_STATUS, &compile_ok);
[36]67        glGetShaderInfoLog( object_id, buffer_size, &length, buffer );
68
69        if ( length > 0 )
70        {
[40]71                if ( compile_ok == 0 )
72                {
73                        NV_LOG( LOG_ERROR, "Shader #" << object_id << " error: " << buffer );
74                }
75                else
76                {
77                        NV_LOG( LOG_INFO, "Shader #" << object_id << " compiled successfully: " << buffer );
78                }
[36]79        }
80        else
81        {
82                NV_LOG( LOG_INFO, "Shader #" << object_id << " compiled successfully." );
83        }
[40]84        return compile_ok != 0;
[36]85}
86
[37]87gl_program::gl_program( const string& vertex_program, const string& fragment_program )
88        : vertex_shader( GL_VERTEX_SHADER ), fragment_shader( GL_FRAGMENT_SHADER )
[36]89{
[300]90        glid = glCreateProgram();
[37]91        compile( vertex_program, fragment_program );
[36]92}
93
94gl_program::~gl_program()
95{
[300]96        if ( glid != 0 )
[36]97        {
98                // Detach the shaders from the program
[300]99                glDetachShader( glid, vertex_shader.get_id() );
100                glDetachShader( glid, fragment_shader.get_id() );
101                glDeleteProgram( glid );
[36]102        }
103}
104
[37]105bool gl_program::compile( const string& vertex_program, const string& fragment_program )
[36]106{
107        if (!vertex_shader.compile( vertex_program )) { return false; }
108        if (!fragment_shader.compile( fragment_program )) { return false; }
109
[300]110        glBindAttribLocation( glid, static_cast<GLuint>( slot::POSITION   ), "nv_position"  );
111        glBindAttribLocation( glid, static_cast<GLuint>( slot::TEXCOORD   ), "nv_texcoord"  );
112        glBindAttribLocation( glid, static_cast<GLuint>( slot::NORMAL     ), "nv_normal"    );
113        glBindAttribLocation( glid, static_cast<GLuint>( slot::COLOR      ), "nv_color"     );
114        glBindAttribLocation( glid, static_cast<GLuint>( slot::TANGENT    ), "nv_tangent"   );
115        glBindAttribLocation( glid, static_cast<GLuint>( slot::BONEINDEX  ), "nv_boneindex" );
116        glBindAttribLocation( glid, static_cast<GLuint>( slot::BONEWEIGHT ), "nv_boneweight");
[161]117
[300]118        glAttachShader( glid, fragment_shader.get_id() );
119        glAttachShader( glid, vertex_shader.get_id() );
120        glLinkProgram( glid );
[36]121
122        if (!validate())
123        {
124                return false;
125        }
126        load_attributes();
127        load_uniforms();
128        return true;
129}
130
131bool gl_program::is_valid() const
132{
[300]133        return glid != 0;
[36]134}
135
136void gl_program::load_attributes()
137{
138        int params;
[300]139        glGetProgramiv( glid, GL_ACTIVE_ATTRIBUTES, &params );
[36]140
[121]141        for ( unsigned i = 0; i < (unsigned)params; ++i )
[36]142        {
143                int attr_nlen;
144                int attr_len;
145                unsigned attr_type;
146                char name_buffer[128];
147
[300]148                glGetActiveAttrib( glid, i, 128, &attr_nlen, &attr_len, &attr_type, name_buffer );
[36]149
[121]150                string name( name_buffer, size_t(attr_nlen) );
[36]151
152                // skip built-ins
153                if ( name.substr(0,3) == "gl_" ) continue;
154
[300]155                int attr_loc = glGetAttribLocation( glid, name.c_str() );
[36]156
[70]157                m_attribute_map[ name ] = new attribute( name, attr_loc, gl_enum_to_datatype( attr_type ), attr_len );
[36]158        }
159}
160
161void gl_program::load_uniforms()
162{
163        int params;
[300]164        glGetProgramiv( glid, GL_ACTIVE_UNIFORMS, &params );
[36]165
[121]166        for ( unsigned i = 0; i < size_t(params); ++i )
[36]167        {
168                int uni_nlen;
169                int uni_len;
170                unsigned uni_type;
171                char name_buffer[128];
172
[300]173                glGetActiveUniform( glid, i, 128, &uni_nlen, &uni_len, &uni_type, name_buffer );
[36]174
[121]175                string name( name_buffer, size_t(uni_nlen) );
[235]176               
[36]177                // skip built-ins
178                if ( name.substr(0,3) == "gl_" ) continue;
179
[300]180                int uni_loc = glGetUniformLocation( glid, name.c_str() );
[70]181                datatype utype = gl_enum_to_datatype( uni_type );
[235]182               
183                // check for array
184                string::size_type arrchar = name.find('[');
185                if ( arrchar != string::npos )
186                {
187                        name = name.substr( 0, arrchar );
188                }
189
[237]190                uniform_base* u = create_uniform( utype, name, uni_loc, uni_len );
191                NV_ASSERT( u, "Unknown uniform type!" );
192                m_uniform_map[ name ] = u;
[36]193        }
[232]194
195        apply_link_engine_uniforms();
196        bind_engine_uniforms();
[36]197}
198
[41]199void gl_program::update_uniforms()
200{
201        for ( uniform_map::iterator i = m_uniform_map.begin();  i != m_uniform_map.end(); ++i )
202        {
203                uniform_base* ubase = i->second;
204                if ( ubase->is_dirty() )
205                {
206                        int uloc = ubase->get_location();
207                        switch( ubase->get_type() )
208                        {
[235]209                        case FLOAT          : glUniform1fv( uloc, ubase->get_length(), ((uniform< enum_to_type< FLOAT >::type >*)( ubase ))->get_value() ); break;
210                        case INT            : glUniform1iv( uloc, ubase->get_length(), ((uniform< enum_to_type< INT >::type >*)( ubase ))->get_value() ); break;
211                        case FLOAT_VECTOR_2 : glUniform2fv( uloc, ubase->get_length(), (GLfloat*)((uniform< enum_to_type< FLOAT_VECTOR_2 >::type >*)( ubase ))->get_value()); break;
212                        case FLOAT_VECTOR_3 : glUniform3fv( uloc, ubase->get_length(), (GLfloat*)((uniform< enum_to_type< FLOAT_VECTOR_3 >::type >*)( ubase ))->get_value()); break;
213                        case FLOAT_VECTOR_4 : glUniform4fv( uloc, ubase->get_length(), (GLfloat*)((uniform< enum_to_type< FLOAT_VECTOR_4 >::type >*)( ubase ))->get_value()); break;
214                        case INT_VECTOR_2   : glUniform2iv( uloc, ubase->get_length(), (GLint*)((uniform< enum_to_type< INT_VECTOR_2 >::type >*)( ubase ))->get_value()); break;
215                        case INT_VECTOR_3   : glUniform3iv( uloc, ubase->get_length(), (GLint*)((uniform< enum_to_type< INT_VECTOR_3 >::type >*)( ubase ))->get_value()); break;
216                        case INT_VECTOR_4   : glUniform4iv( uloc, ubase->get_length(), (GLint*)((uniform< enum_to_type< INT_VECTOR_4 >::type >*)( ubase ))->get_value()); break;
217                        case FLOAT_MATRIX_2 : glUniformMatrix2fv( uloc, ubase->get_length(), GL_FALSE, (GLfloat*)((uniform< enum_to_type< FLOAT_MATRIX_2 >::type >*)( ubase ))->get_value()); break;
218                        case FLOAT_MATRIX_3 : glUniformMatrix3fv( uloc, ubase->get_length(), GL_FALSE, (GLfloat*)((uniform< enum_to_type< FLOAT_MATRIX_3 >::type >*)( ubase ))->get_value()); break;
219                        case FLOAT_MATRIX_4 : glUniformMatrix4fv( uloc, ubase->get_length(), GL_FALSE, (GLfloat*)((uniform< enum_to_type< FLOAT_MATRIX_4 >::type >*)( ubase ))->get_value()); break;
[121]220                        default : break; // error?
[41]221                        }
222                        ubase->clean();
223                }
224        }
225
226}
227
228
[36]229bool gl_program::validate()
230{
231        const uint32 buffer_size = 2048;
232        char buffer[ buffer_size ] = { 0 };
233        int length;
234        int status;
235
[300]236        glGetProgramiv( glid, GL_LINK_STATUS, &status );
237        glGetProgramInfoLog( glid, buffer_size, &length, buffer );
[36]238
[300]239        NV_LOG( LOG_INFO, "Program #" << glid << (status == GL_FALSE ? " failed to compile!" : " compiled successfully.") );
[36]240
241        if ( length > 0 )
242        {
[300]243                NV_LOG( LOG_INFO, "Program #" << glid << " log: " << buffer );
[36]244        }
245
246        if ( status == GL_FALSE )
247        {
248                return false;
249        }
250
[300]251        glValidateProgram( glid );
252        glGetProgramiv( glid, GL_VALIDATE_STATUS, &status );
[36]253
254        if ( status == GL_FALSE )
255        {
[300]256                glGetProgramInfoLog( glid, buffer_size, &length, buffer );
257                NV_LOG( LOG_ERROR, "Program #" << glid << " validation error : " << buffer );
[36]258                return false;
259        }
260        return true;
261}
262
263
Note: See TracBrowser for help on using the repository browser.