tr_sky.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846
  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_sky.c
  19. #include "tr_local.h"
  20. #define SKY_SUBDIVISIONS 8
  21. #define HALF_SKY_SUBDIVISIONS (SKY_SUBDIVISIONS/2)
  22. static float s_cloudTexCoords[6][SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1][2];
  23. static float s_cloudTexP[6][SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1];
  24. /*
  25. ===================================================================================
  26. POLYGON TO BOX SIDE PROJECTION
  27. ===================================================================================
  28. */
  29. static vec3_t sky_clip[6] =
  30. {
  31. {1,1,0},
  32. {1,-1,0},
  33. {0,-1,1},
  34. {0,1,1},
  35. {1,0,1},
  36. {-1,0,1}
  37. };
  38. static float sky_mins[2][6], sky_maxs[2][6];
  39. static float sky_min, sky_max;
  40. /*
  41. ================
  42. AddSkyPolygon
  43. ================
  44. */
  45. static void AddSkyPolygon (int nump, vec3_t vecs)
  46. {
  47. int i,j;
  48. vec3_t v, av;
  49. float s, t, dv;
  50. int axis;
  51. float *vp;
  52. // s = [0]/[2], t = [1]/[2]
  53. static int vec_to_st[6][3] =
  54. {
  55. {-2,3,1},
  56. {2,3,-1},
  57. {1,3,2},
  58. {-1,3,-2},
  59. {-2,-1,3},
  60. {-2,1,-3}
  61. // {-1,2,3},
  62. // {1,2,-3}
  63. };
  64. // decide which face it maps to
  65. VectorCopy (vec3_origin, v);
  66. for (i=0, vp=vecs ; i<nump ; i++, vp+=3)
  67. {
  68. VectorAdd (vp, v, v);
  69. }
  70. av[0] = fabs(v[0]);
  71. av[1] = fabs(v[1]);
  72. av[2] = fabs(v[2]);
  73. if (av[0] > av[1] && av[0] > av[2])
  74. {
  75. if (v[0] < 0)
  76. axis = 1;
  77. else
  78. axis = 0;
  79. }
  80. else if (av[1] > av[2] && av[1] > av[0])
  81. {
  82. if (v[1] < 0)
  83. axis = 3;
  84. else
  85. axis = 2;
  86. }
  87. else
  88. {
  89. if (v[2] < 0)
  90. axis = 5;
  91. else
  92. axis = 4;
  93. }
  94. // project new texture coords
  95. for (i=0 ; i<nump ; i++, vecs+=3)
  96. {
  97. j = vec_to_st[axis][2];
  98. if (j > 0)
  99. dv = vecs[j - 1];
  100. else
  101. dv = -vecs[-j - 1];
  102. if (dv < 0.001)
  103. continue; // don't divide by zero
  104. j = vec_to_st[axis][0];
  105. if (j < 0)
  106. s = -vecs[-j -1] / dv;
  107. else
  108. s = vecs[j-1] / dv;
  109. j = vec_to_st[axis][1];
  110. if (j < 0)
  111. t = -vecs[-j -1] / dv;
  112. else
  113. t = vecs[j-1] / dv;
  114. if (s < sky_mins[0][axis])
  115. sky_mins[0][axis] = s;
  116. if (t < sky_mins[1][axis])
  117. sky_mins[1][axis] = t;
  118. if (s > sky_maxs[0][axis])
  119. sky_maxs[0][axis] = s;
  120. if (t > sky_maxs[1][axis])
  121. sky_maxs[1][axis] = t;
  122. }
  123. }
  124. #define ON_EPSILON 0.1f // point on plane side epsilon
  125. #define MAX_CLIP_VERTS 64
  126. /*
  127. ================
  128. ClipSkyPolygon
  129. ================
  130. */
  131. static void ClipSkyPolygon (int nump, vec3_t vecs, int stage)
  132. {
  133. float *norm;
  134. float *v;
  135. qboolean front, back;
  136. float d, e;
  137. float dists[MAX_CLIP_VERTS];
  138. int sides[MAX_CLIP_VERTS];
  139. vec3_t newv[2][MAX_CLIP_VERTS];
  140. int newc[2];
  141. int i, j;
  142. if (nump > MAX_CLIP_VERTS-2)
  143. ri.Error (ERR_DROP, "ClipSkyPolygon: MAX_CLIP_VERTS");
  144. if (stage == 6)
  145. { // fully clipped, so draw it
  146. AddSkyPolygon (nump, vecs);
  147. return;
  148. }
  149. front = back = qfalse;
  150. norm = sky_clip[stage];
  151. for (i=0, v = vecs ; i<nump ; i++, v+=3)
  152. {
  153. d = DotProduct (v, norm);
  154. if (d > ON_EPSILON)
  155. {
  156. front = qtrue;
  157. sides[i] = SIDE_FRONT;
  158. }
  159. else if (d < -ON_EPSILON)
  160. {
  161. back = qtrue;
  162. sides[i] = SIDE_BACK;
  163. }
  164. else
  165. sides[i] = SIDE_ON;
  166. dists[i] = d;
  167. }
  168. if (!front || !back)
  169. { // not clipped
  170. ClipSkyPolygon (nump, vecs, stage+1);
  171. return;
  172. }
  173. // clip it
  174. sides[i] = sides[0];
  175. dists[i] = dists[0];
  176. VectorCopy (vecs, (vecs+(i*3)) );
  177. newc[0] = newc[1] = 0;
  178. for (i=0, v = vecs ; i<nump ; i++, v+=3)
  179. {
  180. switch (sides[i])
  181. {
  182. case SIDE_FRONT:
  183. VectorCopy (v, newv[0][newc[0]]);
  184. newc[0]++;
  185. break;
  186. case SIDE_BACK:
  187. VectorCopy (v, newv[1][newc[1]]);
  188. newc[1]++;
  189. break;
  190. case SIDE_ON:
  191. VectorCopy (v, newv[0][newc[0]]);
  192. newc[0]++;
  193. VectorCopy (v, newv[1][newc[1]]);
  194. newc[1]++;
  195. break;
  196. }
  197. if (sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
  198. continue;
  199. d = dists[i] / (dists[i] - dists[i+1]);
  200. for (j=0 ; j<3 ; j++)
  201. {
  202. e = v[j] + d*(v[j+3] - v[j]);
  203. newv[0][newc[0]][j] = e;
  204. newv[1][newc[1]][j] = e;
  205. }
  206. newc[0]++;
  207. newc[1]++;
  208. }
  209. // continue
  210. ClipSkyPolygon (newc[0], newv[0][0], stage+1);
  211. ClipSkyPolygon (newc[1], newv[1][0], stage+1);
  212. }
  213. /*
  214. ==============
  215. ClearSkyBox
  216. ==============
  217. */
  218. static void ClearSkyBox (void) {
  219. int i;
  220. for (i=0 ; i<6 ; i++) {
  221. sky_mins[0][i] = sky_mins[1][i] = 9999;
  222. sky_maxs[0][i] = sky_maxs[1][i] = -9999;
  223. }
  224. }
  225. /*
  226. ================
  227. RB_ClipSkyPolygons
  228. ================
  229. */
  230. void RB_ClipSkyPolygons( shaderCommands_t *input )
  231. {
  232. vec3_t p[5]; // need one extra point for clipping
  233. int i, j;
  234. ClearSkyBox();
  235. for ( i = 0; i < input->numIndexes; i += 3 )
  236. {
  237. for (j = 0 ; j < 3 ; j++)
  238. {
  239. VectorSubtract( input->xyz[input->indexes[i+j]],
  240. backEnd.viewParms.or.origin,
  241. p[j] );
  242. }
  243. ClipSkyPolygon( 3, p[0], 0 );
  244. }
  245. }
  246. /*
  247. ===================================================================================
  248. CLOUD VERTEX GENERATION
  249. ===================================================================================
  250. */
  251. /*
  252. ** MakeSkyVec
  253. **
  254. ** Parms: s, t range from -1 to 1
  255. */
  256. static void MakeSkyVec( float s, float t, int axis, float outSt[2], vec3_t outXYZ )
  257. {
  258. // 1 = s, 2 = t, 3 = 2048
  259. static int st_to_vec[6][3] =
  260. {
  261. {3,-1,2},
  262. {-3,1,2},
  263. {1,3,2},
  264. {-1,-3,2},
  265. {-2,-1,3}, // 0 degrees yaw, look straight up
  266. {2,-1,-3} // look straight down
  267. };
  268. vec3_t b;
  269. int j, k;
  270. float boxSize;
  271. boxSize = backEnd.viewParms.zFar / 1.75; // div sqrt(3)
  272. b[0] = s*boxSize;
  273. b[1] = t*boxSize;
  274. b[2] = boxSize;
  275. for (j=0 ; j<3 ; j++)
  276. {
  277. k = st_to_vec[axis][j];
  278. if (k < 0)
  279. {
  280. outXYZ[j] = -b[-k - 1];
  281. }
  282. else
  283. {
  284. outXYZ[j] = b[k - 1];
  285. }
  286. }
  287. // avoid bilerp seam
  288. s = (s+1)*0.5;
  289. t = (t+1)*0.5;
  290. if (s < sky_min)
  291. {
  292. s = sky_min;
  293. }
  294. else if (s > sky_max)
  295. {
  296. s = sky_max;
  297. }
  298. if (t < sky_min)
  299. {
  300. t = sky_min;
  301. }
  302. else if (t > sky_max)
  303. {
  304. t = sky_max;
  305. }
  306. t = 1.0 - t;
  307. if ( outSt )
  308. {
  309. outSt[0] = s;
  310. outSt[1] = t;
  311. }
  312. }
  313. static int sky_texorder[6] = {0,2,1,3,4,5};
  314. static vec3_t s_skyPoints[SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1];
  315. static float s_skyTexCoords[SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1][2];
  316. static void DrawSkySide( struct image_s *image, const int mins[2], const int maxs[2] )
  317. {
  318. int s, t;
  319. GL_Bind( image );
  320. for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t < maxs[1]+HALF_SKY_SUBDIVISIONS; t++ )
  321. {
  322. qglBegin( GL_TRIANGLE_STRIP );
  323. for ( s = mins[0]+HALF_SKY_SUBDIVISIONS; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++ )
  324. {
  325. qglTexCoord2fv( s_skyTexCoords[t][s] );
  326. qglVertex3fv( s_skyPoints[t][s] );
  327. qglTexCoord2fv( s_skyTexCoords[t+1][s] );
  328. qglVertex3fv( s_skyPoints[t+1][s] );
  329. }
  330. qglEnd();
  331. }
  332. }
  333. static void DrawSkyBox( shader_t *shader )
  334. {
  335. int i;
  336. sky_min = 0;
  337. sky_max = 1;
  338. Com_Memset( s_skyTexCoords, 0, sizeof( s_skyTexCoords ) );
  339. for (i=0 ; i<6 ; i++)
  340. {
  341. int sky_mins_subd[2], sky_maxs_subd[2];
  342. int s, t;
  343. sky_mins[0][i] = floor( sky_mins[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
  344. sky_mins[1][i] = floor( sky_mins[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
  345. sky_maxs[0][i] = ceil( sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
  346. sky_maxs[1][i] = ceil( sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
  347. if ( ( sky_mins[0][i] >= sky_maxs[0][i] ) ||
  348. ( sky_mins[1][i] >= sky_maxs[1][i] ) )
  349. {
  350. continue;
  351. }
  352. sky_mins_subd[0] = sky_mins[0][i] * HALF_SKY_SUBDIVISIONS;
  353. sky_mins_subd[1] = sky_mins[1][i] * HALF_SKY_SUBDIVISIONS;
  354. sky_maxs_subd[0] = sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS;
  355. sky_maxs_subd[1] = sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS;
  356. if ( sky_mins_subd[0] < -HALF_SKY_SUBDIVISIONS )
  357. sky_mins_subd[0] = -HALF_SKY_SUBDIVISIONS;
  358. else if ( sky_mins_subd[0] > HALF_SKY_SUBDIVISIONS )
  359. sky_mins_subd[0] = HALF_SKY_SUBDIVISIONS;
  360. if ( sky_mins_subd[1] < -HALF_SKY_SUBDIVISIONS )
  361. sky_mins_subd[1] = -HALF_SKY_SUBDIVISIONS;
  362. else if ( sky_mins_subd[1] > HALF_SKY_SUBDIVISIONS )
  363. sky_mins_subd[1] = HALF_SKY_SUBDIVISIONS;
  364. if ( sky_maxs_subd[0] < -HALF_SKY_SUBDIVISIONS )
  365. sky_maxs_subd[0] = -HALF_SKY_SUBDIVISIONS;
  366. else if ( sky_maxs_subd[0] > HALF_SKY_SUBDIVISIONS )
  367. sky_maxs_subd[0] = HALF_SKY_SUBDIVISIONS;
  368. if ( sky_maxs_subd[1] < -HALF_SKY_SUBDIVISIONS )
  369. sky_maxs_subd[1] = -HALF_SKY_SUBDIVISIONS;
  370. else if ( sky_maxs_subd[1] > HALF_SKY_SUBDIVISIONS )
  371. sky_maxs_subd[1] = HALF_SKY_SUBDIVISIONS;
  372. //
  373. // iterate through the subdivisions
  374. //
  375. for ( t = sky_mins_subd[1]+HALF_SKY_SUBDIVISIONS; t <= sky_maxs_subd[1]+HALF_SKY_SUBDIVISIONS; t++ )
  376. {
  377. for ( s = sky_mins_subd[0]+HALF_SKY_SUBDIVISIONS; s <= sky_maxs_subd[0]+HALF_SKY_SUBDIVISIONS; s++ )
  378. {
  379. MakeSkyVec( ( s - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS,
  380. ( t - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS,
  381. i,
  382. s_skyTexCoords[t][s],
  383. s_skyPoints[t][s] );
  384. }
  385. }
  386. DrawSkySide( shader->sky.outerbox[sky_texorder[i]],
  387. sky_mins_subd,
  388. sky_maxs_subd );
  389. }
  390. }
  391. static void FillCloudySkySide( const int mins[2], const int maxs[2], qboolean addIndexes )
  392. {
  393. int s, t;
  394. int vertexStart = tess.numVertexes;
  395. int tHeight, sWidth;
  396. tHeight = maxs[1] - mins[1] + 1;
  397. sWidth = maxs[0] - mins[0] + 1;
  398. for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t <= maxs[1]+HALF_SKY_SUBDIVISIONS; t++ )
  399. {
  400. for ( s = mins[0]+HALF_SKY_SUBDIVISIONS; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++ )
  401. {
  402. VectorAdd( s_skyPoints[t][s], backEnd.viewParms.or.origin, tess.xyz[tess.numVertexes] );
  403. tess.texCoords[tess.numVertexes][0][0] = s_skyTexCoords[t][s][0];
  404. tess.texCoords[tess.numVertexes][0][1] = s_skyTexCoords[t][s][1];
  405. tess.numVertexes++;
  406. if ( tess.numVertexes >= SHADER_MAX_VERTEXES )
  407. {
  408. ri.Error( ERR_DROP, "SHADER_MAX_VERTEXES hit in FillCloudySkySide()\n" );
  409. }
  410. }
  411. }
  412. // only add indexes for one pass, otherwise it would draw multiple times for each pass
  413. if ( addIndexes ) {
  414. for ( t = 0; t < tHeight-1; t++ )
  415. {
  416. for ( s = 0; s < sWidth-1; s++ )
  417. {
  418. tess.indexes[tess.numIndexes] = vertexStart + s + t * ( sWidth );
  419. tess.numIndexes++;
  420. tess.indexes[tess.numIndexes] = vertexStart + s + ( t + 1 ) * ( sWidth );
  421. tess.numIndexes++;
  422. tess.indexes[tess.numIndexes] = vertexStart + s + 1 + t * ( sWidth );
  423. tess.numIndexes++;
  424. tess.indexes[tess.numIndexes] = vertexStart + s + ( t + 1 ) * ( sWidth );
  425. tess.numIndexes++;
  426. tess.indexes[tess.numIndexes] = vertexStart + s + 1 + ( t + 1 ) * ( sWidth );
  427. tess.numIndexes++;
  428. tess.indexes[tess.numIndexes] = vertexStart + s + 1 + t * ( sWidth );
  429. tess.numIndexes++;
  430. }
  431. }
  432. }
  433. }
  434. static void FillCloudBox( const shader_t *shader, int stage )
  435. {
  436. int i;
  437. for ( i =0; i < 6; i++ )
  438. {
  439. int sky_mins_subd[2], sky_maxs_subd[2];
  440. int s, t;
  441. float MIN_T;
  442. if ( 1 ) // FIXME? shader->sky.fullClouds )
  443. {
  444. MIN_T = -HALF_SKY_SUBDIVISIONS;
  445. // still don't want to draw the bottom, even if fullClouds
  446. if ( i == 5 )
  447. continue;
  448. }
  449. else
  450. {
  451. switch( i )
  452. {
  453. case 0:
  454. case 1:
  455. case 2:
  456. case 3:
  457. MIN_T = -1;
  458. break;
  459. case 5:
  460. // don't draw clouds beneath you
  461. continue;
  462. case 4: // top
  463. default:
  464. MIN_T = -HALF_SKY_SUBDIVISIONS;
  465. break;
  466. }
  467. }
  468. sky_mins[0][i] = floor( sky_mins[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
  469. sky_mins[1][i] = floor( sky_mins[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
  470. sky_maxs[0][i] = ceil( sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
  471. sky_maxs[1][i] = ceil( sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
  472. if ( ( sky_mins[0][i] >= sky_maxs[0][i] ) ||
  473. ( sky_mins[1][i] >= sky_maxs[1][i] ) )
  474. {
  475. continue;
  476. }
  477. sky_mins_subd[0] = myftol( sky_mins[0][i] * HALF_SKY_SUBDIVISIONS );
  478. sky_mins_subd[1] = myftol( sky_mins[1][i] * HALF_SKY_SUBDIVISIONS );
  479. sky_maxs_subd[0] = myftol( sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS );
  480. sky_maxs_subd[1] = myftol( sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS );
  481. if ( sky_mins_subd[0] < -HALF_SKY_SUBDIVISIONS )
  482. sky_mins_subd[0] = -HALF_SKY_SUBDIVISIONS;
  483. else if ( sky_mins_subd[0] > HALF_SKY_SUBDIVISIONS )
  484. sky_mins_subd[0] = HALF_SKY_SUBDIVISIONS;
  485. if ( sky_mins_subd[1] < MIN_T )
  486. sky_mins_subd[1] = MIN_T;
  487. else if ( sky_mins_subd[1] > HALF_SKY_SUBDIVISIONS )
  488. sky_mins_subd[1] = HALF_SKY_SUBDIVISIONS;
  489. if ( sky_maxs_subd[0] < -HALF_SKY_SUBDIVISIONS )
  490. sky_maxs_subd[0] = -HALF_SKY_SUBDIVISIONS;
  491. else if ( sky_maxs_subd[0] > HALF_SKY_SUBDIVISIONS )
  492. sky_maxs_subd[0] = HALF_SKY_SUBDIVISIONS;
  493. if ( sky_maxs_subd[1] < MIN_T )
  494. sky_maxs_subd[1] = MIN_T;
  495. else if ( sky_maxs_subd[1] > HALF_SKY_SUBDIVISIONS )
  496. sky_maxs_subd[1] = HALF_SKY_SUBDIVISIONS;
  497. //
  498. // iterate through the subdivisions
  499. //
  500. for ( t = sky_mins_subd[1]+HALF_SKY_SUBDIVISIONS; t <= sky_maxs_subd[1]+HALF_SKY_SUBDIVISIONS; t++ )
  501. {
  502. for ( s = sky_mins_subd[0]+HALF_SKY_SUBDIVISIONS; s <= sky_maxs_subd[0]+HALF_SKY_SUBDIVISIONS; s++ )
  503. {
  504. MakeSkyVec( ( s - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS,
  505. ( t - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS,
  506. i,
  507. NULL,
  508. s_skyPoints[t][s] );
  509. s_skyTexCoords[t][s][0] = s_cloudTexCoords[i][t][s][0];
  510. s_skyTexCoords[t][s][1] = s_cloudTexCoords[i][t][s][1];
  511. }
  512. }
  513. // only add indexes for first stage
  514. FillCloudySkySide( sky_mins_subd, sky_maxs_subd, ( stage == 0 ) );
  515. }
  516. }
  517. /*
  518. ** R_BuildCloudData
  519. */
  520. void R_BuildCloudData( shaderCommands_t *input )
  521. {
  522. int i;
  523. shader_t *shader;
  524. shader = input->shader;
  525. assert( shader->isSky );
  526. sky_min = 1.0 / 256.0f; // FIXME: not correct?
  527. sky_max = 255.0 / 256.0f;
  528. // set up for drawing
  529. tess.numIndexes = 0;
  530. tess.numVertexes = 0;
  531. if ( input->shader->sky.cloudHeight )
  532. {
  533. for ( i = 0; i < MAX_SHADER_STAGES; i++ )
  534. {
  535. if ( !tess.xstages[i] ) {
  536. break;
  537. }
  538. FillCloudBox( input->shader, i );
  539. }
  540. }
  541. }
  542. /*
  543. ** R_InitSkyTexCoords
  544. ** Called when a sky shader is parsed
  545. */
  546. #define SQR( a ) ((a)*(a))
  547. void R_InitSkyTexCoords( float heightCloud )
  548. {
  549. int i, s, t;
  550. float radiusWorld = 4096;
  551. float p;
  552. float sRad, tRad;
  553. vec3_t skyVec;
  554. vec3_t v;
  555. // init zfar so MakeSkyVec works even though
  556. // a world hasn't been bounded
  557. backEnd.viewParms.zFar = 1024;
  558. for ( i = 0; i < 6; i++ )
  559. {
  560. for ( t = 0; t <= SKY_SUBDIVISIONS; t++ )
  561. {
  562. for ( s = 0; s <= SKY_SUBDIVISIONS; s++ )
  563. {
  564. // compute vector from view origin to sky side integral point
  565. MakeSkyVec( ( s - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS,
  566. ( t - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS,
  567. i,
  568. NULL,
  569. skyVec );
  570. // compute parametric value 'p' that intersects with cloud layer
  571. p = ( 1.0f / ( 2 * DotProduct( skyVec, skyVec ) ) ) *
  572. ( -2 * skyVec[2] * radiusWorld +
  573. 2 * sqrt( SQR( skyVec[2] ) * SQR( radiusWorld ) +
  574. 2 * SQR( skyVec[0] ) * radiusWorld * heightCloud +
  575. SQR( skyVec[0] ) * SQR( heightCloud ) +
  576. 2 * SQR( skyVec[1] ) * radiusWorld * heightCloud +
  577. SQR( skyVec[1] ) * SQR( heightCloud ) +
  578. 2 * SQR( skyVec[2] ) * radiusWorld * heightCloud +
  579. SQR( skyVec[2] ) * SQR( heightCloud ) ) );
  580. s_cloudTexP[i][t][s] = p;
  581. // compute intersection point based on p
  582. VectorScale( skyVec, p, v );
  583. v[2] += radiusWorld;
  584. // compute vector from world origin to intersection point 'v'
  585. VectorNormalize( v );
  586. sRad = Q_acos( v[0] );
  587. tRad = Q_acos( v[1] );
  588. s_cloudTexCoords[i][t][s][0] = sRad;
  589. s_cloudTexCoords[i][t][s][1] = tRad;
  590. }
  591. }
  592. }
  593. }
  594. //======================================================================================
  595. /*
  596. ** RB_DrawSun
  597. */
  598. void RB_DrawSun( void ) {
  599. float size;
  600. float dist;
  601. vec3_t origin, vec1, vec2;
  602. vec3_t temp;
  603. if ( !backEnd.skyRenderedThisView ) {
  604. return;
  605. }
  606. if ( !r_drawSun->integer ) {
  607. return;
  608. }
  609. qglLoadMatrixf( backEnd.viewParms.world.modelMatrix );
  610. qglTranslatef (backEnd.viewParms.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2]);
  611. dist = backEnd.viewParms.zFar / 1.75; // div sqrt(3)
  612. size = dist * 0.4;
  613. VectorScale( tr.sunDirection, dist, origin );
  614. PerpendicularVector( vec1, tr.sunDirection );
  615. CrossProduct( tr.sunDirection, vec1, vec2 );
  616. VectorScale( vec1, size, vec1 );
  617. VectorScale( vec2, size, vec2 );
  618. // farthest depth range
  619. qglDepthRange( 1.0, 1.0 );
  620. // FIXME: use quad stamp
  621. RB_BeginSurface( tr.sunShader, tess.fogNum );
  622. VectorCopy( origin, temp );
  623. VectorSubtract( temp, vec1, temp );
  624. VectorSubtract( temp, vec2, temp );
  625. VectorCopy( temp, tess.xyz[tess.numVertexes] );
  626. tess.texCoords[tess.numVertexes][0][0] = 0;
  627. tess.texCoords[tess.numVertexes][0][1] = 0;
  628. tess.vertexColors[tess.numVertexes][0] = 255;
  629. tess.vertexColors[tess.numVertexes][1] = 255;
  630. tess.vertexColors[tess.numVertexes][2] = 255;
  631. tess.numVertexes++;
  632. VectorCopy( origin, temp );
  633. VectorAdd( temp, vec1, temp );
  634. VectorSubtract( temp, vec2, temp );
  635. VectorCopy( temp, tess.xyz[tess.numVertexes] );
  636. tess.texCoords[tess.numVertexes][0][0] = 0;
  637. tess.texCoords[tess.numVertexes][0][1] = 1;
  638. tess.vertexColors[tess.numVertexes][0] = 255;
  639. tess.vertexColors[tess.numVertexes][1] = 255;
  640. tess.vertexColors[tess.numVertexes][2] = 255;
  641. tess.numVertexes++;
  642. VectorCopy( origin, temp );
  643. VectorAdd( temp, vec1, temp );
  644. VectorAdd( temp, vec2, temp );
  645. VectorCopy( temp, tess.xyz[tess.numVertexes] );
  646. tess.texCoords[tess.numVertexes][0][0] = 1;
  647. tess.texCoords[tess.numVertexes][0][1] = 1;
  648. tess.vertexColors[tess.numVertexes][0] = 255;
  649. tess.vertexColors[tess.numVertexes][1] = 255;
  650. tess.vertexColors[tess.numVertexes][2] = 255;
  651. tess.numVertexes++;
  652. VectorCopy( origin, temp );
  653. VectorSubtract( temp, vec1, temp );
  654. VectorAdd( temp, vec2, temp );
  655. VectorCopy( temp, tess.xyz[tess.numVertexes] );
  656. tess.texCoords[tess.numVertexes][0][0] = 1;
  657. tess.texCoords[tess.numVertexes][0][1] = 0;
  658. tess.vertexColors[tess.numVertexes][0] = 255;
  659. tess.vertexColors[tess.numVertexes][1] = 255;
  660. tess.vertexColors[tess.numVertexes][2] = 255;
  661. tess.numVertexes++;
  662. tess.indexes[tess.numIndexes++] = 0;
  663. tess.indexes[tess.numIndexes++] = 1;
  664. tess.indexes[tess.numIndexes++] = 2;
  665. tess.indexes[tess.numIndexes++] = 0;
  666. tess.indexes[tess.numIndexes++] = 2;
  667. tess.indexes[tess.numIndexes++] = 3;
  668. RB_EndSurface();
  669. // back to normal depth range
  670. qglDepthRange( 0.0, 1.0 );
  671. }
  672. /*
  673. ================
  674. RB_StageIteratorSky
  675. All of the visible sky triangles are in tess
  676. Other things could be stuck in here, like birds in the sky, etc
  677. ================
  678. */
  679. void RB_StageIteratorSky( void ) {
  680. if ( r_fastsky->integer ) {
  681. return;
  682. }
  683. // go through all the polygons and project them onto
  684. // the sky box to see which blocks on each side need
  685. // to be drawn
  686. RB_ClipSkyPolygons( &tess );
  687. // r_showsky will let all the sky blocks be drawn in
  688. // front of everything to allow developers to see how
  689. // much sky is getting sucked in
  690. if ( r_showsky->integer ) {
  691. qglDepthRange( 0.0, 0.0 );
  692. } else {
  693. qglDepthRange( 1.0, 1.0 );
  694. }
  695. // draw the outer skybox
  696. if ( tess.shader->sky.outerbox[0] && tess.shader->sky.outerbox[0] != tr.defaultImage ) {
  697. qglColor3f( tr.identityLight, tr.identityLight, tr.identityLight );
  698. qglPushMatrix ();
  699. GL_State( 0 );
  700. qglTranslatef (backEnd.viewParms.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2]);
  701. DrawSkyBox( tess.shader );
  702. qglPopMatrix();
  703. }
  704. // generate the vertexes for all the clouds, which will be drawn
  705. // by the generic shader routine
  706. R_BuildCloudData( &tess );
  707. RB_StageIteratorGeneric();
  708. // draw the inner skybox
  709. // back to normal depth range
  710. qglDepthRange( 0.0, 1.0 );
  711. // note that sky was drawn so we will draw a sun later
  712. backEnd.skyRenderedThisView = qtrue;
  713. }