RenderProgs.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #pragma hdrstop
  21. #include "../idlib/precompiled.h"
  22. #include "tr_local.h"
  23. idRenderProgManager renderProgManager;
  24. /*
  25. ================================================================================================
  26. idRenderProgManager::idRenderProgManager()
  27. ================================================================================================
  28. */
  29. idRenderProgManager::idRenderProgManager() {
  30. }
  31. /*
  32. ================================================================================================
  33. idRenderProgManager::~idRenderProgManager()
  34. ================================================================================================
  35. */
  36. idRenderProgManager::~idRenderProgManager() {
  37. }
  38. /*
  39. ================================================================================================
  40. R_ReloadShaders
  41. ================================================================================================
  42. */
  43. static void R_ReloadShaders( const idCmdArgs &args ) {
  44. renderProgManager.KillAllShaders();
  45. renderProgManager.LoadAllShaders();
  46. }
  47. /*
  48. ================================================================================================
  49. idRenderProgManager::Init()
  50. ================================================================================================
  51. */
  52. void idRenderProgManager::Init() {
  53. common->Printf( "----- Initializing Render Shaders -----\n" );
  54. for ( int i = 0; i < MAX_BUILTINS; i++ ) {
  55. builtinShaders[i] = -1;
  56. }
  57. struct builtinShaders_t {
  58. int index;
  59. const char * name;
  60. } builtins[] = {
  61. { BUILTIN_GUI, "gui.vfp" },
  62. { BUILTIN_COLOR, "color.vfp" },
  63. { BUILTIN_SIMPLESHADE, "simpleshade.vfp" },
  64. { BUILTIN_TEXTURED, "texture.vfp" },
  65. { BUILTIN_TEXTURE_VERTEXCOLOR, "texture_color.vfp" },
  66. { BUILTIN_TEXTURE_VERTEXCOLOR_SKINNED, "texture_color_skinned.vfp" },
  67. { BUILTIN_TEXTURE_TEXGEN_VERTEXCOLOR, "texture_color_texgen.vfp" },
  68. { BUILTIN_INTERACTION, "interaction.vfp" },
  69. { BUILTIN_INTERACTION_SKINNED, "interaction_skinned.vfp" },
  70. { BUILTIN_INTERACTION_AMBIENT, "interactionAmbient.vfp" },
  71. { BUILTIN_INTERACTION_AMBIENT_SKINNED, "interactionAmbient_skinned.vfp" },
  72. { BUILTIN_ENVIRONMENT, "environment.vfp" },
  73. { BUILTIN_ENVIRONMENT_SKINNED, "environment_skinned.vfp" },
  74. { BUILTIN_BUMPY_ENVIRONMENT, "bumpyEnvironment.vfp" },
  75. { BUILTIN_BUMPY_ENVIRONMENT_SKINNED, "bumpyEnvironment_skinned.vfp" },
  76. { BUILTIN_DEPTH, "depth.vfp" },
  77. { BUILTIN_DEPTH_SKINNED, "depth_skinned.vfp" },
  78. { BUILTIN_SHADOW_DEBUG, "shadowDebug.vfp" },
  79. { BUILTIN_SHADOW_DEBUG_SKINNED, "shadowDebug_skinned.vfp" },
  80. { BUILTIN_BLENDLIGHT, "blendlight.vfp" },
  81. { BUILTIN_FOG, "fog.vfp" },
  82. { BUILTIN_FOG_SKINNED, "fog_skinned.vfp" },
  83. { BUILTIN_SKYBOX, "skybox.vfp" },
  84. { BUILTIN_WOBBLESKY, "wobblesky.vfp" },
  85. { BUILTIN_POSTPROCESS, "postprocess.vfp" },
  86. { BUILTIN_STEREO_DEGHOST, "stereoDeGhost.vfp" },
  87. { BUILTIN_STEREO_WARP, "stereoWarp.vfp" },
  88. { BUILTIN_ZCULL_RECONSTRUCT, "zcullReconstruct.vfp" },
  89. { BUILTIN_BINK, "bink.vfp" },
  90. { BUILTIN_BINK_GUI, "bink_gui.vfp" },
  91. { BUILTIN_STEREO_INTERLACE, "stereoInterlace.vfp" },
  92. { BUILTIN_MOTION_BLUR, "motionBlur.vfp" },
  93. };
  94. int numBuiltins = sizeof( builtins ) / sizeof( builtins[0] );
  95. vertexShaders.SetNum( numBuiltins );
  96. fragmentShaders.SetNum( numBuiltins );
  97. glslPrograms.SetNum( numBuiltins );
  98. for ( int i = 0; i < numBuiltins; i++ ) {
  99. vertexShaders[i].name = builtins[i].name;
  100. fragmentShaders[i].name = builtins[i].name;
  101. builtinShaders[builtins[i].index] = i;
  102. LoadVertexShader( i );
  103. LoadFragmentShader( i );
  104. LoadGLSLProgram( i, i, i );
  105. }
  106. // Special case handling for fastZ shaders
  107. builtinShaders[BUILTIN_SHADOW] = FindVertexShader( "shadow.vp" );
  108. builtinShaders[BUILTIN_SHADOW_SKINNED] = FindVertexShader( "shadow_skinned.vp" );
  109. FindGLSLProgram( "shadow.vp", builtinShaders[BUILTIN_SHADOW], -1 );
  110. FindGLSLProgram( "shadow_skinned.vp", builtinShaders[BUILTIN_SHADOW_SKINNED], -1 );
  111. glslUniforms.SetNum( RENDERPARM_USER + MAX_GLSL_USER_PARMS, vec4_zero );
  112. vertexShaders[builtinShaders[BUILTIN_TEXTURE_VERTEXCOLOR_SKINNED]].usesJoints = true;
  113. vertexShaders[builtinShaders[BUILTIN_INTERACTION_SKINNED]].usesJoints = true;
  114. vertexShaders[builtinShaders[BUILTIN_INTERACTION_AMBIENT_SKINNED]].usesJoints = true;
  115. vertexShaders[builtinShaders[BUILTIN_ENVIRONMENT_SKINNED]].usesJoints = true;
  116. vertexShaders[builtinShaders[BUILTIN_BUMPY_ENVIRONMENT_SKINNED]].usesJoints = true;
  117. vertexShaders[builtinShaders[BUILTIN_DEPTH_SKINNED]].usesJoints = true;
  118. vertexShaders[builtinShaders[BUILTIN_SHADOW_SKINNED]].usesJoints = true;
  119. vertexShaders[builtinShaders[BUILTIN_SHADOW_DEBUG_SKINNED]].usesJoints = true;
  120. vertexShaders[builtinShaders[BUILTIN_FOG_SKINNED]].usesJoints = true;
  121. cmdSystem->AddCommand( "reloadShaders", R_ReloadShaders, CMD_FL_RENDERER, "reloads shaders" );
  122. }
  123. /*
  124. ================================================================================================
  125. idRenderProgManager::LoadAllShaders()
  126. ================================================================================================
  127. */
  128. void idRenderProgManager::LoadAllShaders() {
  129. for ( int i = 0; i < vertexShaders.Num(); i++ ) {
  130. LoadVertexShader( i );
  131. }
  132. for ( int i = 0; i < fragmentShaders.Num(); i++ ) {
  133. LoadFragmentShader( i );
  134. }
  135. for ( int i = 0; i < glslPrograms.Num(); ++i ) {
  136. LoadGLSLProgram( i, glslPrograms[i].vertexShaderIndex, glslPrograms[i].fragmentShaderIndex );
  137. }
  138. }
  139. /*
  140. ================================================================================================
  141. idRenderProgManager::KillAllShaders()
  142. ================================================================================================
  143. */
  144. void idRenderProgManager::KillAllShaders() {
  145. Unbind();
  146. for ( int i = 0; i < vertexShaders.Num(); i++ ) {
  147. if ( vertexShaders[i].progId != INVALID_PROGID ) {
  148. qglDeleteShader( vertexShaders[i].progId );
  149. vertexShaders[i].progId = INVALID_PROGID;
  150. }
  151. }
  152. for ( int i = 0; i < fragmentShaders.Num(); i++ ) {
  153. if ( fragmentShaders[i].progId != INVALID_PROGID ) {
  154. qglDeleteShader( fragmentShaders[i].progId );
  155. fragmentShaders[i].progId = INVALID_PROGID;
  156. }
  157. }
  158. for ( int i = 0; i < glslPrograms.Num(); ++i ) {
  159. if ( glslPrograms[i].progId != INVALID_PROGID ) {
  160. qglDeleteProgram( glslPrograms[i].progId );
  161. glslPrograms[i].progId = INVALID_PROGID;
  162. }
  163. }
  164. }
  165. /*
  166. ================================================================================================
  167. idRenderProgManager::Shutdown()
  168. ================================================================================================
  169. */
  170. void idRenderProgManager::Shutdown() {
  171. KillAllShaders();
  172. }
  173. /*
  174. ================================================================================================
  175. idRenderProgManager::FindVertexShader
  176. ================================================================================================
  177. */
  178. int idRenderProgManager::FindVertexShader( const char * name ) {
  179. for ( int i = 0; i < vertexShaders.Num(); i++ ) {
  180. if ( vertexShaders[i].name.Icmp( name ) == 0 ) {
  181. LoadVertexShader( i );
  182. return i;
  183. }
  184. }
  185. vertexShader_t shader;
  186. shader.name = name;
  187. int index = vertexShaders.Append( shader );
  188. LoadVertexShader( index );
  189. currentVertexShader = index;
  190. // FIXME: we should really scan the program source code for using rpEnableSkinning but at this
  191. // point we directly load a binary and the program source code is not available on the consoles
  192. if ( idStr::Icmp( name, "heatHaze.vfp" ) == 0 ||
  193. idStr::Icmp( name, "heatHazeWithMask.vfp" ) == 0 ||
  194. idStr::Icmp( name, "heatHazeWithMaskAndVertex.vfp" ) == 0 ) {
  195. vertexShaders[index].usesJoints = true;
  196. vertexShaders[index].optionalSkinning = true;
  197. }
  198. return index;
  199. }
  200. /*
  201. ================================================================================================
  202. idRenderProgManager::FindFragmentShader
  203. ================================================================================================
  204. */
  205. int idRenderProgManager::FindFragmentShader( const char * name ) {
  206. for ( int i = 0; i < fragmentShaders.Num(); i++ ) {
  207. if ( fragmentShaders[i].name.Icmp( name ) == 0 ) {
  208. LoadFragmentShader( i );
  209. return i;
  210. }
  211. }
  212. fragmentShader_t shader;
  213. shader.name = name;
  214. int index = fragmentShaders.Append( shader );
  215. LoadFragmentShader( index );
  216. currentFragmentShader = index;
  217. return index;
  218. }
  219. /*
  220. ================================================================================================
  221. idRenderProgManager::LoadVertexShader
  222. ================================================================================================
  223. */
  224. void idRenderProgManager::LoadVertexShader( int index ) {
  225. if ( vertexShaders[index].progId != INVALID_PROGID ) {
  226. return; // Already loaded
  227. }
  228. vertexShaders[index].progId = ( GLuint ) LoadGLSLShader( GL_VERTEX_SHADER, vertexShaders[index].name, vertexShaders[index].uniforms );
  229. }
  230. /*
  231. ================================================================================================
  232. idRenderProgManager::LoadFragmentShader
  233. ================================================================================================
  234. */
  235. void idRenderProgManager::LoadFragmentShader( int index ) {
  236. if ( fragmentShaders[index].progId != INVALID_PROGID ) {
  237. return; // Already loaded
  238. }
  239. fragmentShaders[index].progId = ( GLuint ) LoadGLSLShader( GL_FRAGMENT_SHADER, fragmentShaders[index].name, fragmentShaders[index].uniforms );
  240. }
  241. /*
  242. ================================================================================================
  243. idRenderProgManager::LoadShader
  244. ================================================================================================
  245. */
  246. GLuint idRenderProgManager::LoadShader( GLenum target, const char * name, const char * startToken ) {
  247. idStr fullPath = "renderprogs\\gl\\";
  248. fullPath += name;
  249. common->Printf( "%s", fullPath.c_str() );
  250. char * fileBuffer = NULL;
  251. fileSystem->ReadFile( fullPath.c_str(), (void **)&fileBuffer, NULL );
  252. if ( fileBuffer == NULL ) {
  253. common->Printf( ": File not found\n" );
  254. return INVALID_PROGID;
  255. }
  256. if ( !R_IsInitialized() ) {
  257. common->Printf( ": Renderer not initialized\n" );
  258. fileSystem->FreeFile( fileBuffer );
  259. return INVALID_PROGID;
  260. }
  261. // vertex and fragment shaders are both be present in a single file, so
  262. // scan for the proper header to be the start point, and stamp a 0 in after the end
  263. char * start = strstr( (char *)fileBuffer, startToken );
  264. if ( start == NULL ) {
  265. common->Printf( ": %s not found\n", startToken );
  266. fileSystem->FreeFile( fileBuffer );
  267. return INVALID_PROGID;
  268. }
  269. char * end = strstr( start, "END" );
  270. if ( end == NULL ) {
  271. common->Printf( ": END not found for %s\n", startToken );
  272. fileSystem->FreeFile( fileBuffer );
  273. return INVALID_PROGID;
  274. }
  275. end[3] = 0;
  276. idStr program = start;
  277. program.Replace( "vertex.normal", "vertex.attrib[11]" );
  278. program.Replace( "vertex.texcoord[0]", "vertex.attrib[8]" );
  279. program.Replace( "vertex.texcoord", "vertex.attrib[8]" );
  280. GLuint progId;
  281. qglGenProgramsARB( 1, &progId );
  282. qglBindProgramARB( target, progId );
  283. qglGetError();
  284. qglProgramStringARB( target, GL_PROGRAM_FORMAT_ASCII_ARB, program.Length(), program.c_str() );
  285. GLenum err = qglGetError();
  286. GLint ofs = -1;
  287. qglGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &ofs );
  288. if ( ( err == GL_INVALID_OPERATION ) || ( ofs != -1 ) ) {
  289. if ( err == GL_INVALID_OPERATION ) {
  290. const GLubyte * str = qglGetString( GL_PROGRAM_ERROR_STRING_ARB );
  291. common->Printf( "\nGL_PROGRAM_ERROR_STRING_ARB: %s\n", str );
  292. } else {
  293. common->Printf( "\nUNKNOWN ERROR\n" );
  294. }
  295. if ( ofs < 0 ) {
  296. common->Printf( "GL_PROGRAM_ERROR_POSITION_ARB < 0\n" );
  297. } else if ( ofs >= program.Length() ) {
  298. common->Printf( "error at end of shader\n" );
  299. } else {
  300. common->Printf( "error at %i:\n%s", ofs, program.c_str() + ofs );
  301. }
  302. qglDeleteProgramsARB( 1, &progId );
  303. fileSystem->FreeFile( fileBuffer );
  304. return INVALID_PROGID;
  305. }
  306. common->Printf( "\n" );
  307. fileSystem->FreeFile( fileBuffer );
  308. return progId;
  309. }
  310. /*
  311. ================================================================================================
  312. idRenderProgManager::BindShader
  313. ================================================================================================
  314. */
  315. void idRenderProgManager::BindShader( int vIndex, int fIndex ) {
  316. if ( currentVertexShader == vIndex && currentFragmentShader == fIndex ) {
  317. return;
  318. }
  319. currentVertexShader = vIndex;
  320. currentFragmentShader = fIndex;
  321. // vIndex denotes the GLSL program
  322. if ( vIndex >= 0 && vIndex < glslPrograms.Num() ) {
  323. currentRenderProgram = vIndex;
  324. RENDERLOG_PRINTF( "Binding GLSL Program %s\n", glslPrograms[vIndex].name.c_str() );
  325. qglUseProgram( glslPrograms[vIndex].progId );
  326. }
  327. }
  328. /*
  329. ================================================================================================
  330. idRenderProgManager::Unbind
  331. ================================================================================================
  332. */
  333. void idRenderProgManager::Unbind() {
  334. currentVertexShader = -1;
  335. currentFragmentShader = -1;
  336. qglUseProgram( 0 );
  337. }
  338. /*
  339. ================================================================================================
  340. idRenderProgManager::SetRenderParms
  341. ================================================================================================
  342. */
  343. void idRenderProgManager::SetRenderParms( renderParm_t rp, const float * value, int num ) {
  344. for ( int i = 0; i < num; i++ ) {
  345. SetRenderParm( (renderParm_t)(rp + i), value + ( i * 4 ) );
  346. }
  347. }
  348. /*
  349. ================================================================================================
  350. idRenderProgManager::SetRenderParm
  351. ================================================================================================
  352. */
  353. void idRenderProgManager::SetRenderParm( renderParm_t rp, const float * value ) {
  354. SetUniformValue( rp, value );
  355. }