tr_shade.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1999-2005 Id Software, Inc.
  4. This file is part of Quake III Arena source code.
  5. Quake III Arena source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake III Arena source code is distributed in the hope that it will be
  10. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Foobar; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. // tr_shade.c
  19. #include "tr_local.h"
  20. /*
  21. THIS ENTIRE FILE IS BACK END
  22. This file deals with applying shaders to surface data in the tess struct.
  23. */
  24. /*
  25. ================
  26. R_ArrayElementDiscrete
  27. This is just for OpenGL conformance testing, it should never be the fastest
  28. ================
  29. */
  30. static void APIENTRY R_ArrayElementDiscrete( GLint index ) {
  31. qglColor4ubv( tess.svars.colors[ index ] );
  32. if ( glState.currenttmu ) {
  33. qglMultiTexCoord2fARB( 0, tess.svars.texcoords[ 0 ][ index ][0], tess.svars.texcoords[ 0 ][ index ][1] );
  34. qglMultiTexCoord2fARB( 1, tess.svars.texcoords[ 1 ][ index ][0], tess.svars.texcoords[ 1 ][ index ][1] );
  35. } else {
  36. qglTexCoord2fv( tess.svars.texcoords[ 0 ][ index ] );
  37. }
  38. qglVertex3fv( tess.xyz[ index ] );
  39. }
  40. /*
  41. ===================
  42. R_DrawStripElements
  43. ===================
  44. */
  45. static int c_vertexes; // for seeing how long our average strips are
  46. static int c_begins;
  47. static void R_DrawStripElements( int numIndexes, const glIndex_t *indexes, void ( APIENTRY *element )(GLint) ) {
  48. int i;
  49. int last[3] = { -1, -1, -1 };
  50. qboolean even;
  51. c_begins++;
  52. if ( numIndexes <= 0 ) {
  53. return;
  54. }
  55. qglBegin( GL_TRIANGLE_STRIP );
  56. // prime the strip
  57. element( indexes[0] );
  58. element( indexes[1] );
  59. element( indexes[2] );
  60. c_vertexes += 3;
  61. last[0] = indexes[0];
  62. last[1] = indexes[1];
  63. last[2] = indexes[2];
  64. even = qfalse;
  65. for ( i = 3; i < numIndexes; i += 3 )
  66. {
  67. // odd numbered triangle in potential strip
  68. if ( !even )
  69. {
  70. // check previous triangle to see if we're continuing a strip
  71. if ( ( indexes[i+0] == last[2] ) && ( indexes[i+1] == last[1] ) )
  72. {
  73. element( indexes[i+2] );
  74. c_vertexes++;
  75. assert( indexes[i+2] < tess.numVertexes );
  76. even = qtrue;
  77. }
  78. // otherwise we're done with this strip so finish it and start
  79. // a new one
  80. else
  81. {
  82. qglEnd();
  83. qglBegin( GL_TRIANGLE_STRIP );
  84. c_begins++;
  85. element( indexes[i+0] );
  86. element( indexes[i+1] );
  87. element( indexes[i+2] );
  88. c_vertexes += 3;
  89. even = qfalse;
  90. }
  91. }
  92. else
  93. {
  94. // check previous triangle to see if we're continuing a strip
  95. if ( ( last[2] == indexes[i+1] ) && ( last[0] == indexes[i+0] ) )
  96. {
  97. element( indexes[i+2] );
  98. c_vertexes++;
  99. even = qfalse;
  100. }
  101. // otherwise we're done with this strip so finish it and start
  102. // a new one
  103. else
  104. {
  105. qglEnd();
  106. qglBegin( GL_TRIANGLE_STRIP );
  107. c_begins++;
  108. element( indexes[i+0] );
  109. element( indexes[i+1] );
  110. element( indexes[i+2] );
  111. c_vertexes += 3;
  112. even = qfalse;
  113. }
  114. }
  115. // cache the last three vertices
  116. last[0] = indexes[i+0];
  117. last[1] = indexes[i+1];
  118. last[2] = indexes[i+2];
  119. }
  120. qglEnd();
  121. }
  122. /*
  123. ==================
  124. R_DrawElements
  125. Optionally performs our own glDrawElements that looks for strip conditions
  126. instead of using the single glDrawElements call that may be inefficient
  127. without compiled vertex arrays.
  128. ==================
  129. */
  130. static void R_DrawElements( int numIndexes, const glIndex_t *indexes ) {
  131. int primitives;
  132. primitives = r_primitives->integer;
  133. // default is to use triangles if compiled vertex arrays are present
  134. if ( primitives == 0 ) {
  135. if ( qglLockArraysEXT ) {
  136. primitives = 2;
  137. } else {
  138. primitives = 1;
  139. }
  140. }
  141. if ( primitives == 2 ) {
  142. qglDrawElements( GL_TRIANGLES,
  143. numIndexes,
  144. GL_INDEX_TYPE,
  145. indexes );
  146. return;
  147. }
  148. if ( primitives == 1 ) {
  149. R_DrawStripElements( numIndexes, indexes, qglArrayElement );
  150. return;
  151. }
  152. if ( primitives == 3 ) {
  153. R_DrawStripElements( numIndexes, indexes, R_ArrayElementDiscrete );
  154. return;
  155. }
  156. // anything else will cause no drawing
  157. }
  158. /*
  159. =============================================================
  160. SURFACE SHADERS
  161. =============================================================
  162. */
  163. shaderCommands_t tess;
  164. static qboolean setArraysOnce;
  165. /*
  166. =================
  167. R_BindAnimatedImage
  168. =================
  169. */
  170. static void R_BindAnimatedImage( textureBundle_t *bundle ) {
  171. int index;
  172. if ( bundle->isVideoMap ) {
  173. ri.CIN_RunCinematic(bundle->videoMapHandle);
  174. ri.CIN_UploadCinematic(bundle->videoMapHandle);
  175. return;
  176. }
  177. if ( bundle->numImageAnimations <= 1 ) {
  178. GL_Bind( bundle->image[0] );
  179. return;
  180. }
  181. // it is necessary to do this messy calc to make sure animations line up
  182. // exactly with waveforms of the same frequency
  183. index = myftol( tess.shaderTime * bundle->imageAnimationSpeed * FUNCTABLE_SIZE );
  184. index >>= FUNCTABLE_SIZE2;
  185. if ( index < 0 ) {
  186. index = 0; // may happen with shader time offsets
  187. }
  188. index %= bundle->numImageAnimations;
  189. GL_Bind( bundle->image[ index ] );
  190. }
  191. /*
  192. ================
  193. DrawTris
  194. Draws triangle outlines for debugging
  195. ================
  196. */
  197. static void DrawTris (shaderCommands_t *input) {
  198. GL_Bind( tr.whiteImage );
  199. qglColor3f (1,1,1);
  200. GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE );
  201. qglDepthRange( 0, 0 );
  202. qglDisableClientState (GL_COLOR_ARRAY);
  203. qglDisableClientState (GL_TEXTURE_COORD_ARRAY);
  204. qglVertexPointer (3, GL_FLOAT, 16, input->xyz); // padded for SIMD
  205. if (qglLockArraysEXT) {
  206. qglLockArraysEXT(0, input->numVertexes);
  207. GLimp_LogComment( "glLockArraysEXT\n" );
  208. }
  209. R_DrawElements( input->numIndexes, input->indexes );
  210. if (qglUnlockArraysEXT) {
  211. qglUnlockArraysEXT();
  212. GLimp_LogComment( "glUnlockArraysEXT\n" );
  213. }
  214. qglDepthRange( 0, 1 );
  215. }
  216. /*
  217. ================
  218. DrawNormals
  219. Draws vertex normals for debugging
  220. ================
  221. */
  222. static void DrawNormals (shaderCommands_t *input) {
  223. int i;
  224. vec3_t temp;
  225. GL_Bind( tr.whiteImage );
  226. qglColor3f (1,1,1);
  227. qglDepthRange( 0, 0 ); // never occluded
  228. GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE );
  229. qglBegin (GL_LINES);
  230. for (i = 0 ; i < input->numVertexes ; i++) {
  231. qglVertex3fv (input->xyz[i]);
  232. VectorMA (input->xyz[i], 2, input->normal[i], temp);
  233. qglVertex3fv (temp);
  234. }
  235. qglEnd ();
  236. qglDepthRange( 0, 1 );
  237. }
  238. /*
  239. ==============
  240. RB_BeginSurface
  241. We must set some things up before beginning any tesselation,
  242. because a surface may be forced to perform a RB_End due
  243. to overflow.
  244. ==============
  245. */
  246. void RB_BeginSurface( shader_t *shader, int fogNum ) {
  247. shader_t *state = (shader->remappedShader) ? shader->remappedShader : shader;
  248. tess.numIndexes = 0;
  249. tess.numVertexes = 0;
  250. tess.shader = state;
  251. tess.fogNum = fogNum;
  252. tess.dlightBits = 0; // will be OR'd in by surface functions
  253. tess.xstages = state->stages;
  254. tess.numPasses = state->numUnfoggedPasses;
  255. tess.currentStageIteratorFunc = state->optimalStageIteratorFunc;
  256. tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;
  257. if (tess.shader->clampTime && tess.shaderTime >= tess.shader->clampTime) {
  258. tess.shaderTime = tess.shader->clampTime;
  259. }
  260. }
  261. /*
  262. ===================
  263. DrawMultitextured
  264. output = t0 * t1 or t0 + t1
  265. t0 = most upstream according to spec
  266. t1 = most downstream according to spec
  267. ===================
  268. */
  269. static void DrawMultitextured( shaderCommands_t *input, int stage ) {
  270. shaderStage_t *pStage;
  271. pStage = tess.xstages[stage];
  272. GL_State( pStage->stateBits );
  273. // this is an ugly hack to work around a GeForce driver
  274. // bug with multitexture and clip planes
  275. if ( backEnd.viewParms.isPortal ) {
  276. qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
  277. }
  278. //
  279. // base
  280. //
  281. GL_SelectTexture( 0 );
  282. qglTexCoordPointer( 2, GL_FLOAT, 0, input->svars.texcoords[0] );
  283. R_BindAnimatedImage( &pStage->bundle[0] );
  284. //
  285. // lightmap/secondary pass
  286. //
  287. GL_SelectTexture( 1 );
  288. qglEnable( GL_TEXTURE_2D );
  289. qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
  290. if ( r_lightmap->integer ) {
  291. GL_TexEnv( GL_REPLACE );
  292. } else {
  293. GL_TexEnv( tess.shader->multitextureEnv );
  294. }
  295. qglTexCoordPointer( 2, GL_FLOAT, 0, input->svars.texcoords[1] );
  296. R_BindAnimatedImage( &pStage->bundle[1] );
  297. R_DrawElements( input->numIndexes, input->indexes );
  298. //
  299. // disable texturing on TEXTURE1, then select TEXTURE0
  300. //
  301. //qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
  302. qglDisable( GL_TEXTURE_2D );
  303. GL_SelectTexture( 0 );
  304. }
  305. /*
  306. ===================
  307. ProjectDlightTexture
  308. Perform dynamic lighting with another rendering pass
  309. ===================
  310. */
  311. static void ProjectDlightTexture( void ) {
  312. int i, l;
  313. #if idppc_altivec
  314. vec_t origin0, origin1, origin2;
  315. float texCoords0, texCoords1;
  316. vector float floatColorVec0, floatColorVec1;
  317. vector float modulateVec, colorVec, zero;
  318. vector short colorShort;
  319. vector signed int colorInt;
  320. vector unsigned char floatColorVecPerm, modulatePerm, colorChar;
  321. vector unsigned char vSel = (vector unsigned char)(0x00, 0x00, 0x00, 0xff,
  322. 0x00, 0x00, 0x00, 0xff,
  323. 0x00, 0x00, 0x00, 0xff,
  324. 0x00, 0x00, 0x00, 0xff);
  325. #else
  326. vec3_t origin;
  327. #endif
  328. float *texCoords;
  329. byte *colors;
  330. byte clipBits[SHADER_MAX_VERTEXES];
  331. MAC_STATIC float texCoordsArray[SHADER_MAX_VERTEXES][2];
  332. byte colorArray[SHADER_MAX_VERTEXES][4];
  333. unsigned hitIndexes[SHADER_MAX_INDEXES];
  334. int numIndexes;
  335. float scale;
  336. float radius;
  337. vec3_t floatColor;
  338. float modulate;
  339. if ( !backEnd.refdef.num_dlights ) {
  340. return;
  341. }
  342. #if idppc_altivec
  343. // There has to be a better way to do this so that floatColor
  344. // and/or modulate are already 16-byte aligned.
  345. floatColorVecPerm = vec_lvsl(0,(float *)floatColor);
  346. modulatePerm = vec_lvsl(0,(float *)&modulate);
  347. modulatePerm = (vector unsigned char)vec_splat((vector unsigned int)modulatePerm,0);
  348. zero = (vector float)vec_splat_s8(0);
  349. #endif
  350. for ( l = 0 ; l < backEnd.refdef.num_dlights ; l++ ) {
  351. dlight_t *dl;
  352. if ( !( tess.dlightBits & ( 1 << l ) ) ) {
  353. continue; // this surface definately doesn't have any of this light
  354. }
  355. texCoords = texCoordsArray[0];
  356. colors = colorArray[0];
  357. dl = &backEnd.refdef.dlights[l];
  358. #if idppc_altivec
  359. origin0 = dl->transformed[0];
  360. origin1 = dl->transformed[1];
  361. origin2 = dl->transformed[2];
  362. #else
  363. VectorCopy( dl->transformed, origin );
  364. #endif
  365. radius = dl->radius;
  366. scale = 1.0f / radius;
  367. floatColor[0] = dl->color[0] * 255.0f;
  368. floatColor[1] = dl->color[1] * 255.0f;
  369. floatColor[2] = dl->color[2] * 255.0f;
  370. #if idppc_altivec
  371. floatColorVec0 = vec_ld(0, floatColor);
  372. floatColorVec1 = vec_ld(11, floatColor);
  373. floatColorVec0 = vec_perm(floatColorVec0,floatColorVec0,floatColorVecPerm);
  374. #endif
  375. for ( i = 0 ; i < tess.numVertexes ; i++, texCoords += 2, colors += 4 ) {
  376. #if idppc_altivec
  377. vec_t dist0, dist1, dist2;
  378. #else
  379. vec3_t dist;
  380. #endif
  381. int clip;
  382. backEnd.pc.c_dlightVertexes++;
  383. #if idppc_altivec
  384. //VectorSubtract( origin, tess.xyz[i], dist );
  385. dist0 = origin0 - tess.xyz[i][0];
  386. dist1 = origin1 - tess.xyz[i][1];
  387. dist2 = origin2 - tess.xyz[i][2];
  388. texCoords0 = 0.5f + dist0 * scale;
  389. texCoords1 = 0.5f + dist1 * scale;
  390. clip = 0;
  391. if ( texCoords0 < 0.0f ) {
  392. clip |= 1;
  393. } else if ( texCoords0 > 1.0f ) {
  394. clip |= 2;
  395. }
  396. if ( texCoords1 < 0.0f ) {
  397. clip |= 4;
  398. } else if ( texCoords1 > 1.0f ) {
  399. clip |= 8;
  400. }
  401. texCoords[0] = texCoords0;
  402. texCoords[1] = texCoords1;
  403. // modulate the strength based on the height and color
  404. if ( dist2 > radius ) {
  405. clip |= 16;
  406. modulate = 0.0f;
  407. } else if ( dist2 < -radius ) {
  408. clip |= 32;
  409. modulate = 0.0f;
  410. } else {
  411. dist2 = Q_fabs(dist2);
  412. if ( dist2 < radius * 0.5f ) {
  413. modulate = 1.0f;
  414. } else {
  415. modulate = 2.0f * (radius - dist2) * scale;
  416. }
  417. }
  418. clipBits[i] = clip;
  419. modulateVec = vec_ld(0,(float *)&modulate);
  420. modulateVec = vec_perm(modulateVec,modulateVec,modulatePerm);
  421. colorVec = vec_madd(floatColorVec0,modulateVec,zero);
  422. colorInt = vec_cts(colorVec,0); // RGBx
  423. colorShort = vec_pack(colorInt,colorInt); // RGBxRGBx
  424. colorChar = vec_packsu(colorShort,colorShort); // RGBxRGBxRGBxRGBx
  425. colorChar = vec_sel(colorChar,vSel,vSel); // RGBARGBARGBARGBA replace alpha with 255
  426. vec_ste((vector unsigned int)colorChar,0,(unsigned int *)colors); // store color
  427. #else
  428. VectorSubtract( origin, tess.xyz[i], dist );
  429. texCoords[0] = 0.5f + dist[0] * scale;
  430. texCoords[1] = 0.5f + dist[1] * scale;
  431. clip = 0;
  432. if ( texCoords[0] < 0.0f ) {
  433. clip |= 1;
  434. } else if ( texCoords[0] > 1.0f ) {
  435. clip |= 2;
  436. }
  437. if ( texCoords[1] < 0.0f ) {
  438. clip |= 4;
  439. } else if ( texCoords[1] > 1.0f ) {
  440. clip |= 8;
  441. }
  442. // modulate the strength based on the height and color
  443. if ( dist[2] > radius ) {
  444. clip |= 16;
  445. modulate = 0.0f;
  446. } else if ( dist[2] < -radius ) {
  447. clip |= 32;
  448. modulate = 0.0f;
  449. } else {
  450. dist[2] = Q_fabs(dist[2]);
  451. if ( dist[2] < radius * 0.5f ) {
  452. modulate = 1.0f;
  453. } else {
  454. modulate = 2.0f * (radius - dist[2]) * scale;
  455. }
  456. }
  457. clipBits[i] = clip;
  458. colors[0] = myftol(floatColor[0] * modulate);
  459. colors[1] = myftol(floatColor[1] * modulate);
  460. colors[2] = myftol(floatColor[2] * modulate);
  461. colors[3] = 255;
  462. #endif
  463. }
  464. // build a list of triangles that need light
  465. numIndexes = 0;
  466. for ( i = 0 ; i < tess.numIndexes ; i += 3 ) {
  467. int a, b, c;
  468. a = tess.indexes[i];
  469. b = tess.indexes[i+1];
  470. c = tess.indexes[i+2];
  471. if ( clipBits[a] & clipBits[b] & clipBits[c] ) {
  472. continue; // not lighted
  473. }
  474. hitIndexes[numIndexes] = a;
  475. hitIndexes[numIndexes+1] = b;
  476. hitIndexes[numIndexes+2] = c;
  477. numIndexes += 3;
  478. }
  479. if ( !numIndexes ) {
  480. continue;
  481. }
  482. qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
  483. qglTexCoordPointer( 2, GL_FLOAT, 0, texCoordsArray[0] );
  484. qglEnableClientState( GL_COLOR_ARRAY );
  485. qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, colorArray );
  486. GL_Bind( tr.dlightImage );
  487. // include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light
  488. // where they aren't rendered
  489. if ( dl->additive ) {
  490. GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL );
  491. }
  492. else {
  493. GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL );
  494. }
  495. R_DrawElements( numIndexes, hitIndexes );
  496. backEnd.pc.c_totalIndexes += numIndexes;
  497. backEnd.pc.c_dlightIndexes += numIndexes;
  498. }
  499. }
  500. /*
  501. ===================
  502. RB_FogPass
  503. Blends a fog texture on top of everything else
  504. ===================
  505. */
  506. static void RB_FogPass( void ) {
  507. fog_t *fog;
  508. int i;
  509. qglEnableClientState( GL_COLOR_ARRAY );
  510. qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.svars.colors );
  511. qglEnableClientState( GL_TEXTURE_COORD_ARRAY);
  512. qglTexCoordPointer( 2, GL_FLOAT, 0, tess.svars.texcoords[0] );
  513. fog = tr.world->fogs + tess.fogNum;
  514. for ( i = 0; i < tess.numVertexes; i++ ) {
  515. * ( int * )&tess.svars.colors[i] = fog->colorInt;
  516. }
  517. RB_CalcFogTexCoords( ( float * ) tess.svars.texcoords[0] );
  518. GL_Bind( tr.fogImage );
  519. if ( tess.shader->fogPass == FP_EQUAL ) {
  520. GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_EQUAL );
  521. } else {
  522. GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
  523. }
  524. R_DrawElements( tess.numIndexes, tess.indexes );
  525. }
  526. /*
  527. ===============
  528. ComputeColors
  529. ===============
  530. */
  531. static void ComputeColors( shaderStage_t *pStage )
  532. {
  533. int i;
  534. //
  535. // rgbGen
  536. //
  537. switch ( pStage->rgbGen )
  538. {
  539. case CGEN_IDENTITY:
  540. Com_Memset( tess.svars.colors, 0xff, tess.numVertexes * 4 );
  541. break;
  542. default:
  543. case CGEN_IDENTITY_LIGHTING:
  544. Com_Memset( tess.svars.colors, tr.identityLightByte, tess.numVertexes * 4 );
  545. break;
  546. case CGEN_LIGHTING_DIFFUSE:
  547. RB_CalcDiffuseColor( ( unsigned char * ) tess.svars.colors );
  548. break;
  549. case CGEN_EXACT_VERTEX:
  550. Com_Memcpy( tess.svars.colors, tess.vertexColors, tess.numVertexes * sizeof( tess.vertexColors[0] ) );
  551. break;
  552. case CGEN_CONST:
  553. for ( i = 0; i < tess.numVertexes; i++ ) {
  554. *(int *)tess.svars.colors[i] = *(int *)pStage->constantColor;
  555. }
  556. break;
  557. case CGEN_VERTEX:
  558. if ( tr.identityLight == 1 )
  559. {
  560. Com_Memcpy( tess.svars.colors, tess.vertexColors, tess.numVertexes * sizeof( tess.vertexColors[0] ) );
  561. }
  562. else
  563. {
  564. for ( i = 0; i < tess.numVertexes; i++ )
  565. {
  566. tess.svars.colors[i][0] = tess.vertexColors[i][0] * tr.identityLight;
  567. tess.svars.colors[i][1] = tess.vertexColors[i][1] * tr.identityLight;
  568. tess.svars.colors[i][2] = tess.vertexColors[i][2] * tr.identityLight;
  569. tess.svars.colors[i][3] = tess.vertexColors[i][3];
  570. }
  571. }
  572. break;
  573. case CGEN_ONE_MINUS_VERTEX:
  574. if ( tr.identityLight == 1 )
  575. {
  576. for ( i = 0; i < tess.numVertexes; i++ )
  577. {
  578. tess.svars.colors[i][0] = 255 - tess.vertexColors[i][0];
  579. tess.svars.colors[i][1] = 255 - tess.vertexColors[i][1];
  580. tess.svars.colors[i][2] = 255 - tess.vertexColors[i][2];
  581. }
  582. }
  583. else
  584. {
  585. for ( i = 0; i < tess.numVertexes; i++ )
  586. {
  587. tess.svars.colors[i][0] = ( 255 - tess.vertexColors[i][0] ) * tr.identityLight;
  588. tess.svars.colors[i][1] = ( 255 - tess.vertexColors[i][1] ) * tr.identityLight;
  589. tess.svars.colors[i][2] = ( 255 - tess.vertexColors[i][2] ) * tr.identityLight;
  590. }
  591. }
  592. break;
  593. case CGEN_FOG:
  594. {
  595. fog_t *fog;
  596. fog = tr.world->fogs + tess.fogNum;
  597. for ( i = 0; i < tess.numVertexes; i++ ) {
  598. * ( int * )&tess.svars.colors[i] = fog->colorInt;
  599. }
  600. }
  601. break;
  602. case CGEN_WAVEFORM:
  603. RB_CalcWaveColor( &pStage->rgbWave, ( unsigned char * ) tess.svars.colors );
  604. break;
  605. case CGEN_ENTITY:
  606. RB_CalcColorFromEntity( ( unsigned char * ) tess.svars.colors );
  607. break;
  608. case CGEN_ONE_MINUS_ENTITY:
  609. RB_CalcColorFromOneMinusEntity( ( unsigned char * ) tess.svars.colors );
  610. break;
  611. }
  612. //
  613. // alphaGen
  614. //
  615. switch ( pStage->alphaGen )
  616. {
  617. case AGEN_SKIP:
  618. break;
  619. case AGEN_IDENTITY:
  620. if ( pStage->rgbGen != CGEN_IDENTITY ) {
  621. if ( ( pStage->rgbGen == CGEN_VERTEX && tr.identityLight != 1 ) ||
  622. pStage->rgbGen != CGEN_VERTEX ) {
  623. for ( i = 0; i < tess.numVertexes; i++ ) {
  624. tess.svars.colors[i][3] = 0xff;
  625. }
  626. }
  627. }
  628. break;
  629. case AGEN_CONST:
  630. if ( pStage->rgbGen != CGEN_CONST ) {
  631. for ( i = 0; i < tess.numVertexes; i++ ) {
  632. tess.svars.colors[i][3] = pStage->constantColor[3];
  633. }
  634. }
  635. break;
  636. case AGEN_WAVEFORM:
  637. RB_CalcWaveAlpha( &pStage->alphaWave, ( unsigned char * ) tess.svars.colors );
  638. break;
  639. case AGEN_LIGHTING_SPECULAR:
  640. RB_CalcSpecularAlpha( ( unsigned char * ) tess.svars.colors );
  641. break;
  642. case AGEN_ENTITY:
  643. RB_CalcAlphaFromEntity( ( unsigned char * ) tess.svars.colors );
  644. break;
  645. case AGEN_ONE_MINUS_ENTITY:
  646. RB_CalcAlphaFromOneMinusEntity( ( unsigned char * ) tess.svars.colors );
  647. break;
  648. case AGEN_VERTEX:
  649. if ( pStage->rgbGen != CGEN_VERTEX ) {
  650. for ( i = 0; i < tess.numVertexes; i++ ) {
  651. tess.svars.colors[i][3] = tess.vertexColors[i][3];
  652. }
  653. }
  654. break;
  655. case AGEN_ONE_MINUS_VERTEX:
  656. for ( i = 0; i < tess.numVertexes; i++ )
  657. {
  658. tess.svars.colors[i][3] = 255 - tess.vertexColors[i][3];
  659. }
  660. break;
  661. case AGEN_PORTAL:
  662. {
  663. unsigned char alpha;
  664. for ( i = 0; i < tess.numVertexes; i++ )
  665. {
  666. float len;
  667. vec3_t v;
  668. VectorSubtract( tess.xyz[i], backEnd.viewParms.or.origin, v );
  669. len = VectorLength( v );
  670. len /= tess.shader->portalRange;
  671. if ( len < 0 )
  672. {
  673. alpha = 0;
  674. }
  675. else if ( len > 1 )
  676. {
  677. alpha = 0xff;
  678. }
  679. else
  680. {
  681. alpha = len * 0xff;
  682. }
  683. tess.svars.colors[i][3] = alpha;
  684. }
  685. }
  686. break;
  687. }
  688. //
  689. // fog adjustment for colors to fade out as fog increases
  690. //
  691. if ( tess.fogNum )
  692. {
  693. switch ( pStage->adjustColorsForFog )
  694. {
  695. case ACFF_MODULATE_RGB:
  696. RB_CalcModulateColorsByFog( ( unsigned char * ) tess.svars.colors );
  697. break;
  698. case ACFF_MODULATE_ALPHA:
  699. RB_CalcModulateAlphasByFog( ( unsigned char * ) tess.svars.colors );
  700. break;
  701. case ACFF_MODULATE_RGBA:
  702. RB_CalcModulateRGBAsByFog( ( unsigned char * ) tess.svars.colors );
  703. break;
  704. case ACFF_NONE:
  705. break;
  706. }
  707. }
  708. }
  709. /*
  710. ===============
  711. ComputeTexCoords
  712. ===============
  713. */
  714. static void ComputeTexCoords( shaderStage_t *pStage ) {
  715. int i;
  716. int b;
  717. for ( b = 0; b < NUM_TEXTURE_BUNDLES; b++ ) {
  718. int tm;
  719. //
  720. // generate the texture coordinates
  721. //
  722. switch ( pStage->bundle[b].tcGen )
  723. {
  724. case TCGEN_IDENTITY:
  725. Com_Memset( tess.svars.texcoords[b], 0, sizeof( float ) * 2 * tess.numVertexes );
  726. break;
  727. case TCGEN_TEXTURE:
  728. for ( i = 0 ; i < tess.numVertexes ; i++ ) {
  729. tess.svars.texcoords[b][i][0] = tess.texCoords[i][0][0];
  730. tess.svars.texcoords[b][i][1] = tess.texCoords[i][0][1];
  731. }
  732. break;
  733. case TCGEN_LIGHTMAP:
  734. for ( i = 0 ; i < tess.numVertexes ; i++ ) {
  735. tess.svars.texcoords[b][i][0] = tess.texCoords[i][1][0];
  736. tess.svars.texcoords[b][i][1] = tess.texCoords[i][1][1];
  737. }
  738. break;
  739. case TCGEN_VECTOR:
  740. for ( i = 0 ; i < tess.numVertexes ; i++ ) {
  741. tess.svars.texcoords[b][i][0] = DotProduct( tess.xyz[i], pStage->bundle[b].tcGenVectors[0] );
  742. tess.svars.texcoords[b][i][1] = DotProduct( tess.xyz[i], pStage->bundle[b].tcGenVectors[1] );
  743. }
  744. break;
  745. case TCGEN_FOG:
  746. RB_CalcFogTexCoords( ( float * ) tess.svars.texcoords[b] );
  747. break;
  748. case TCGEN_ENVIRONMENT_MAPPED:
  749. RB_CalcEnvironmentTexCoords( ( float * ) tess.svars.texcoords[b] );
  750. break;
  751. case TCGEN_BAD:
  752. return;
  753. }
  754. //
  755. // alter texture coordinates
  756. //
  757. for ( tm = 0; tm < pStage->bundle[b].numTexMods ; tm++ ) {
  758. switch ( pStage->bundle[b].texMods[tm].type )
  759. {
  760. case TMOD_NONE:
  761. tm = TR_MAX_TEXMODS; // break out of for loop
  762. break;
  763. case TMOD_TURBULENT:
  764. RB_CalcTurbulentTexCoords( &pStage->bundle[b].texMods[tm].wave,
  765. ( float * ) tess.svars.texcoords[b] );
  766. break;
  767. case TMOD_ENTITY_TRANSLATE:
  768. RB_CalcScrollTexCoords( backEnd.currentEntity->e.shaderTexCoord,
  769. ( float * ) tess.svars.texcoords[b] );
  770. break;
  771. case TMOD_SCROLL:
  772. RB_CalcScrollTexCoords( pStage->bundle[b].texMods[tm].scroll,
  773. ( float * ) tess.svars.texcoords[b] );
  774. break;
  775. case TMOD_SCALE:
  776. RB_CalcScaleTexCoords( pStage->bundle[b].texMods[tm].scale,
  777. ( float * ) tess.svars.texcoords[b] );
  778. break;
  779. case TMOD_STRETCH:
  780. RB_CalcStretchTexCoords( &pStage->bundle[b].texMods[tm].wave,
  781. ( float * ) tess.svars.texcoords[b] );
  782. break;
  783. case TMOD_TRANSFORM:
  784. RB_CalcTransformTexCoords( &pStage->bundle[b].texMods[tm],
  785. ( float * ) tess.svars.texcoords[b] );
  786. break;
  787. case TMOD_ROTATE:
  788. RB_CalcRotateTexCoords( pStage->bundle[b].texMods[tm].rotateSpeed,
  789. ( float * ) tess.svars.texcoords[b] );
  790. break;
  791. default:
  792. ri.Error( ERR_DROP, "ERROR: unknown texmod '%d' in shader '%s'\n", pStage->bundle[b].texMods[tm].type, tess.shader->name );
  793. break;
  794. }
  795. }
  796. }
  797. }
  798. /*
  799. ** RB_IterateStagesGeneric
  800. */
  801. static void RB_IterateStagesGeneric( shaderCommands_t *input )
  802. {
  803. int stage;
  804. for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ )
  805. {
  806. shaderStage_t *pStage = tess.xstages[stage];
  807. if ( !pStage )
  808. {
  809. break;
  810. }
  811. ComputeColors( pStage );
  812. ComputeTexCoords( pStage );
  813. if ( !setArraysOnce )
  814. {
  815. qglEnableClientState( GL_COLOR_ARRAY );
  816. qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, input->svars.colors );
  817. }
  818. //
  819. // do multitexture
  820. //
  821. if ( pStage->bundle[1].image[0] != 0 )
  822. {
  823. DrawMultitextured( input, stage );
  824. }
  825. else
  826. {
  827. if ( !setArraysOnce )
  828. {
  829. qglTexCoordPointer( 2, GL_FLOAT, 0, input->svars.texcoords[0] );
  830. }
  831. //
  832. // set state
  833. //
  834. if ( pStage->bundle[0].vertexLightmap && ( (r_vertexLight->integer && !r_uiFullScreen->integer) || glConfig.hardwareType == GLHW_PERMEDIA2 ) && r_lightmap->integer )
  835. {
  836. GL_Bind( tr.whiteImage );
  837. }
  838. else
  839. R_BindAnimatedImage( &pStage->bundle[0] );
  840. GL_State( pStage->stateBits );
  841. //
  842. // draw
  843. //
  844. R_DrawElements( input->numIndexes, input->indexes );
  845. }
  846. // allow skipping out to show just lightmaps during development
  847. if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap || pStage->bundle[0].vertexLightmap ) )
  848. {
  849. break;
  850. }
  851. }
  852. }
  853. /*
  854. ** RB_StageIteratorGeneric
  855. */
  856. void RB_StageIteratorGeneric( void )
  857. {
  858. shaderCommands_t *input;
  859. input = &tess;
  860. RB_DeformTessGeometry();
  861. //
  862. // log this call
  863. //
  864. if ( r_logFile->integer )
  865. {
  866. // don't just call LogComment, or we will get
  867. // a call to va() every frame!
  868. GLimp_LogComment( va("--- RB_StageIteratorGeneric( %s ) ---\n", tess.shader->name) );
  869. }
  870. //
  871. // set face culling appropriately
  872. //
  873. GL_Cull( input->shader->cullType );
  874. // set polygon offset if necessary
  875. if ( input->shader->polygonOffset )
  876. {
  877. qglEnable( GL_POLYGON_OFFSET_FILL );
  878. qglPolygonOffset( r_offsetFactor->value, r_offsetUnits->value );
  879. }
  880. //
  881. // if there is only a single pass then we can enable color
  882. // and texture arrays before we compile, otherwise we need
  883. // to avoid compiling those arrays since they will change
  884. // during multipass rendering
  885. //
  886. if ( tess.numPasses > 1 || input->shader->multitextureEnv )
  887. {
  888. setArraysOnce = qfalse;
  889. qglDisableClientState (GL_COLOR_ARRAY);
  890. qglDisableClientState (GL_TEXTURE_COORD_ARRAY);
  891. }
  892. else
  893. {
  894. setArraysOnce = qtrue;
  895. qglEnableClientState( GL_COLOR_ARRAY);
  896. qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.svars.colors );
  897. qglEnableClientState( GL_TEXTURE_COORD_ARRAY);
  898. qglTexCoordPointer( 2, GL_FLOAT, 0, tess.svars.texcoords[0] );
  899. }
  900. //
  901. // lock XYZ
  902. //
  903. qglVertexPointer (3, GL_FLOAT, 16, input->xyz); // padded for SIMD
  904. if (qglLockArraysEXT)
  905. {
  906. qglLockArraysEXT(0, input->numVertexes);
  907. GLimp_LogComment( "glLockArraysEXT\n" );
  908. }
  909. //
  910. // enable color and texcoord arrays after the lock if necessary
  911. //
  912. if ( !setArraysOnce )
  913. {
  914. qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
  915. qglEnableClientState( GL_COLOR_ARRAY );
  916. }
  917. //
  918. // call shader function
  919. //
  920. RB_IterateStagesGeneric( input );
  921. //
  922. // now do any dynamic lighting needed
  923. //
  924. if ( tess.dlightBits && tess.shader->sort <= SS_OPAQUE
  925. && !(tess.shader->surfaceFlags & (SURF_NODLIGHT | SURF_SKY) ) ) {
  926. ProjectDlightTexture();
  927. }
  928. //
  929. // now do fog
  930. //
  931. if ( tess.fogNum && tess.shader->fogPass ) {
  932. RB_FogPass();
  933. }
  934. //
  935. // unlock arrays
  936. //
  937. if (qglUnlockArraysEXT)
  938. {
  939. qglUnlockArraysEXT();
  940. GLimp_LogComment( "glUnlockArraysEXT\n" );
  941. }
  942. //
  943. // reset polygon offset
  944. //
  945. if ( input->shader->polygonOffset )
  946. {
  947. qglDisable( GL_POLYGON_OFFSET_FILL );
  948. }
  949. }
  950. /*
  951. ** RB_StageIteratorVertexLitTexture
  952. */
  953. void RB_StageIteratorVertexLitTexture( void )
  954. {
  955. shaderCommands_t *input;
  956. shader_t *shader;
  957. input = &tess;
  958. shader = input->shader;
  959. //
  960. // compute colors
  961. //
  962. RB_CalcDiffuseColor( ( unsigned char * ) tess.svars.colors );
  963. //
  964. // log this call
  965. //
  966. if ( r_logFile->integer )
  967. {
  968. // don't just call LogComment, or we will get
  969. // a call to va() every frame!
  970. GLimp_LogComment( va("--- RB_StageIteratorVertexLitTexturedUnfogged( %s ) ---\n", tess.shader->name) );
  971. }
  972. //
  973. // set face culling appropriately
  974. //
  975. GL_Cull( input->shader->cullType );
  976. //
  977. // set arrays and lock
  978. //
  979. qglEnableClientState( GL_COLOR_ARRAY);
  980. qglEnableClientState( GL_TEXTURE_COORD_ARRAY);
  981. qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.svars.colors );
  982. qglTexCoordPointer( 2, GL_FLOAT, 16, tess.texCoords[0][0] );
  983. qglVertexPointer (3, GL_FLOAT, 16, input->xyz);
  984. if ( qglLockArraysEXT )
  985. {
  986. qglLockArraysEXT(0, input->numVertexes);
  987. GLimp_LogComment( "glLockArraysEXT\n" );
  988. }
  989. //
  990. // call special shade routine
  991. //
  992. R_BindAnimatedImage( &tess.xstages[0]->bundle[0] );
  993. GL_State( tess.xstages[0]->stateBits );
  994. R_DrawElements( input->numIndexes, input->indexes );
  995. //
  996. // now do any dynamic lighting needed
  997. //
  998. if ( tess.dlightBits && tess.shader->sort <= SS_OPAQUE ) {
  999. ProjectDlightTexture();
  1000. }
  1001. //
  1002. // now do fog
  1003. //
  1004. if ( tess.fogNum && tess.shader->fogPass ) {
  1005. RB_FogPass();
  1006. }
  1007. //
  1008. // unlock arrays
  1009. //
  1010. if (qglUnlockArraysEXT)
  1011. {
  1012. qglUnlockArraysEXT();
  1013. GLimp_LogComment( "glUnlockArraysEXT\n" );
  1014. }
  1015. }
  1016. //define REPLACE_MODE
  1017. void RB_StageIteratorLightmappedMultitexture( void ) {
  1018. shaderCommands_t *input;
  1019. input = &tess;
  1020. //
  1021. // log this call
  1022. //
  1023. if ( r_logFile->integer ) {
  1024. // don't just call LogComment, or we will get
  1025. // a call to va() every frame!
  1026. GLimp_LogComment( va("--- RB_StageIteratorLightmappedMultitexture( %s ) ---\n", tess.shader->name) );
  1027. }
  1028. //
  1029. // set face culling appropriately
  1030. //
  1031. GL_Cull( input->shader->cullType );
  1032. //
  1033. // set color, pointers, and lock
  1034. //
  1035. GL_State( GLS_DEFAULT );
  1036. qglVertexPointer( 3, GL_FLOAT, 16, input->xyz );
  1037. #ifdef REPLACE_MODE
  1038. qglDisableClientState( GL_COLOR_ARRAY );
  1039. qglColor3f( 1, 1, 1 );
  1040. qglShadeModel( GL_FLAT );
  1041. #else
  1042. qglEnableClientState( GL_COLOR_ARRAY );
  1043. qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.constantColor255 );
  1044. #endif
  1045. //
  1046. // select base stage
  1047. //
  1048. GL_SelectTexture( 0 );
  1049. qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
  1050. R_BindAnimatedImage( &tess.xstages[0]->bundle[0] );
  1051. qglTexCoordPointer( 2, GL_FLOAT, 16, tess.texCoords[0][0] );
  1052. //
  1053. // configure second stage
  1054. //
  1055. GL_SelectTexture( 1 );
  1056. qglEnable( GL_TEXTURE_2D );
  1057. if ( r_lightmap->integer ) {
  1058. GL_TexEnv( GL_REPLACE );
  1059. } else {
  1060. GL_TexEnv( GL_MODULATE );
  1061. }
  1062. R_BindAnimatedImage( &tess.xstages[0]->bundle[1] );
  1063. qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
  1064. qglTexCoordPointer( 2, GL_FLOAT, 16, tess.texCoords[0][1] );
  1065. //
  1066. // lock arrays
  1067. //
  1068. if ( qglLockArraysEXT ) {
  1069. qglLockArraysEXT(0, input->numVertexes);
  1070. GLimp_LogComment( "glLockArraysEXT\n" );
  1071. }
  1072. R_DrawElements( input->numIndexes, input->indexes );
  1073. //
  1074. // disable texturing on TEXTURE1, then select TEXTURE0
  1075. //
  1076. qglDisable( GL_TEXTURE_2D );
  1077. qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
  1078. GL_SelectTexture( 0 );
  1079. #ifdef REPLACE_MODE
  1080. GL_TexEnv( GL_MODULATE );
  1081. qglShadeModel( GL_SMOOTH );
  1082. #endif
  1083. //
  1084. // now do any dynamic lighting needed
  1085. //
  1086. if ( tess.dlightBits && tess.shader->sort <= SS_OPAQUE ) {
  1087. ProjectDlightTexture();
  1088. }
  1089. //
  1090. // now do fog
  1091. //
  1092. if ( tess.fogNum && tess.shader->fogPass ) {
  1093. RB_FogPass();
  1094. }
  1095. //
  1096. // unlock arrays
  1097. //
  1098. if ( qglUnlockArraysEXT ) {
  1099. qglUnlockArraysEXT();
  1100. GLimp_LogComment( "glUnlockArraysEXT\n" );
  1101. }
  1102. }
  1103. /*
  1104. ** RB_EndSurface
  1105. */
  1106. void RB_EndSurface( void ) {
  1107. shaderCommands_t *input;
  1108. input = &tess;
  1109. if (input->numIndexes == 0) {
  1110. return;
  1111. }
  1112. if (input->indexes[SHADER_MAX_INDEXES-1] != 0) {
  1113. ri.Error (ERR_DROP, "RB_EndSurface() - SHADER_MAX_INDEXES hit");
  1114. }
  1115. if (input->xyz[SHADER_MAX_VERTEXES-1][0] != 0) {
  1116. ri.Error (ERR_DROP, "RB_EndSurface() - SHADER_MAX_VERTEXES hit");
  1117. }
  1118. if ( tess.shader == tr.shadowShader ) {
  1119. RB_ShadowTessEnd();
  1120. return;
  1121. }
  1122. // for debugging of sort order issues, stop rendering after a given sort value
  1123. if ( r_debugSort->integer && r_debugSort->integer < tess.shader->sort ) {
  1124. return;
  1125. }
  1126. //
  1127. // update performance counters
  1128. //
  1129. backEnd.pc.c_shaders++;
  1130. backEnd.pc.c_vertexes += tess.numVertexes;
  1131. backEnd.pc.c_indexes += tess.numIndexes;
  1132. backEnd.pc.c_totalIndexes += tess.numIndexes * tess.numPasses;
  1133. //
  1134. // call off to shader specific tess end function
  1135. //
  1136. tess.currentStageIteratorFunc();
  1137. //
  1138. // draw debugging stuff
  1139. //
  1140. if ( r_showtris->integer ) {
  1141. DrawTris (input);
  1142. }
  1143. if ( r_shownormals->integer ) {
  1144. DrawNormals (input);
  1145. }
  1146. // clear shader so we can tell we don't have any unclosed surfaces
  1147. tess.numIndexes = 0;
  1148. GLimp_LogComment( "----------\n" );
  1149. }