ShaderProg.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. #include "ShaderProg.h"
  2. #include "Renderer.h"
  3. #include "ShaderPrePreprocessor.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. attribVars.reserve( num );
  88. for( int i=0; i<num; i++ ) // loop all attributes
  89. {
  90. glGetActiveAttrib( glId, i, sizeof(name_)/sizeof(char), &length, &size, &type, name_ );
  91. name_[ length ] = '\0';
  92. // check if its FFP location
  93. int loc = glGetAttribLocation(glId, name_);
  94. if( loc == -1 ) // if -1 it means that its an FFP var
  95. {
  96. //SHADER_WARNING( "You are using FFP vertex attributes (\"" << name_ << "\")" );
  97. continue;
  98. }
  99. attribVars.push_back( Var( loc, name_, type, Var::SVT_ATTRIBUTE ) );
  100. attribNameToVar[ name_ ] = &attribVars.back();
  101. }
  102. // uni locations
  103. glGetProgramiv( glId, GL_ACTIVE_UNIFORMS, &num );
  104. uniVars.reserve( num );
  105. for( int i=0; i<num; i++ ) // loop all uniforms
  106. {
  107. glGetActiveUniform( glId, i, sizeof(name_)/sizeof(char), &length, &size, &type, name_ );
  108. name_[ length ] = '\0';
  109. // check if its FFP location
  110. int loc = glGetUniformLocation(glId, name_);
  111. if( loc == -1 ) // if -1 it means that its an FFP var
  112. {
  113. //SHADER_WARNING( "You are using FFP uniforms (\"" << name_ << "\")" );
  114. continue;
  115. }
  116. uniVars.push_back( Var( loc, name_, type, Var::SVT_UNIFORM ) );
  117. uniNameToVar[ name_ ] = &uniVars.back();
  118. }
  119. }
  120. //=====================================================================================================================================
  121. // bindCustomAttribLocs =
  122. //=====================================================================================================================================
  123. bool ShaderProg::bindCustomAttribLocs( const ShaderPrePreprocessor& pars ) const
  124. {
  125. for( uint i=0; i<pars.getOutput().getAttribLocs().size(); ++i )
  126. {
  127. const string& name = pars.getOutput().getAttribLocs()[i].name;
  128. int loc = pars.getOutput().getAttribLocs()[i].customLoc;
  129. glBindAttribLocation( glId, loc, name.c_str() );
  130. // check for error
  131. GLenum errId = glGetError();
  132. if( errId != GL_NO_ERROR )
  133. {
  134. SHADER_ERROR( "Something went wrong for attrib \"" << name << "\" and location " << loc << " (" << gluErrorString( errId ) << ")" );
  135. return false;
  136. }
  137. }
  138. return true;
  139. }
  140. //=====================================================================================================================================
  141. // load =
  142. //=====================================================================================================================================
  143. bool ShaderProg::load( const char* filename )
  144. {
  145. if( !customLoad( filename, "" ) ) return false;
  146. return true;
  147. }
  148. //=====================================================================================================================================
  149. // customLoad =
  150. //=====================================================================================================================================
  151. bool ShaderProg::customLoad( const char* filename, const char* extraSource )
  152. {
  153. if( getRsrcName().length() == 0 )
  154. {
  155. name = Util::cutPath( filename );
  156. path = Util::getPath( filename );
  157. }
  158. ShaderPrePreprocessor pars;
  159. if( !pars.parseFile( filename ) ) return false;
  160. // 1) create and compile the shaders
  161. string preprocSource = R::getStdShaderPreprocDefines() + extraSource;
  162. uint vertGlId = createAndCompileShader( pars.getOutput().getVertShaderSource().c_str(), preprocSource.c_str(), GL_VERTEX_SHADER );
  163. if( vertGlId == 0 ) return false;
  164. uint fragGlId = createAndCompileShader( pars.getOutput().getFragShaderSource().c_str(), preprocSource.c_str(), GL_FRAGMENT_SHADER );
  165. if( fragGlId == 0 ) return false;
  166. // 2) create program and attach shaders
  167. glId = glCreateProgram();
  168. glAttachShader( glId, vertGlId );
  169. glAttachShader( glId, fragGlId );
  170. // 3) bind the custom attrib locs
  171. if( !bindCustomAttribLocs( pars ) ) return false;
  172. // 5) link
  173. if( !link() ) return false;
  174. // init the rest
  175. getUniAndAttribVars();
  176. return true;
  177. }
  178. //=====================================================================================================================================
  179. // getUniVar =
  180. //=====================================================================================================================================
  181. const ShaderProg::Var& ShaderProg::getUniVar( const char* name ) const
  182. {
  183. NameToVarIterator it = uniNameToVar.find( name );
  184. if( it == uniNameToVar.end() )
  185. {
  186. SHADER_ERROR( "Cannot get uniform loc \"" << name << '\"' );
  187. return dummyVar;
  188. }
  189. return *(it->second);
  190. }
  191. //=====================================================================================================================================
  192. // getAttribVar =
  193. //=====================================================================================================================================
  194. const ShaderProg::Var& ShaderProg::getAttribVar( const char* name ) const
  195. {
  196. NameToVarIterator it = attribNameToVar.find( name );
  197. if( it == attribNameToVar.end() )
  198. {
  199. SHADER_ERROR( "Cannot get attribute loc \"" << name << '\"' );
  200. return dummyVar;
  201. }
  202. return *(it->second);
  203. }
  204. //=====================================================================================================================================
  205. // uniVarExists =
  206. //=====================================================================================================================================
  207. bool ShaderProg::uniVarExists( const char* name ) const
  208. {
  209. NameToVarIterator it = uniNameToVar.find( name );
  210. return it != uniNameToVar.end();
  211. }
  212. //=====================================================================================================================================
  213. // attribVarExists =
  214. //=====================================================================================================================================
  215. bool ShaderProg::attribVarExists( const char* name ) const
  216. {
  217. NameToVarIterator it = attribNameToVar.find( name );
  218. return it != attribNameToVar.end();
  219. }
  220. //=====================================================================================================================================
  221. // locTexUnit =
  222. //=====================================================================================================================================
  223. void ShaderProg::locTexUnit( int loc, const Texture& tex, uint tex_unit ) const
  224. {
  225. DEBUG_ERR( loc == -1 );
  226. DEBUG_ERR( getCurrentProgramGlId() != glId );
  227. tex.bind( tex_unit );
  228. glUniform1i( loc, tex_unit );
  229. }
  230. void ShaderProg::locTexUnit( const char* loc, const Texture& tex, uint tex_unit ) const
  231. {
  232. DEBUG_ERR( getCurrentProgramGlId() != glId );
  233. tex.bind( tex_unit );
  234. glUniform1i( getUniVar(loc).getLoc(), tex_unit );
  235. }