| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360 |
- #include "shader_prog.h"
- #include "renderer.h"
- #include "shader_parser.h"
- #include "texture.h"
- #define SHADER_ERROR( x ) ERROR( "Shader prog \"" << GetName() << "\": " << x )
- #define SHADER_WARNING( x ) WARNING( "Shader prog \"" << GetName() << "\": " << x )
- //=====================================================================================================================================
- // CreateAndCompileShader =
- //=====================================================================================================================================
- uint shader_prog_t::CreateAndCompileShader( const char* source_code, const char* preproc, int type ) const
- {
- uint gl_id = 0;
- const char* source_strs[2] = {NULL, NULL};
- // create the shader
- gl_id = glCreateShader( type );
- // attach the source
- source_strs[1] = source_code;
- source_strs[0] = preproc;
- // compile
- glShaderSource( gl_id, 2, source_strs, NULL );
- glCompileShader( gl_id );
- int success;
- glGetShaderiv( gl_id, GL_COMPILE_STATUS, &success );
- if( !success )
- {
- // print info log
- int info_len = 0;
- int chars_written = 0;
- char* info_log = NULL;
- glGetShaderiv( gl_id, GL_INFO_LOG_LENGTH, &info_len );
- info_log = (char*)malloc( (info_len+1)*sizeof(char) );
- glGetShaderInfoLog( gl_id, info_len, &chars_written, info_log );
-
- const char* shader_type;
- switch( type )
- {
- case GL_VERTEX_SHADER:
- shader_type = "Vertex shader";
- break;
- case GL_FRAGMENT_SHADER:
- shader_type = "Fragment shader";
- break;
- default:
- DEBUG_ERR( 1 ); // Not supported
- }
- SHADER_ERROR( shader_type << " compiler log follows:\n" << info_log );
-
- free( info_log );
- return 0;
- }
- return gl_id;
- }
- //=====================================================================================================================================
- // Link =
- //=====================================================================================================================================
- bool shader_prog_t::Link()
- {
- // link
- glLinkProgram( gl_id );
- // check if linked correctly
- int success;
- glGetProgramiv( gl_id, GL_LINK_STATUS, &success );
- if( !success )
- {
- int info_len = 0;
- int chars_written = 0;
- char* info_log_txt = NULL;
- glGetProgramiv( gl_id, GL_INFO_LOG_LENGTH, &info_len );
- info_log_txt = (char*)malloc( (info_len+1)*sizeof(char) );
- glGetProgramInfoLog( gl_id, info_len, &chars_written, info_log_txt );
- SHADER_ERROR( "Link log follows:\n" << info_log_txt );
- free( info_log_txt );
- return false;
- }
- return true;
- }
- //=====================================================================================================================================
- // GetUniAndAttribLocs =
- //=====================================================================================================================================
- void shader_prog_t::GetUniAndAttribLocs()
- {
- int num;
- char name_[256];
- GLsizei length;
- GLint size;
- GLenum type;
- // attrib locations
- glGetProgramiv( gl_id, GL_ACTIVE_ATTRIBUTES, &num );
- for( int i=0; i<num; i++ ) // loop all attributes
- {
- glGetActiveAttrib( gl_id, i, sizeof(name_)/sizeof(char), &length, &size, &type, name_ );
- name_[ length ] = '\0';
- // check if its FFP location
- int loc = glGetAttribLocation(gl_id, name_);
- if( loc == -1 )
- {
- //SHADER_WARNING( "You are using FFP vertex attributes (\"" << name_ << "\")" );
- continue;
- }
- attrib_name_to_loc[ name_ ] = loc;
- }
- // uni locations
- glGetProgramiv( gl_id, GL_ACTIVE_UNIFORMS, &num );
- for( int i=0; i<num; i++ ) // loop all uniforms
- {
- glGetActiveUniform( gl_id, i, sizeof(name_)/sizeof(char), &length, &size, &type, name_ );
- name_[ length ] = '\0';
- // check if its FFP location
- int loc = glGetUniformLocation(gl_id, name_);
- if( loc == -1 )
- {
- //SHADER_WARNING( "You are using FFP uniforms (\"" << name_ << "\")" );
- continue;
- }
- uni_name_to_loc[ name_ ] = loc;
- }
- }
- //=====================================================================================================================================
- // FillTheCustomLocationsVectors =
- //=====================================================================================================================================
- bool shader_prog_t::FillTheCustomLocationsVectors( const shader_parser_t& pars )
- {
- Bind();
- uint max = 0;
- // uniforms
- for( uint i=0; i<pars.uniforms.size(); ++i )
- {
- if( pars.uniforms[i].custom_loc > max )
- max = pars.uniforms[i].custom_loc;
- }
- custom_uni_loc_to_real_loc.assign( max + 1, -1 );
- for( uint i=0; i<pars.uniforms.size(); ++i )
- {
- if( custom_uni_loc_to_real_loc[ pars.uniforms[i].custom_loc ] != -1 )
- {
- SHADER_ERROR( "The uniform \"" << pars.uniforms[i].name << "\" has the same value with another one" );
- return false;
- }
- int loc = GetUniformLocation( pars.uniforms[i].name.c_str() );
- if( loc == -1 )
- {
- SHADER_ERROR( "Check the previous error" );
- return false;
- }
- custom_uni_loc_to_real_loc[pars.uniforms[i].custom_loc] = loc;
- }
-
-
- // attributes
- max = 0;
-
- for( uint i=0; i<pars.attributes.size(); ++i )
- {
- if( pars.attributes[i].custom_loc > max )
- max = pars.attributes[i].custom_loc;
- }
- custom_attrib_loc_to_real_loc.assign( max + 1, -1 );
- for( uint i=0; i<pars.attributes.size(); ++i )
- {
- if( custom_attrib_loc_to_real_loc[ pars.attributes[i].custom_loc ] != -1 )
- {
- SHADER_ERROR( "The attribute \"" << pars.attributes[i].name << "\" has the same value with another one" );
- return false;
- }
- int loc = GetAttributeLocation( pars.attributes[i].name.c_str() );
- if( loc == -1 )
- {
- SHADER_ERROR( "Check the previous error" );
- return false;
- }
- custom_attrib_loc_to_real_loc[pars.attributes[i].custom_loc] = loc;
- }
- return true;
- }
- //=====================================================================================================================================
- // Load =
- //=====================================================================================================================================
- bool shader_prog_t::Load( const char* filename )
- {
- if( !CustomLoad( filename, "" ) ) return false;
- return true;
- }
- //=====================================================================================================================================
- // CustomLoad =
- //=====================================================================================================================================
- bool shader_prog_t::CustomLoad( const char* filename, const char* extra_source )
- {
- if( GetName().length() == 0 )
- {
- name = util::CutPath( filename );
- path = util::GetPath( filename );
- }
- shader_parser_t pars;
- if( !pars.ParseFile( filename ) ) return false;
- // create, compile, attach and link
- string preproc_source = r::GetStdShaderPreprocDefines() + extra_source;
- uint vert_gl_id = CreateAndCompileShader( pars.vert_shader_source.c_str(), preproc_source.c_str(), GL_VERTEX_SHADER );
- if( vert_gl_id == 0 ) return false;
- uint frag_gl_id = CreateAndCompileShader( pars.frag_shader_source.c_str(), preproc_source.c_str(), GL_FRAGMENT_SHADER );
- if( frag_gl_id == 0 ) return false;
- gl_id = glCreateProgram();
- glAttachShader( gl_id, vert_gl_id );
- glAttachShader( gl_id, frag_gl_id );
- if( !Link() ) return false;
-
-
- // init the rest
- GetUniAndAttribLocs();
- if( !FillTheCustomLocationsVectors( pars ) ) return false;
- return true;
- }
- //=====================================================================================================================================
- // GetUniformLocation =
- //=====================================================================================================================================
- int shader_prog_t::GetUniformLocation( const char* name ) const
- {
- DEBUG_ERR( gl_id == 0 ); // not initialized
- ntlit_t it = uni_name_to_loc.find( name );
- if( it == uni_name_to_loc.end() )
- {
- SHADER_ERROR( "Cannot get uniform loc \"" << name << '\"' );
- return -1;
- }
- return it->second;
- }
- //=====================================================================================================================================
- // GetAttributeLocation =
- //=====================================================================================================================================
- int shader_prog_t::GetAttributeLocation( const char* name ) const
- {
- DEBUG_ERR( gl_id == 0 ); // not initialized
- ntlit_t it = attrib_name_to_loc.find( name );
- if( it == attrib_name_to_loc.end() )
- {
- SHADER_ERROR( "Cannot get attrib loc \"" << name << '\"' );
- return -1;
- }
- return it->second;
- }
- //=====================================================================================================================================
- // GetUniformLocationSilently =
- //=====================================================================================================================================
- int shader_prog_t::GetUniformLocationSilently( const char* name ) const
- {
- DEBUG_ERR( gl_id == 0 ); // not initialized
- ntlit_t it = uni_name_to_loc.find( name );
- if( it == uni_name_to_loc.end() )
- {
- return -1;
- }
- return it->second;
- }
- //=====================================================================================================================================
- // GetAttributeLocationSilently =
- //=====================================================================================================================================
- int shader_prog_t::GetAttributeLocationSilently( const char* name ) const
- {
- DEBUG_ERR( gl_id == 0 ); // not initialized
- ntlit_t it = attrib_name_to_loc.find( name );
- if( it == attrib_name_to_loc.end() )
- {
- return -1;
- }
- return it->second;
- }
- //=====================================================================================================================================
- // GetUniformLocation =
- //=====================================================================================================================================
- int shader_prog_t::GetUniformLocation( int id ) const
- {
- DEBUG_ERR( uint(id) >= custom_uni_loc_to_real_loc.size() );
- DEBUG_ERR( custom_uni_loc_to_real_loc[id] == -1 );
- return custom_uni_loc_to_real_loc[id];
- }
- //=====================================================================================================================================
- // GetAttributeLocation =
- //=====================================================================================================================================
- int shader_prog_t::GetAttributeLocation( int id ) const
- {
- DEBUG_ERR( uint(id) >= custom_attrib_loc_to_real_loc.size() );
- DEBUG_ERR( custom_attrib_loc_to_real_loc[id] == -1 );
- return custom_attrib_loc_to_real_loc[id];
- }
- //=====================================================================================================================================
- // LocTexUnit =
- //=====================================================================================================================================
- void shader_prog_t::LocTexUnit( int loc, const texture_t& tex, uint tex_unit ) const
- {
- DEBUG_ERR( loc == -1 );
- DEBUG_ERR( GetCurrentProgram() != gl_id );
- tex.Bind( tex_unit );
- glUniform1i( loc, tex_unit );
- }
- void shader_prog_t::LocTexUnit( const char* loc, const texture_t& tex, uint tex_unit ) const
- {
- DEBUG_ERR( GetCurrentProgram() != gl_id );
- tex.Bind( tex_unit );
- glUniform1i( GetUniformLocation(loc), tex_unit );
- }
|