| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371 |
- #include "ShaderProg.h"
- #include "Renderer.h"
- #include "ShaderPrePreprocessor.h"
- #include "Texture.h"
- #define SHADER_ERROR( x ) ERROR( "Shader (" << getRsrcName() << "): " << x )
- #define SHADER_WARNING( x ) WARNING( "Shader (" << getRsrcName() << "): " << x )
- string ShaderProg::stdSourceCode(
- "#version 150 compatibility\n \
- precision lowp float;\n \
- #pragma optimize(on)\n \
- #pragma debug(off)\n"
- );
- //=====================================================================================================================================
- // set uniforms =
- //=====================================================================================================================================
- /**
- * Standard set uniform check
- */
- #define STD_SET_UNI_CHECK() DEBUG_ERR( getLoc() == -1 || ShaderProg::getCurrentProgramGlId() != fatherSProg->getGlId() );
- void ShaderProg::UniVar::setFloat( float f ) const
- {
- STD_SET_UNI_CHECK();
- DEBUG_ERR( getGlDataType() != GL_FLOAT );
- glUniform1f( getLoc(), f );
- }
- void ShaderProg::UniVar::setFloatVec( float f[], uint size ) const
- {
- STD_SET_UNI_CHECK();
- DEBUG_ERR( getGlDataType() != GL_FLOAT );
- glUniform1fv( getLoc(), size, f );
- }
- void ShaderProg::UniVar::setVec2( const Vec2 v2[], uint size ) const
- {
- STD_SET_UNI_CHECK();
- DEBUG_ERR( getGlDataType() != GL_FLOAT_VEC2 );
- glUniform2fv( getLoc(), size, &( const_cast<Vec2&>(v2[0]) )[0] );
- }
- void ShaderProg::UniVar::setVec3( const Vec3 v3[], uint size ) const
- {
- STD_SET_UNI_CHECK();
- DEBUG_ERR( getGlDataType() != GL_FLOAT_VEC3 );
- glUniform3fv( getLoc(), size, &( const_cast<Vec3&>(v3[0]) )[0] );
- }
- void ShaderProg::UniVar::setVec4( const Vec4 v4[], uint size ) const
- {
- STD_SET_UNI_CHECK();
- DEBUG_ERR( getGlDataType() != GL_FLOAT_VEC4 );
- glUniform4fv( getLoc(), size, &( const_cast<Vec4&>(v4[0]) )[0] );
- }
- void ShaderProg::UniVar::setMat3( const Mat3 m3[], uint size ) const
- {
- STD_SET_UNI_CHECK();
- DEBUG_ERR( getGlDataType() != GL_FLOAT_MAT3 );
- glUniformMatrix3fv( getLoc(), size, true, &(m3[0])[0] );
- }
- void ShaderProg::UniVar::setMat4( const Mat4 m4[], uint size ) const
- {
- STD_SET_UNI_CHECK();
- DEBUG_ERR( getGlDataType() != GL_FLOAT_MAT4 );
- glUniformMatrix4fv( getLoc(), size, true, &(m4[0])[0] );
- }
- void ShaderProg::UniVar::setTexture( const Texture& tex, uint texUnit ) const
- {
- STD_SET_UNI_CHECK();
- DEBUG_ERR( getGlDataType() != GL_TEXTURE_2D );
- tex.bind( texUnit );
- glUniform1i( getLoc(), texUnit );
- }
- //=====================================================================================================================================
- // createAndCompileShader =
- //=====================================================================================================================================
- uint ShaderProg::createAndCompileShader( const char* sourceCode, const char* preproc, int type ) const
- {
- uint glId = 0;
- const char* sourceStrs[2] = {NULL, NULL};
- // create the shader
- glId = glCreateShader( type );
- // attach the source
- sourceStrs[1] = sourceCode;
- sourceStrs[0] = preproc;
- // compile
- glShaderSource( glId, 2, sourceStrs, NULL );
- glCompileShader( glId );
- int success;
- glGetShaderiv( glId, GL_COMPILE_STATUS, &success );
- if( !success )
- {
- // print info log
- int info_len = 0;
- int charsWritten = 0;
- char* infoLog = NULL;
- glGetShaderiv( glId, GL_INFO_LOG_LENGTH, &info_len );
- infoLog = (char*)malloc( (info_len+1)*sizeof(char) );
- glGetShaderInfoLog( glId, info_len, &charsWritten, infoLog );
-
- const char* shaderType;
- switch( type )
- {
- case GL_VERTEX_SHADER:
- shaderType = "Vertex shader";
- break;
- case GL_FRAGMENT_SHADER:
- shaderType = "Fragment shader";
- break;
- default:
- DEBUG_ERR( 1 ); // Not supported
- }
- SHADER_ERROR( shaderType << " compiler log follows:\n" << infoLog );
-
- free( infoLog );
- return 0;
- }
- return glId;
- }
- //=====================================================================================================================================
- // link =
- //=====================================================================================================================================
- bool ShaderProg::link()
- {
- // link
- glLinkProgram( glId );
- // check if linked correctly
- int success;
- glGetProgramiv( glId, GL_LINK_STATUS, &success );
- if( !success )
- {
- int info_len = 0;
- int chars_written = 0;
- char* info_log_txt = NULL;
- glGetProgramiv( glId, GL_INFO_LOG_LENGTH, &info_len );
- info_log_txt = (char*)malloc( (info_len+1)*sizeof(char) );
- glGetProgramInfoLog( glId, info_len, &chars_written, info_log_txt );
- SHADER_ERROR( "Link log follows:\n" << info_log_txt );
- free( info_log_txt );
- return false;
- }
- return true;
- }
- //=====================================================================================================================================
- // getUniAndAttribVars =
- //=====================================================================================================================================
- void ShaderProg::getUniAndAttribVars()
- {
- int num;
- char name_[256];
- GLsizei length;
- GLint size;
- GLenum type;
- // attrib locations
- glGetProgramiv( glId, GL_ACTIVE_ATTRIBUTES, &num );
- attribVars.reserve( num );
- for( int i=0; i<num; i++ ) // loop all attributes
- {
- glGetActiveAttrib( glId, i, sizeof(name_)/sizeof(char), &length, &size, &type, name_ );
- name_[ length ] = '\0';
- // check if its FFP location
- int loc = glGetAttribLocation(glId, name_);
- if( loc == -1 ) // if -1 it means that its an FFP var
- {
- //SHADER_WARNING( "You are using FFP vertex attributes (\"" << name_ << "\")" );
- continue;
- }
- attribVars.push_back( AttribVar( loc, name_, type, this ) );
- attribNameToVar[ name_ ] = &attribVars.back();
- }
- // uni locations
- glGetProgramiv( glId, GL_ACTIVE_UNIFORMS, &num );
- uniVars.reserve( num );
- for( int i=0; i<num; i++ ) // loop all uniforms
- {
- glGetActiveUniform( glId, i, sizeof(name_)/sizeof(char), &length, &size, &type, name_ );
- name_[ length ] = '\0';
- // check if its FFP location
- int loc = glGetUniformLocation(glId, name_);
- if( loc == -1 ) // if -1 it means that its an FFP var
- {
- //SHADER_WARNING( "You are using FFP uniforms (\"" << name_ << "\")" );
- continue;
- }
- uniVars.push_back( UniVar( loc, name_, type, this ) );
- uniNameToVar[ name_ ] = &uniVars.back();
- }
- }
- //=====================================================================================================================================
- // bindCustomAttribLocs =
- //=====================================================================================================================================
- bool ShaderProg::bindCustomAttribLocs( const ShaderPrePreprocessor& pars ) const
- {
- for( uint i=0; i<pars.getOutput().getAttribLocs().size(); ++i )
- {
- const string& name = pars.getOutput().getAttribLocs()[i].name;
- int loc = pars.getOutput().getAttribLocs()[i].customLoc;
- glBindAttribLocation( glId, loc, name.c_str() );
- // check for error
- GLenum errId = glGetError();
- if( errId != GL_NO_ERROR )
- {
- SHADER_ERROR( "Something went wrong for attrib \"" << name << "\" and location " << loc << " (" << gluErrorString( errId ) << ")" );
- return false;
- }
- }
- return true;
- }
- //=====================================================================================================================================
- // load =
- //=====================================================================================================================================
- bool ShaderProg::load( const char* filename )
- {
- if( !customLoad( filename, "" ) ) return false;
- return true;
- }
- //=====================================================================================================================================
- // customLoad =
- //=====================================================================================================================================
- bool ShaderProg::customLoad( const char* filename, const char* extraSource )
- {
- if( getRsrcName().length() == 0 )
- {
- name = Util::cutPath( filename );
- path = Util::getPath( filename );
- }
- ShaderPrePreprocessor pars;
- if( !pars.parseFile( filename ) ) return false;
- // 1) create and compile the shaders
- string preprocSource = stdSourceCode + extraSource;
- uint vertGlId = createAndCompileShader( pars.getOutput().getVertShaderSource().c_str(), preprocSource.c_str(), GL_VERTEX_SHADER );
- if( vertGlId == 0 ) return false;
- uint fragGlId = createAndCompileShader( pars.getOutput().getFragShaderSource().c_str(), preprocSource.c_str(), GL_FRAGMENT_SHADER );
- if( fragGlId == 0 ) return false;
- // 2) create program and attach shaders
- glId = glCreateProgram();
- if( glId == 0 )
- {
- ERROR( "glCreateProgram failed" );
- return false;
- }
- glAttachShader( glId, vertGlId );
- glAttachShader( glId, fragGlId );
- // 3) bind the custom attrib locs
- if( !bindCustomAttribLocs( pars ) ) return false;
- // 5) link
- if( !link() ) return false;
-
- // init the rest
- getUniAndAttribVars();
- return true;
- }
- //=====================================================================================================================================
- // findUniVar =
- //=====================================================================================================================================
- const ShaderProg::UniVar* ShaderProg::findUniVar( const char* name ) const
- {
- NameToUniVarIterator it = uniNameToVar.find( name );
- if( it == uniNameToVar.end() )
- {
- SHADER_ERROR( "Cannot get uniform loc \"" << name << '\"' );
- return NULL;
- }
- return it->second;
- }
- //=====================================================================================================================================
- // findAttribVar =
- //=====================================================================================================================================
- const ShaderProg::AttribVar* ShaderProg::findAttribVar( const char* name ) const
- {
- NameToAttribVarIterator it = attribNameToVar.find( name );
- if( it == attribNameToVar.end() )
- {
- SHADER_ERROR( "Cannot get attribute loc \"" << name << '\"' );
- return NULL;
- }
- return it->second;
- }
- //=====================================================================================================================================
- // uniVarExists =
- //=====================================================================================================================================
- bool ShaderProg::uniVarExists( const char* name ) const
- {
- NameToUniVarIterator it = uniNameToVar.find( name );
- return it != uniNameToVar.end();
- }
- //=====================================================================================================================================
- // attribVarExists =
- //=====================================================================================================================================
- bool ShaderProg::attribVarExists( const char* name ) const
- {
- NameToAttribVarIterator it = attribNameToVar.find( name );
- return it != attribNameToVar.end();
- }
- //=====================================================================================================================================
- // locTexUnit =
- //=====================================================================================================================================
- void ShaderProg::locTexUnit( int loc, const Texture& tex, uint tex_unit ) const
- {
- DEBUG_ERR( loc == -1 );
- DEBUG_ERR( getCurrentProgramGlId() != glId );
- tex.bind( tex_unit );
- glUniform1i( loc, tex_unit );
- }
- void ShaderProg::locTexUnit( const char* loc, const Texture& tex, uint tex_unit ) const
- {
- DEBUG_ERR( getCurrentProgramGlId() != glId );
- tex.bind( tex_unit );
- glUniform1i( findUniVar(loc)->getLoc(), tex_unit );
- }
|