ShaderProg.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. #include "ShaderProg.h"
  2. #include "Renderer.h"
  3. #include "ShaderParser.h"
  4. #include "Texture.h"
  5. #define SHADER_ERROR( x ) ERROR( "Shader (" << getRsrcName() << "): " << x )
  6. #define SHADER_WARNING( x ) WARNING( "Shader (" << getRsrcName() << "): " << x )
  7. //=====================================================================================================================================
  8. // createAndCompileShader =
  9. //=====================================================================================================================================
  10. uint ShaderProg::createAndCompileShader( const char* sourceCode, const char* preproc, int type ) const
  11. {
  12. uint glId = 0;
  13. const char* source_strs[2] = {NULL, NULL};
  14. // create the shader
  15. glId = glCreateShader( type );
  16. // attach the source
  17. source_strs[1] = sourceCode;
  18. source_strs[0] = preproc;
  19. // compile
  20. glShaderSource( glId, 2, source_strs, NULL );
  21. glCompileShader( glId );
  22. int success;
  23. glGetShaderiv( glId, GL_COMPILE_STATUS, &success );
  24. if( !success )
  25. {
  26. // print info log
  27. int info_len = 0;
  28. int chars_written = 0;
  29. char* info_log = NULL;
  30. glGetShaderiv( glId, GL_INFO_LOG_LENGTH, &info_len );
  31. info_log = (char*)malloc( (info_len+1)*sizeof(char) );
  32. glGetShaderInfoLog( glId, info_len, &chars_written, info_log );
  33. const char* shader_type;
  34. switch( type )
  35. {
  36. case GL_VERTEX_SHADER:
  37. shader_type = "Vertex shader";
  38. break;
  39. case GL_FRAGMENT_SHADER:
  40. shader_type = "Fragment shader";
  41. break;
  42. default:
  43. DEBUG_ERR( 1 ); // Not supported
  44. }
  45. SHADER_ERROR( shader_type << " compiler log follows:\n" << info_log );
  46. free( info_log );
  47. return 0;
  48. }
  49. return glId;
  50. }
  51. //=====================================================================================================================================
  52. // link =
  53. //=====================================================================================================================================
  54. bool ShaderProg::link()
  55. {
  56. // link
  57. glLinkProgram( glId );
  58. // check if linked correctly
  59. int success;
  60. glGetProgramiv( glId, GL_LINK_STATUS, &success );
  61. if( !success )
  62. {
  63. int info_len = 0;
  64. int chars_written = 0;
  65. char* info_log_txt = NULL;
  66. glGetProgramiv( glId, GL_INFO_LOG_LENGTH, &info_len );
  67. info_log_txt = (char*)malloc( (info_len+1)*sizeof(char) );
  68. glGetProgramInfoLog( glId, info_len, &chars_written, info_log_txt );
  69. SHADER_ERROR( "Link log follows:\n" << info_log_txt );
  70. free( info_log_txt );
  71. return false;
  72. }
  73. return true;
  74. }
  75. //=====================================================================================================================================
  76. // getUniAndAttribVars =
  77. //=====================================================================================================================================
  78. void ShaderProg::getUniAndAttribVars()
  79. {
  80. int num;
  81. char name_[256];
  82. GLsizei length;
  83. GLint size;
  84. GLenum type;
  85. // attrib locations
  86. glGetProgramiv( glId, GL_ACTIVE_ATTRIBUTES, &num );
  87. for( int i=0; i<num; i++ ) // loop all attributes
  88. {
  89. glGetActiveAttrib( glId, i, sizeof(name_)/sizeof(char), &length, &size, &type, name_ );
  90. name_[ length ] = '\0';
  91. // check if its FFP location
  92. int loc = glGetAttribLocation(glId, name_);
  93. if( loc == -1 ) // if -1 it means that its an FFP var
  94. {
  95. //SHADER_WARNING( "You are using FFP vertex attributes (\"" << name_ << "\")" );
  96. continue;
  97. }
  98. attribNameToLoc[ name_ ] = loc; //ToDo to be removed
  99. attribVars.push_back( Var( loc, name_, type, Var::LT_ATTRIBUTE ) );
  100. attribNameToVar[ name_ ] = &attribVars.back();
  101. }
  102. // uni locations
  103. glGetProgramiv( glId, GL_ACTIVE_UNIFORMS, &num );
  104. for( int i=0; i<num; i++ ) // loop all uniforms
  105. {
  106. glGetActiveUniform( glId, i, sizeof(name_)/sizeof(char), &length, &size, &type, name_ );
  107. name_[ length ] = '\0';
  108. // check if its FFP location
  109. int loc = glGetUniformLocation(glId, name_);
  110. if( loc == -1 ) // if -1 it means that its an FFP var
  111. {
  112. //SHADER_WARNING( "You are using FFP uniforms (\"" << name_ << "\")" );
  113. continue;
  114. }
  115. uniNameToLoc[ name_ ] = loc;
  116. uniVars.push_back( Var( loc, name_, type, Var::LT_UNIFORM ) );
  117. uniNameToVar[ name_ ] = &uniVars.back();
  118. }
  119. }
  120. //=====================================================================================================================================
  121. // fillTheCustomLocationsVectors =
  122. //=====================================================================================================================================
  123. bool ShaderProg::fillTheCustomLocationsVectors( const ShaderParser& pars )
  124. {
  125. bind();
  126. uint max = 0;
  127. // uniforms
  128. for( uint i=0; i<pars.getOutput().getUniLocs().size(); ++i )
  129. {
  130. if( pars.getOutput().getUniLocs()[i].customLoc > max )
  131. max = pars.getOutput().getUniLocs()[i].customLoc;
  132. }
  133. customUniLocToRealLoc.assign( max + 1, -1 );
  134. for( uint i=0; i<pars.getOutput().getUniLocs().size(); ++i )
  135. {
  136. if( customUniLocToRealLoc[ pars.getOutput().getUniLocs()[i].customLoc ] != -1 )
  137. {
  138. SHADER_ERROR( "The uniform \"" << pars.getOutput().getUniLocs()[i].name << "\" has the same value with another one" );
  139. return false;
  140. }
  141. int loc = getUniVar( pars.getOutput().getUniLocs()[i].name.c_str() ).getLoc();
  142. if( loc == -1 )
  143. {
  144. SHADER_WARNING( "Check the previous error" );
  145. continue;
  146. }
  147. customUniLocToRealLoc[pars.getOutput().getUniLocs()[i].customLoc] = loc;
  148. }
  149. // attributes
  150. max = 0;
  151. for( uint i=0; i<pars.getOutput().getAttribLocs().size(); ++i )
  152. {
  153. if( pars.getOutput().getAttribLocs()[i].customLoc > max )
  154. max = pars.getOutput().getAttribLocs()[i].customLoc;
  155. }
  156. customAttribLocToRealLoc.assign( max + 1, -1 );
  157. for( uint i=0; i<pars.getOutput().getAttribLocs().size(); ++i )
  158. {
  159. if( customAttribLocToRealLoc[ pars.getOutput().getAttribLocs()[i].customLoc ] != -1 )
  160. {
  161. SHADER_ERROR( "The attribute \"" << pars.getOutput().getAttribLocs()[i].name << "\" has the same value with another one" );
  162. return false;
  163. }
  164. int loc = getAttribVar( pars.getOutput().getAttribLocs()[i].name.c_str() ).getLoc();
  165. if( loc == -1 )
  166. {
  167. SHADER_ERROR( "Check the previous error" );
  168. return false;
  169. }
  170. customAttribLocToRealLoc[pars.getOutput().getAttribLocs()[i].customLoc] = loc;
  171. }
  172. return true;
  173. }
  174. //=====================================================================================================================================
  175. // bindCustomAttribLocs =
  176. //=====================================================================================================================================
  177. bool ShaderProg::bindCustomAttribLocs( const ShaderParser& pars ) const
  178. {
  179. for( uint i=0; i<pars.getOutput().getAttribLocs().size(); ++i )
  180. {
  181. const string& name = pars.getOutput().getAttribLocs()[i].name;
  182. int loc = pars.getOutput().getAttribLocs()[i].customLoc;
  183. glBindAttribLocation( glId, loc, name.c_str() );
  184. // check for error
  185. GLenum errId = glGetError();
  186. if( errId != GL_NO_ERROR )
  187. {
  188. SHADER_ERROR( "Something went wrong for attrib \"" << name << "\" and location " << loc << " (" << gluErrorString( errId ) << ")" );
  189. return false;
  190. }
  191. }
  192. return true;
  193. }
  194. //=====================================================================================================================================
  195. // load =
  196. //=====================================================================================================================================
  197. bool ShaderProg::load( const char* filename )
  198. {
  199. if( !customload( filename, "" ) ) return false;
  200. return true;
  201. }
  202. //=====================================================================================================================================
  203. // customload =
  204. //=====================================================================================================================================
  205. bool ShaderProg::customload( const char* filename, const char* extraSource )
  206. {
  207. if( getRsrcName().length() == 0 )
  208. {
  209. name = Util::cutPath( filename );
  210. path = Util::getPath( filename );
  211. }
  212. ShaderParser pars;
  213. if( !pars.parseFile( filename ) ) return false;
  214. // 1) create and compile the shaders
  215. string preproc_source = R::getStdShaderPreprocDefines() + extraSource;
  216. uint vertGlId = createAndCompileShader( pars.getOutput().getVertShaderSource().c_str(), preproc_source.c_str(), GL_VERTEX_SHADER );
  217. if( vertGlId == 0 ) return false;
  218. uint fragGlId = createAndCompileShader( pars.getOutput().getFragShaderSource().c_str(), preproc_source.c_str(), GL_FRAGMENT_SHADER );
  219. if( fragGlId == 0 ) return false;
  220. // 2) create program and attach shaders
  221. glId = glCreateProgram();
  222. glAttachShader( glId, vertGlId );
  223. glAttachShader( glId, fragGlId );
  224. // 3) bind the custom attrib locs
  225. if( !bindCustomAttribLocs( pars ) ) return false;
  226. // 5) link
  227. if( !link() ) return false;
  228. // init the rest
  229. getUniAndAttribVars();
  230. if( !fillTheCustomLocationsVectors( pars ) ) return false;
  231. return true;
  232. }
  233. //=====================================================================================================================================
  234. // getUniLoc =
  235. //=====================================================================================================================================
  236. int ShaderProg::getUniLoc( int id ) const
  237. {
  238. DEBUG_ERR( uint(id) >= customUniLocToRealLoc.size() );
  239. DEBUG_ERR( customUniLocToRealLoc[id] == -1 );
  240. return customUniLocToRealLoc[id];
  241. }
  242. //=====================================================================================================================================
  243. // getAttribLoc =
  244. //=====================================================================================================================================
  245. int ShaderProg::getAttribLoc( int id ) const
  246. {
  247. DEBUG_ERR( uint(id) >= customAttribLocToRealLoc.size() );
  248. DEBUG_ERR( customAttribLocToRealLoc[id] == -1 );
  249. return customAttribLocToRealLoc[id];
  250. }
  251. //=====================================================================================================================================
  252. // getUniVar =
  253. //=====================================================================================================================================
  254. const ShaderProg::Var& ShaderProg::getUniVar( const char* name ) const
  255. {
  256. NameToVarIterator it = uniNameToVar.find( name );
  257. if( it == uniNameToVar.end() )
  258. {
  259. SHADER_ERROR( "Cannot get uniform loc \"" << name << '\"' );
  260. }
  261. return *(it->second);
  262. }
  263. //=====================================================================================================================================
  264. // getAttribVar =
  265. //=====================================================================================================================================
  266. const ShaderProg::Var& ShaderProg::getAttribVar( const char* name ) const
  267. {
  268. NameToVarIterator it = attribNameToVar.find( name );
  269. if( it == attribNameToVar.end() )
  270. {
  271. SHADER_ERROR( "Cannot get attribute loc \"" << name << '\"' );
  272. }
  273. return *(it->second);
  274. }
  275. //=====================================================================================================================================
  276. // uniVarExists =
  277. //=====================================================================================================================================
  278. bool ShaderProg::uniVarExists( const char* name ) const
  279. {
  280. NameToVarIterator it = uniNameToVar.find( name );
  281. return it != uniNameToVar.end();
  282. }
  283. //=====================================================================================================================================
  284. // attribVarExists =
  285. //=====================================================================================================================================
  286. bool ShaderProg::attribVarExists( const char* name ) const
  287. {
  288. NameToVarIterator it = attribNameToVar.find( name );
  289. return it != attribNameToVar.end();
  290. }
  291. //=====================================================================================================================================
  292. // locTexUnit =
  293. //=====================================================================================================================================
  294. void ShaderProg::locTexUnit( int loc, const Texture& tex, uint tex_unit ) const
  295. {
  296. DEBUG_ERR( loc == -1 );
  297. DEBUG_ERR( getCurrentProgramGlId() != glId );
  298. tex.bind( tex_unit );
  299. glUniform1i( loc, tex_unit );
  300. }
  301. void ShaderProg::locTexUnit( const char* loc, const Texture& tex, uint tex_unit ) const
  302. {
  303. DEBUG_ERR( getCurrentProgramGlId() != glId );
  304. tex.bind( tex_unit );
  305. glUniform1i( getUniVar(loc).getLoc(), tex_unit );
  306. }