ShaderProg.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. #include "ShaderProg.h"
  2. #include "renderer.h"
  3. #include "ShaderParser.h"
  4. #include "Texture.h"
  5. #define SHADER_ERROR( x ) ERROR( "Shader (" << getName() << "): " << x )
  6. #define SHADER_WARNING( x ) WARNING( "Shader (" << getName() << "): " << x )
  7. //=====================================================================================================================================
  8. // createAndCompileShader =
  9. //=====================================================================================================================================
  10. uint ShaderProg::createAndCompileShader( const char* source_code, 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] = source_code;
  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. // getUniAndAttribLocs =
  77. //=====================================================================================================================================
  78. void ShaderProg::getUniAndAttribLocs()
  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 )
  94. {
  95. //SHADER_WARNING( "You are using FFP vertex attributes (\"" << name_ << "\")" );
  96. continue;
  97. }
  98. attribNameToLoc[ name_ ] = loc;
  99. }
  100. // uni locations
  101. glGetProgramiv( glId, GL_ACTIVE_UNIFORMS, &num );
  102. for( int i=0; i<num; i++ ) // loop all uniforms
  103. {
  104. glGetActiveUniform( glId, i, sizeof(name_)/sizeof(char), &length, &size, &type, name_ );
  105. name_[ length ] = '\0';
  106. // check if its FFP location
  107. int loc = glGetUniformLocation(glId, name_);
  108. if( loc == -1 )
  109. {
  110. //SHADER_WARNING( "You are using FFP uniforms (\"" << name_ << "\")" );
  111. continue;
  112. }
  113. uniNameToLoc[ name_ ] = loc;
  114. }
  115. }
  116. //=====================================================================================================================================
  117. // fillTheCustomLocationsVectors =
  118. //=====================================================================================================================================
  119. bool ShaderProg::fillTheCustomLocationsVectors( const ShaderParser& pars )
  120. {
  121. bind();
  122. uint max = 0;
  123. // uniforms
  124. for( uint i=0; i<pars.getOutput().getUniLocs().size(); ++i )
  125. {
  126. if( pars.getOutput().getUniLocs()[i].customLoc > max )
  127. max = pars.getOutput().getUniLocs()[i].customLoc;
  128. }
  129. customUniLocToRealLoc.assign( max + 1, -1 );
  130. for( uint i=0; i<pars.getOutput().getUniLocs().size(); ++i )
  131. {
  132. if( customUniLocToRealLoc[ pars.getOutput().getUniLocs()[i].customLoc ] != -1 )
  133. {
  134. SHADER_ERROR( "The uniform \"" << pars.getOutput().getUniLocs()[i].name << "\" has the same value with another one" );
  135. return false;
  136. }
  137. int loc = getUniLoc( pars.getOutput().getUniLocs()[i].name.c_str() );
  138. if( loc == -1 )
  139. {
  140. SHADER_WARNING( "Check the previous error" );
  141. continue;
  142. }
  143. customUniLocToRealLoc[pars.getOutput().getUniLocs()[i].customLoc] = loc;
  144. }
  145. // attributes
  146. max = 0;
  147. for( uint i=0; i<pars.getOutput().getAttribLocs().size(); ++i )
  148. {
  149. if( pars.getOutput().getAttribLocs()[i].customLoc > max )
  150. max = pars.getOutput().getAttribLocs()[i].customLoc;
  151. }
  152. customAttribLocToRealLoc.assign( max + 1, -1 );
  153. for( uint i=0; i<pars.getOutput().getAttribLocs().size(); ++i )
  154. {
  155. if( customAttribLocToRealLoc[ pars.getOutput().getAttribLocs()[i].customLoc ] != -1 )
  156. {
  157. SHADER_ERROR( "The attribute \"" << pars.getOutput().getAttribLocs()[i].name << "\" has the same value with another one" );
  158. return false;
  159. }
  160. int loc = getAttribLoc( pars.getOutput().getAttribLocs()[i].name.c_str() );
  161. if( loc == -1 )
  162. {
  163. SHADER_ERROR( "Check the previous error" );
  164. return false;
  165. }
  166. customAttribLocToRealLoc[pars.getOutput().getAttribLocs()[i].customLoc] = loc;
  167. }
  168. return true;
  169. }
  170. //=====================================================================================================================================
  171. // load =
  172. //=====================================================================================================================================
  173. bool ShaderProg::load( const char* filename )
  174. {
  175. if( !customload( filename, "" ) ) return false;
  176. return true;
  177. }
  178. //=====================================================================================================================================
  179. // customload =
  180. //=====================================================================================================================================
  181. bool ShaderProg::customload( const char* filename, const char* extra_source )
  182. {
  183. if( getName().length() == 0 )
  184. {
  185. name = Util::cutPath( filename );
  186. path = Util::getPath( filename );
  187. }
  188. ShaderParser pars;
  189. if( !pars.parseFile( filename ) ) return false;
  190. // create, compile, attach and link
  191. string preproc_source = r::GetStdShaderPreprocDefines() + extra_source;
  192. uint vert_glId = createAndCompileShader( pars.getOutput().getVertShaderSource().c_str(), preproc_source.c_str(), GL_VERTEX_SHADER );
  193. if( vert_glId == 0 ) return false;
  194. uint frag_glId = createAndCompileShader( pars.getOutput().getFragShaderSource().c_str(), preproc_source.c_str(), GL_FRAGMENT_SHADER );
  195. if( frag_glId == 0 ) return false;
  196. glId = glCreateProgram();
  197. glAttachShader( glId, vert_glId );
  198. glAttachShader( glId, frag_glId );
  199. if( !link() ) return false;
  200. // init the rest
  201. getUniAndAttribLocs();
  202. if( !fillTheCustomLocationsVectors( pars ) ) return false;
  203. return true;
  204. }
  205. //=====================================================================================================================================
  206. // getUniLoc =
  207. //=====================================================================================================================================
  208. int ShaderProg::getUniLoc( const char* name ) const
  209. {
  210. DEBUG_ERR( glId == 0 ); // not initialized
  211. NameToLocIterator it = uniNameToLoc.find( name );
  212. if( it == uniNameToLoc.end() )
  213. {
  214. SHADER_ERROR( "Cannot get uniform loc \"" << name << '\"' );
  215. return -1;
  216. }
  217. return it->second;
  218. }
  219. //=====================================================================================================================================
  220. // getAttribLoc =
  221. //=====================================================================================================================================
  222. int ShaderProg::getAttribLoc( const char* name ) const
  223. {
  224. DEBUG_ERR( glId == 0 ); // not initialized
  225. NameToLocIterator it = attribNameToLoc.find( name );
  226. if( it == attribNameToLoc.end() )
  227. {
  228. SHADER_ERROR( "Cannot get attrib loc \"" << name << '\"' );
  229. return -1;
  230. }
  231. return it->second;
  232. }
  233. //=====================================================================================================================================
  234. // getUniLocSilently =
  235. //=====================================================================================================================================
  236. int ShaderProg::getUniLocSilently( const char* name ) const
  237. {
  238. DEBUG_ERR( glId == 0 ); // not initialized
  239. NameToLocIterator it = uniNameToLoc.find( name );
  240. if( it == uniNameToLoc.end() )
  241. {
  242. return -1;
  243. }
  244. return it->second;
  245. }
  246. //=====================================================================================================================================
  247. // getAttribLocSilently =
  248. //=====================================================================================================================================
  249. int ShaderProg::getAttribLocSilently( const char* name ) const
  250. {
  251. DEBUG_ERR( glId == 0 ); // not initialized
  252. NameToLocIterator it = attribNameToLoc.find( name );
  253. if( it == attribNameToLoc.end() )
  254. {
  255. return -1;
  256. }
  257. return it->second;
  258. }
  259. //=====================================================================================================================================
  260. // getUniLoc =
  261. //=====================================================================================================================================
  262. int ShaderProg::GetUniLoc( int id ) const
  263. {
  264. DEBUG_ERR( uint(id) >= customUniLocToRealLoc.size() );
  265. DEBUG_ERR( customUniLocToRealLoc[id] == -1 );
  266. return customUniLocToRealLoc[id];
  267. }
  268. //=====================================================================================================================================
  269. // getAttribLoc =
  270. //=====================================================================================================================================
  271. int ShaderProg::getAttribLoc( int id ) const
  272. {
  273. DEBUG_ERR( uint(id) >= customAttribLocToRealLoc.size() );
  274. DEBUG_ERR( customAttribLocToRealLoc[id] == -1 );
  275. return customAttribLocToRealLoc[id];
  276. }
  277. //=====================================================================================================================================
  278. // locTexUnit =
  279. //=====================================================================================================================================
  280. void ShaderProg::locTexUnit( int loc, const Texture& tex, uint tex_unit ) const
  281. {
  282. DEBUG_ERR( loc == -1 );
  283. DEBUG_ERR( getCurrentProgram() != glId );
  284. tex.bind( tex_unit );
  285. glUniform1i( loc, tex_unit );
  286. }
  287. void ShaderProg::locTexUnit( const char* loc, const Texture& tex, uint tex_unit ) const
  288. {
  289. DEBUG_ERR( getCurrentProgram() != glId );
  290. tex.bind( tex_unit );
  291. glUniform1i( getUniLoc(loc), tex_unit );
  292. }