draw_arb2.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 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 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 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 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 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. #include "../idlib/precompiled.h"
  21. #pragma hdrstop
  22. #include "tr_local.h"
  23. #include "cg_explicit.h"
  24. CGcontext cg_context;
  25. static void cg_error_callback( void ) {
  26. CGerror i = cgGetError();
  27. common->Printf( "Cg error (%d): %s\n", i, cgGetErrorString(i) );
  28. }
  29. /*
  30. =========================================================================================
  31. GENERAL INTERACTION RENDERING
  32. =========================================================================================
  33. */
  34. /*
  35. ====================
  36. GL_SelectTextureNoClient
  37. ====================
  38. */
  39. static void GL_SelectTextureNoClient( int unit ) {
  40. backEnd.glState.currenttmu = unit;
  41. qglActiveTextureARB( GL_TEXTURE0_ARB + unit );
  42. RB_LogComment( "glActiveTextureARB( %i )\n", unit );
  43. }
  44. /*
  45. ==================
  46. RB_ARB2_DrawInteraction
  47. ==================
  48. */
  49. void RB_ARB2_DrawInteraction( const drawInteraction_t *din ) {
  50. // load all the vertex program parameters
  51. qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_LIGHT_ORIGIN, din->localLightOrigin.ToFloatPtr() );
  52. qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_VIEW_ORIGIN, din->localViewOrigin.ToFloatPtr() );
  53. qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_LIGHT_PROJECT_S, din->lightProjection[0].ToFloatPtr() );
  54. qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_LIGHT_PROJECT_T, din->lightProjection[1].ToFloatPtr() );
  55. qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_LIGHT_PROJECT_Q, din->lightProjection[2].ToFloatPtr() );
  56. qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_LIGHT_FALLOFF_S, din->lightProjection[3].ToFloatPtr() );
  57. qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_BUMP_MATRIX_S, din->bumpMatrix[0].ToFloatPtr() );
  58. qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_BUMP_MATRIX_T, din->bumpMatrix[1].ToFloatPtr() );
  59. qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_DIFFUSE_MATRIX_S, din->diffuseMatrix[0].ToFloatPtr() );
  60. qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_DIFFUSE_MATRIX_T, din->diffuseMatrix[1].ToFloatPtr() );
  61. qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_SPECULAR_MATRIX_S, din->specularMatrix[0].ToFloatPtr() );
  62. qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_SPECULAR_MATRIX_T, din->specularMatrix[1].ToFloatPtr() );
  63. // testing fragment based normal mapping
  64. if ( r_testARBProgram.GetBool() ) {
  65. qglProgramEnvParameter4fvARB( GL_FRAGMENT_PROGRAM_ARB, 2, din->localLightOrigin.ToFloatPtr() );
  66. qglProgramEnvParameter4fvARB( GL_FRAGMENT_PROGRAM_ARB, 3, din->localViewOrigin.ToFloatPtr() );
  67. }
  68. static const float zero[4] = { 0, 0, 0, 0 };
  69. static const float one[4] = { 1, 1, 1, 1 };
  70. static const float negOne[4] = { -1, -1, -1, -1 };
  71. switch ( din->vertexColor ) {
  72. case SVC_IGNORE:
  73. qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_COLOR_MODULATE, zero );
  74. qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_COLOR_ADD, one );
  75. break;
  76. case SVC_MODULATE:
  77. qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_COLOR_MODULATE, one );
  78. qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_COLOR_ADD, zero );
  79. break;
  80. case SVC_INVERSE_MODULATE:
  81. qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_COLOR_MODULATE, negOne );
  82. qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_COLOR_ADD, one );
  83. break;
  84. }
  85. // set the constant colors
  86. qglProgramEnvParameter4fvARB( GL_FRAGMENT_PROGRAM_ARB, 0, din->diffuseColor.ToFloatPtr() );
  87. qglProgramEnvParameter4fvARB( GL_FRAGMENT_PROGRAM_ARB, 1, din->specularColor.ToFloatPtr() );
  88. // set the textures
  89. // texture 1 will be the per-surface bump map
  90. GL_SelectTextureNoClient( 1 );
  91. din->bumpImage->Bind();
  92. // texture 2 will be the light falloff texture
  93. GL_SelectTextureNoClient( 2 );
  94. din->lightFalloffImage->Bind();
  95. // texture 3 will be the light projection texture
  96. GL_SelectTextureNoClient( 3 );
  97. din->lightImage->Bind();
  98. // texture 4 is the per-surface diffuse map
  99. GL_SelectTextureNoClient( 4 );
  100. din->diffuseImage->Bind();
  101. // texture 5 is the per-surface specular map
  102. GL_SelectTextureNoClient( 5 );
  103. din->specularImage->Bind();
  104. // draw it
  105. RB_DrawElementsWithCounters( din->surf->geo );
  106. }
  107. /*
  108. =============
  109. RB_ARB2_CreateDrawInteractions
  110. =============
  111. */
  112. void RB_ARB2_CreateDrawInteractions( const drawSurf_t *surf ) {
  113. if ( !surf ) {
  114. return;
  115. }
  116. // perform setup here that will be constant for all interactions
  117. GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | backEnd.depthFunc );
  118. // bind the vertex program
  119. if ( r_testARBProgram.GetBool() ) {
  120. qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, VPROG_TEST );
  121. qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, FPROG_TEST );
  122. } else {
  123. qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, VPROG_INTERACTION );
  124. qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, FPROG_INTERACTION );
  125. }
  126. qglEnable(GL_VERTEX_PROGRAM_ARB);
  127. qglEnable(GL_FRAGMENT_PROGRAM_ARB);
  128. // enable the vertex arrays
  129. qglEnableVertexAttribArrayARB( 8 );
  130. qglEnableVertexAttribArrayARB( 9 );
  131. qglEnableVertexAttribArrayARB( 10 );
  132. qglEnableVertexAttribArrayARB( 11 );
  133. qglEnableClientState( GL_COLOR_ARRAY );
  134. // texture 0 is the normalization cube map for the vector towards the light
  135. GL_SelectTextureNoClient( 0 );
  136. if ( backEnd.vLight->lightShader->IsAmbientLight() ) {
  137. globalImages->ambientNormalMap->Bind();
  138. } else {
  139. globalImages->normalCubeMapImage->Bind();
  140. }
  141. // texture 6 is the specular lookup table
  142. GL_SelectTextureNoClient( 6 );
  143. if ( r_testARBProgram.GetBool() ) {
  144. globalImages->specular2DTableImage->Bind(); // variable specularity in alpha channel
  145. } else {
  146. globalImages->specularTableImage->Bind();
  147. }
  148. for ( ; surf ; surf=surf->nextOnLight ) {
  149. // perform setup here that will not change over multiple interaction passes
  150. // set the vertex pointers
  151. idDrawVert *ac = (idDrawVert *)vertexCache.Position( surf->geo->ambientCache );
  152. qglColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( idDrawVert ), ac->color );
  153. qglVertexAttribPointerARB( 11, 3, GL_FLOAT, false, sizeof( idDrawVert ), ac->normal.ToFloatPtr() );
  154. qglVertexAttribPointerARB( 10, 3, GL_FLOAT, false, sizeof( idDrawVert ), ac->tangents[1].ToFloatPtr() );
  155. qglVertexAttribPointerARB( 9, 3, GL_FLOAT, false, sizeof( idDrawVert ), ac->tangents[0].ToFloatPtr() );
  156. qglVertexAttribPointerARB( 8, 2, GL_FLOAT, false, sizeof( idDrawVert ), ac->st.ToFloatPtr() );
  157. qglVertexPointer( 3, GL_FLOAT, sizeof( idDrawVert ), ac->xyz.ToFloatPtr() );
  158. // this may cause RB_ARB2_DrawInteraction to be exacuted multiple
  159. // times with different colors and images if the surface or light have multiple layers
  160. RB_CreateSingleDrawInteractions( surf, RB_ARB2_DrawInteraction );
  161. }
  162. qglDisableVertexAttribArrayARB( 8 );
  163. qglDisableVertexAttribArrayARB( 9 );
  164. qglDisableVertexAttribArrayARB( 10 );
  165. qglDisableVertexAttribArrayARB( 11 );
  166. qglDisableClientState( GL_COLOR_ARRAY );
  167. // disable features
  168. GL_SelectTextureNoClient( 6 );
  169. globalImages->BindNull();
  170. GL_SelectTextureNoClient( 5 );
  171. globalImages->BindNull();
  172. GL_SelectTextureNoClient( 4 );
  173. globalImages->BindNull();
  174. GL_SelectTextureNoClient( 3 );
  175. globalImages->BindNull();
  176. GL_SelectTextureNoClient( 2 );
  177. globalImages->BindNull();
  178. GL_SelectTextureNoClient( 1 );
  179. globalImages->BindNull();
  180. backEnd.glState.currenttmu = -1;
  181. GL_SelectTexture( 0 );
  182. qglDisable(GL_VERTEX_PROGRAM_ARB);
  183. qglDisable(GL_FRAGMENT_PROGRAM_ARB);
  184. }
  185. /*
  186. ==================
  187. RB_ARB2_DrawInteractions
  188. ==================
  189. */
  190. void RB_ARB2_DrawInteractions( void ) {
  191. viewLight_t *vLight;
  192. const idMaterial *lightShader;
  193. GL_SelectTexture( 0 );
  194. qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
  195. //
  196. // for each light, perform adding and shadowing
  197. //
  198. for ( vLight = backEnd.viewDef->viewLights ; vLight ; vLight = vLight->next ) {
  199. backEnd.vLight = vLight;
  200. // do fogging later
  201. if ( vLight->lightShader->IsFogLight() ) {
  202. continue;
  203. }
  204. if ( vLight->lightShader->IsBlendLight() ) {
  205. continue;
  206. }
  207. if ( !vLight->localInteractions && !vLight->globalInteractions
  208. && !vLight->translucentInteractions ) {
  209. continue;
  210. }
  211. lightShader = vLight->lightShader;
  212. // clear the stencil buffer if needed
  213. if ( vLight->globalShadows || vLight->localShadows ) {
  214. backEnd.currentScissor = vLight->scissorRect;
  215. if ( r_useScissor.GetBool() ) {
  216. qglScissor( backEnd.viewDef->viewport.x1 + backEnd.currentScissor.x1,
  217. backEnd.viewDef->viewport.y1 + backEnd.currentScissor.y1,
  218. backEnd.currentScissor.x2 + 1 - backEnd.currentScissor.x1,
  219. backEnd.currentScissor.y2 + 1 - backEnd.currentScissor.y1 );
  220. }
  221. qglClear( GL_STENCIL_BUFFER_BIT );
  222. } else {
  223. // no shadows, so no need to read or write the stencil buffer
  224. // we might in theory want to use GL_ALWAYS instead of disabling
  225. // completely, to satisfy the invarience rules
  226. qglStencilFunc( GL_ALWAYS, 128, 255 );
  227. }
  228. if ( r_useShadowVertexProgram.GetBool() ) {
  229. qglEnable( GL_VERTEX_PROGRAM_ARB );
  230. qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, VPROG_STENCIL_SHADOW );
  231. RB_StencilShadowPass( vLight->globalShadows );
  232. RB_ARB2_CreateDrawInteractions( vLight->localInteractions );
  233. qglEnable( GL_VERTEX_PROGRAM_ARB );
  234. qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, VPROG_STENCIL_SHADOW );
  235. RB_StencilShadowPass( vLight->localShadows );
  236. RB_ARB2_CreateDrawInteractions( vLight->globalInteractions );
  237. qglDisable( GL_VERTEX_PROGRAM_ARB ); // if there weren't any globalInteractions, it would have stayed on
  238. } else {
  239. RB_StencilShadowPass( vLight->globalShadows );
  240. RB_ARB2_CreateDrawInteractions( vLight->localInteractions );
  241. RB_StencilShadowPass( vLight->localShadows );
  242. RB_ARB2_CreateDrawInteractions( vLight->globalInteractions );
  243. }
  244. // translucent surfaces never get stencil shadowed
  245. if ( r_skipTranslucent.GetBool() ) {
  246. continue;
  247. }
  248. qglStencilFunc( GL_ALWAYS, 128, 255 );
  249. backEnd.depthFunc = GLS_DEPTHFUNC_LESS;
  250. RB_ARB2_CreateDrawInteractions( vLight->translucentInteractions );
  251. backEnd.depthFunc = GLS_DEPTHFUNC_EQUAL;
  252. }
  253. // disable stencil shadow test
  254. qglStencilFunc( GL_ALWAYS, 128, 255 );
  255. GL_SelectTexture( 0 );
  256. qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
  257. }
  258. //===================================================================================
  259. typedef struct {
  260. GLenum target;
  261. GLuint ident;
  262. char name[64];
  263. } progDef_t;
  264. static const int MAX_GLPROGS = 200;
  265. // a single file can have both a vertex program and a fragment program
  266. static progDef_t progs[MAX_GLPROGS] = {
  267. { GL_VERTEX_PROGRAM_ARB, VPROG_TEST, "test.vfp" },
  268. { GL_FRAGMENT_PROGRAM_ARB, FPROG_TEST, "test.vfp" },
  269. { GL_VERTEX_PROGRAM_ARB, VPROG_INTERACTION, "interaction.vfp" },
  270. { GL_FRAGMENT_PROGRAM_ARB, FPROG_INTERACTION, "interaction.vfp" },
  271. { GL_VERTEX_PROGRAM_ARB, VPROG_BUMPY_ENVIRONMENT, "bumpyEnvironment.vfp" },
  272. { GL_FRAGMENT_PROGRAM_ARB, FPROG_BUMPY_ENVIRONMENT, "bumpyEnvironment.vfp" },
  273. { GL_VERTEX_PROGRAM_ARB, VPROG_AMBIENT, "ambientLight.vfp" },
  274. { GL_FRAGMENT_PROGRAM_ARB, FPROG_AMBIENT, "ambientLight.vfp" },
  275. { GL_VERTEX_PROGRAM_ARB, VPROG_STENCIL_SHADOW, "shadow.vp" },
  276. { GL_VERTEX_PROGRAM_ARB, VPROG_R200_INTERACTION, "R200_interaction.vp" },
  277. { GL_VERTEX_PROGRAM_ARB, VPROG_NV20_BUMP_AND_LIGHT, "nv20_bumpAndLight.vp" },
  278. { GL_VERTEX_PROGRAM_ARB, VPROG_NV20_DIFFUSE_COLOR, "nv20_diffuseColor.vp" },
  279. { GL_VERTEX_PROGRAM_ARB, VPROG_NV20_SPECULAR_COLOR, "nv20_specularColor.vp" },
  280. { GL_VERTEX_PROGRAM_ARB, VPROG_NV20_DIFFUSE_AND_SPECULAR_COLOR, "nv20_diffuseAndSpecularColor.vp" },
  281. { GL_VERTEX_PROGRAM_ARB, VPROG_ENVIRONMENT, "environment.vfp" },
  282. { GL_FRAGMENT_PROGRAM_ARB, FPROG_ENVIRONMENT, "environment.vfp" },
  283. { GL_VERTEX_PROGRAM_ARB, VPROG_GLASSWARP, "arbVP_glasswarp.txt" },
  284. { GL_FRAGMENT_PROGRAM_ARB, FPROG_GLASSWARP, "arbFP_glasswarp.txt" },
  285. // additional programs can be dynamically specified in materials
  286. };
  287. /*
  288. =================
  289. R_LoadARBProgram
  290. =================
  291. */
  292. void R_LoadARBProgram( int progIndex ) {
  293. int ofs;
  294. int err;
  295. idStr fullPath = "glprogs/";
  296. fullPath += progs[progIndex].name;
  297. char *fileBuffer;
  298. char *buffer;
  299. char *start, *end;
  300. common->Printf( "%s", fullPath.c_str() );
  301. // load the program even if we don't support it, so
  302. // fs_copyfiles can generate cross-platform data dumps
  303. fileSystem->ReadFile( fullPath.c_str(), (void **)&fileBuffer, NULL );
  304. if ( !fileBuffer ) {
  305. common->Printf( ": File not found\n" );
  306. return;
  307. }
  308. // copy to stack memory and free
  309. buffer = (char *)_alloca( strlen( fileBuffer ) + 1 );
  310. strcpy( buffer, fileBuffer );
  311. fileSystem->FreeFile( fileBuffer );
  312. if ( !glConfig.isInitialized ) {
  313. return;
  314. }
  315. //
  316. // submit the program string at start to GL
  317. //
  318. if ( progs[progIndex].ident == 0 ) {
  319. // allocate a new identifier for this program
  320. progs[progIndex].ident = PROG_USER + progIndex;
  321. }
  322. // vertex and fragment programs can both be present in a single file, so
  323. // scan for the proper header to be the start point, and stamp a 0 in after the end
  324. if ( progs[progIndex].target == GL_VERTEX_PROGRAM_ARB ) {
  325. if ( !glConfig.ARBVertexProgramAvailable ) {
  326. common->Printf( ": GL_VERTEX_PROGRAM_ARB not available\n" );
  327. return;
  328. }
  329. start = strstr( (char *)buffer, "!!ARBvp" );
  330. }
  331. if ( progs[progIndex].target == GL_FRAGMENT_PROGRAM_ARB ) {
  332. if ( !glConfig.ARBFragmentProgramAvailable ) {
  333. common->Printf( ": GL_FRAGMENT_PROGRAM_ARB not available\n" );
  334. return;
  335. }
  336. start = strstr( (char *)buffer, "!!ARBfp" );
  337. }
  338. if ( !start ) {
  339. common->Printf( ": !!ARB not found\n" );
  340. return;
  341. }
  342. end = strstr( start, "END" );
  343. if ( !end ) {
  344. common->Printf( ": END not found\n" );
  345. return;
  346. }
  347. end[3] = 0;
  348. qglBindProgramARB( progs[progIndex].target, progs[progIndex].ident );
  349. qglGetError();
  350. qglProgramStringARB( progs[progIndex].target, GL_PROGRAM_FORMAT_ASCII_ARB,
  351. strlen( start ), (unsigned char *)start );
  352. err = qglGetError();
  353. qglGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, (GLint *)&ofs );
  354. if ( err == GL_INVALID_OPERATION ) {
  355. const GLubyte *str = qglGetString( GL_PROGRAM_ERROR_STRING_ARB );
  356. common->Printf( "\nGL_PROGRAM_ERROR_STRING_ARB: %s\n", str );
  357. if ( ofs < 0 ) {
  358. common->Printf( "GL_PROGRAM_ERROR_POSITION_ARB < 0 with error\n" );
  359. } else if ( ofs >= (int)strlen( (char *)start ) ) {
  360. common->Printf( "error at end of program\n" );
  361. } else {
  362. common->Printf( "error at %i:\n%s", ofs, start + ofs );
  363. }
  364. return;
  365. }
  366. if ( ofs != -1 ) {
  367. common->Printf( "\nGL_PROGRAM_ERROR_POSITION_ARB != -1 without error\n" );
  368. return;
  369. }
  370. common->Printf( "\n" );
  371. }
  372. /*
  373. ==================
  374. R_FindARBProgram
  375. Returns a GL identifier that can be bound to the given target, parsing
  376. a text file if it hasn't already been loaded.
  377. ==================
  378. */
  379. int R_FindARBProgram( GLenum target, const char *program ) {
  380. int i;
  381. idStr stripped = program;
  382. stripped.StripFileExtension();
  383. // see if it is already loaded
  384. for ( i = 0 ; progs[i].name[0] ; i++ ) {
  385. if ( progs[i].target != target ) {
  386. continue;
  387. }
  388. idStr compare = progs[i].name;
  389. compare.StripFileExtension();
  390. if ( !idStr::Icmp( stripped.c_str(), compare.c_str() ) ) {
  391. return progs[i].ident;
  392. }
  393. }
  394. if ( i == MAX_GLPROGS ) {
  395. common->Error( "R_FindARBProgram: MAX_GLPROGS" );
  396. }
  397. // add it to the list and load it
  398. progs[i].ident = (program_t)0; // will be gen'd by R_LoadARBProgram
  399. progs[i].target = target;
  400. strncpy( progs[i].name, program, sizeof( progs[i].name ) - 1 );
  401. R_LoadARBProgram( i );
  402. return progs[i].ident;
  403. }
  404. /*
  405. ==================
  406. R_ReloadARBPrograms_f
  407. ==================
  408. */
  409. void R_ReloadARBPrograms_f( const idCmdArgs &args ) {
  410. int i;
  411. common->Printf( "----- R_ReloadARBPrograms -----\n" );
  412. for ( i = 0 ; progs[i].name[0] ; i++ ) {
  413. R_LoadARBProgram( i );
  414. }
  415. common->Printf( "-------------------------------\n" );
  416. }
  417. /*
  418. ==================
  419. R_ARB2_Init
  420. ==================
  421. */
  422. void R_ARB2_Init( void ) {
  423. glConfig.allowARB2Path = false;
  424. common->Printf( "---------- R_ARB2_Init ----------\n" );
  425. if ( !glConfig.ARBVertexProgramAvailable || !glConfig.ARBFragmentProgramAvailable ) {
  426. common->Printf( "Not available.\n" );
  427. return;
  428. }
  429. common->Printf( "Available.\n" );
  430. common->Printf( "---------------------------------\n" );
  431. glConfig.allowARB2Path = true;
  432. }