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