1 /*
2 ===========================================================================
3 Copyright (C) 1999-2005 Id Software, Inc.
4 
5 This file is part of Quake III Arena source code.
6 
7 Quake III Arena source code is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
11 
12 Quake III Arena source code is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Quake III Arena source code; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 ===========================================================================
21 */
22 // tr_shade_calc.c
23 
24 #include "tr_local.h"
25 #if idppc_altivec && !defined(MACOS_X)
26 #include <altivec.h>
27 #endif
28 
29 
30 #define	WAVEVALUE( table, base, amplitude, phase, freq )  ((base) + table[ myftol( ( ( (phase) + tess.shaderTime * (freq) ) * FUNCTABLE_SIZE ) ) & FUNCTABLE_MASK ] * (amplitude))
31 
TableForFunc(genFunc_t func)32 static float *TableForFunc( genFunc_t func )
33 {
34 	switch ( func )
35 	{
36 	case GF_SIN:
37 		return tr.sinTable;
38 	case GF_TRIANGLE:
39 		return tr.triangleTable;
40 	case GF_SQUARE:
41 		return tr.squareTable;
42 	case GF_SAWTOOTH:
43 		return tr.sawToothTable;
44 	case GF_INVERSE_SAWTOOTH:
45 		return tr.inverseSawToothTable;
46 	case GF_NONE:
47 	default:
48 		break;
49 	}
50 
51 	ri.Error( ERR_DROP, "TableForFunc called with invalid function '%d' in shader '%s'\n", func, tess.shader->name );
52 	return NULL;
53 }
54 
55 /*
56 ** EvalWaveForm
57 **
58 ** Evaluates a given waveForm_t, referencing backEnd.refdef.time directly
59 */
EvalWaveForm(const waveForm_t * wf)60 static float EvalWaveForm( const waveForm_t *wf )
61 {
62 	float	*table;
63 
64 	table = TableForFunc( wf->func );
65 
66 	return WAVEVALUE( table, wf->base, wf->amplitude, wf->phase, wf->frequency );
67 }
68 
EvalWaveFormClamped(const waveForm_t * wf)69 static float EvalWaveFormClamped( const waveForm_t *wf )
70 {
71 	float glow  = EvalWaveForm( wf );
72 
73 	if ( glow < 0 )
74 	{
75 		return 0;
76 	}
77 
78 	if ( glow > 1 )
79 	{
80 		return 1;
81 	}
82 
83 	return glow;
84 }
85 
86 /*
87 ** RB_CalcStretchTexCoords
88 */
RB_CalcStretchTexCoords(const waveForm_t * wf,float * st)89 void RB_CalcStretchTexCoords( const waveForm_t *wf, float *st )
90 {
91 	float p;
92 	texModInfo_t tmi;
93 
94 	p = 1.0f / EvalWaveForm( wf );
95 
96 	tmi.matrix[0][0] = p;
97 	tmi.matrix[1][0] = 0;
98 	tmi.translate[0] = 0.5f - 0.5f * p;
99 
100 	tmi.matrix[0][1] = 0;
101 	tmi.matrix[1][1] = p;
102 	tmi.translate[1] = 0.5f - 0.5f * p;
103 
104 	RB_CalcTransformTexCoords( &tmi, st );
105 }
106 
107 /*
108 ====================================================================
109 
110 DEFORMATIONS
111 
112 ====================================================================
113 */
114 
115 /*
116 ========================
117 RB_CalcDeformVertexes
118 
119 ========================
120 */
RB_CalcDeformVertexes(deformStage_t * ds)121 void RB_CalcDeformVertexes( deformStage_t *ds )
122 {
123 	int i;
124 	vec3_t	offset;
125 	float	scale;
126 	float	*xyz = ( float * ) tess.xyz;
127 	float	*normal = ( float * ) tess.normal;
128 	float	*table;
129 
130 	if ( ds->deformationWave.frequency == 0 )
131 	{
132 		scale = EvalWaveForm( &ds->deformationWave );
133 
134 		for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal += 4 )
135 		{
136 			VectorScale( normal, scale, offset );
137 
138 			xyz[0] += offset[0];
139 			xyz[1] += offset[1];
140 			xyz[2] += offset[2];
141 		}
142 	}
143 	else
144 	{
145 		table = TableForFunc( ds->deformationWave.func );
146 
147 		for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal += 4 )
148 		{
149 			float off = ( xyz[0] + xyz[1] + xyz[2] ) * ds->deformationSpread;
150 
151 			scale = WAVEVALUE( table, ds->deformationWave.base,
152 				ds->deformationWave.amplitude,
153 				ds->deformationWave.phase + off,
154 				ds->deformationWave.frequency );
155 
156 			VectorScale( normal, scale, offset );
157 
158 			xyz[0] += offset[0];
159 			xyz[1] += offset[1];
160 			xyz[2] += offset[2];
161 		}
162 	}
163 }
164 
165 /*
166 =========================
167 RB_CalcDeformNormals
168 
169 Wiggle the normals for wavy environment mapping
170 =========================
171 */
RB_CalcDeformNormals(deformStage_t * ds)172 void RB_CalcDeformNormals( deformStage_t *ds ) {
173 	int i;
174 	float	scale;
175 	float	*xyz = ( float * ) tess.xyz;
176 	float	*normal = ( float * ) tess.normal;
177 
178 	for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal += 4 ) {
179 		scale = 0.98f;
180 		scale = R_NoiseGet4f( xyz[0] * scale, xyz[1] * scale, xyz[2] * scale,
181 			tess.shaderTime * ds->deformationWave.frequency );
182 		normal[ 0 ] += ds->deformationWave.amplitude * scale;
183 
184 		scale = 0.98f;
185 		scale = R_NoiseGet4f( 100 + xyz[0] * scale, xyz[1] * scale, xyz[2] * scale,
186 			tess.shaderTime * ds->deformationWave.frequency );
187 		normal[ 1 ] += ds->deformationWave.amplitude * scale;
188 
189 		scale = 0.98f;
190 		scale = R_NoiseGet4f( 200 + xyz[0] * scale, xyz[1] * scale, xyz[2] * scale,
191 			tess.shaderTime * ds->deformationWave.frequency );
192 		normal[ 2 ] += ds->deformationWave.amplitude * scale;
193 
194 		VectorNormalizeFast( normal );
195 	}
196 }
197 
198 /*
199 ========================
200 RB_CalcBulgeVertexes
201 
202 ========================
203 */
RB_CalcBulgeVertexes(deformStage_t * ds)204 void RB_CalcBulgeVertexes( deformStage_t *ds ) {
205 	int i;
206 	const float *st = ( const float * ) tess.texCoords[0];
207 	float		*xyz = ( float * ) tess.xyz;
208 	float		*normal = ( float * ) tess.normal;
209 	float		now;
210 
211 	now = backEnd.refdef.time * ds->bulgeSpeed * 0.001f;
212 
213 	for ( i = 0; i < tess.numVertexes; i++, xyz += 4, st += 4, normal += 4 ) {
214 		int		off;
215 		float scale;
216 
217 		off = (float)( FUNCTABLE_SIZE / (M_PI*2) ) * ( st[0] * ds->bulgeWidth + now );
218 
219 		scale = tr.sinTable[ off & FUNCTABLE_MASK ] * ds->bulgeHeight;
220 
221 		xyz[0] += normal[0] * scale;
222 		xyz[1] += normal[1] * scale;
223 		xyz[2] += normal[2] * scale;
224 	}
225 }
226 
227 
228 /*
229 ======================
230 RB_CalcMoveVertexes
231 
232 A deformation that can move an entire surface along a wave path
233 ======================
234 */
RB_CalcMoveVertexes(deformStage_t * ds)235 void RB_CalcMoveVertexes( deformStage_t *ds ) {
236 	int			i;
237 	float		*xyz;
238 	float		*table;
239 	float		scale;
240 	vec3_t		offset;
241 
242 	table = TableForFunc( ds->deformationWave.func );
243 
244 	scale = WAVEVALUE( table, ds->deformationWave.base,
245 		ds->deformationWave.amplitude,
246 		ds->deformationWave.phase,
247 		ds->deformationWave.frequency );
248 
249 	VectorScale( ds->moveVector, scale, offset );
250 
251 	xyz = ( float * ) tess.xyz;
252 	for ( i = 0; i < tess.numVertexes; i++, xyz += 4 ) {
253 		VectorAdd( xyz, offset, xyz );
254 	}
255 }
256 
257 
258 /*
259 =============
260 DeformText
261 
262 Change a polygon into a bunch of text polygons
263 =============
264 */
DeformText(const char * text)265 void DeformText( const char *text ) {
266 	int		i;
267 	vec3_t	origin, width, height;
268 	int		len;
269 	int		ch;
270 	byte	color[4];
271 	float	bottom, top;
272 	vec3_t	mid;
273 
274 	height[0] = 0;
275 	height[1] = 0;
276 	height[2] = -1;
277 	CrossProduct( tess.normal[0], height, width );
278 
279 	// find the midpoint of the box
280 	VectorClear( mid );
281 	bottom = 999999;
282 	top = -999999;
283 	for ( i = 0 ; i < 4 ; i++ ) {
284 		VectorAdd( tess.xyz[i], mid, mid );
285 		if ( tess.xyz[i][2] < bottom ) {
286 			bottom = tess.xyz[i][2];
287 		}
288 		if ( tess.xyz[i][2] > top ) {
289 			top = tess.xyz[i][2];
290 		}
291 	}
292 	VectorScale( mid, 0.25f, origin );
293 
294 	// determine the individual character size
295 	height[0] = 0;
296 	height[1] = 0;
297 	height[2] = ( top - bottom ) * 0.5f;
298 
299 	VectorScale( width, height[2] * -0.75f, width );
300 
301 	// determine the starting position
302 	len = strlen( text );
303 	VectorMA( origin, (len-1), width, origin );
304 
305 	// clear the shader indexes
306 	tess.numIndexes = 0;
307 	tess.numVertexes = 0;
308 
309 	color[0] = color[1] = color[2] = color[3] = 255;
310 
311 	// draw each character
312 	for ( i = 0 ; i < len ; i++ ) {
313 		ch = text[i];
314 		ch &= 255;
315 
316 		if ( ch != ' ' ) {
317 			int		row, col;
318 			float	frow, fcol, size;
319 
320 			row = ch>>4;
321 			col = ch&15;
322 
323 			frow = row*0.0625f;
324 			fcol = col*0.0625f;
325 			size = 0.0625f;
326 
327 			RB_AddQuadStampExt( origin, width, height, color, fcol, frow, fcol + size, frow + size );
328 		}
329 		VectorMA( origin, -2, width, origin );
330 	}
331 }
332 
333 /*
334 ==================
335 GlobalVectorToLocal
336 ==================
337 */
GlobalVectorToLocal(const vec3_t in,vec3_t out)338 static void GlobalVectorToLocal( const vec3_t in, vec3_t out ) {
339 	out[0] = DotProduct( in, backEnd.or.axis[0] );
340 	out[1] = DotProduct( in, backEnd.or.axis[1] );
341 	out[2] = DotProduct( in, backEnd.or.axis[2] );
342 }
343 
344 /*
345 =====================
346 AutospriteDeform
347 
348 Assuming all the triangles for this shader are independant
349 quads, rebuild them as forward facing sprites
350 =====================
351 */
AutospriteDeform(void)352 static void AutospriteDeform( void ) {
353 	int		i;
354 	int		oldVerts;
355 	float	*xyz;
356 	vec3_t	mid, delta;
357 	float	radius;
358 	vec3_t	left, up;
359 	vec3_t	leftDir, upDir;
360 
361 	if ( tess.numVertexes & 3 ) {
362 		ri.Printf( PRINT_WARNING, "Autosprite shader %s had odd vertex count", tess.shader->name );
363 	}
364 	if ( tess.numIndexes != ( tess.numVertexes >> 2 ) * 6 ) {
365 		ri.Printf( PRINT_WARNING, "Autosprite shader %s had odd index count", tess.shader->name );
366 	}
367 
368 	oldVerts = tess.numVertexes;
369 	tess.numVertexes = 0;
370 	tess.numIndexes = 0;
371 
372 	if ( backEnd.currentEntity != &tr.worldEntity ) {
373 		GlobalVectorToLocal( backEnd.viewParms.or.axis[1], leftDir );
374 		GlobalVectorToLocal( backEnd.viewParms.or.axis[2], upDir );
375 	} else {
376 		VectorCopy( backEnd.viewParms.or.axis[1], leftDir );
377 		VectorCopy( backEnd.viewParms.or.axis[2], upDir );
378 	}
379 
380 	for ( i = 0 ; i < oldVerts ; i+=4 ) {
381 		// find the midpoint
382 		xyz = tess.xyz[i];
383 
384 		mid[0] = 0.25f * (xyz[0] + xyz[4] + xyz[8] + xyz[12]);
385 		mid[1] = 0.25f * (xyz[1] + xyz[5] + xyz[9] + xyz[13]);
386 		mid[2] = 0.25f * (xyz[2] + xyz[6] + xyz[10] + xyz[14]);
387 
388 		VectorSubtract( xyz, mid, delta );
389 		radius = VectorLength( delta ) * 0.707f;		// / sqrt(2)
390 
391 		VectorScale( leftDir, radius, left );
392 		VectorScale( upDir, radius, up );
393 
394 		if ( backEnd.viewParms.isMirror ) {
395 			VectorSubtract( vec3_origin, left, left );
396 		}
397 
398 	  // compensate for scale in the axes if necessary
399   	if ( backEnd.currentEntity->e.nonNormalizedAxes ) {
400       float axisLength;
401 		  axisLength = VectorLength( backEnd.currentEntity->e.axis[0] );
402   		if ( !axisLength ) {
403 	  		axisLength = 0;
404   		} else {
405 	  		axisLength = 1.0f / axisLength;
406   		}
407       VectorScale(left, axisLength, left);
408       VectorScale(up, axisLength, up);
409     }
410 
411 		RB_AddQuadStamp( mid, left, up, tess.vertexColors[i] );
412 	}
413 }
414 
415 
416 /*
417 =====================
418 Autosprite2Deform
419 
420 Autosprite2 will pivot a rectangular quad along the center of its long axis
421 =====================
422 */
423 int edgeVerts[6][2] = {
424 	{ 0, 1 },
425 	{ 0, 2 },
426 	{ 0, 3 },
427 	{ 1, 2 },
428 	{ 1, 3 },
429 	{ 2, 3 }
430 };
431 
Autosprite2Deform(void)432 static void Autosprite2Deform( void ) {
433 	int		i, j, k;
434 	int		indexes;
435 	float	*xyz;
436 	vec3_t	forward;
437 
438 	if ( tess.numVertexes & 3 ) {
439 		ri.Printf( PRINT_WARNING, "Autosprite2 shader %s had odd vertex count", tess.shader->name );
440 	}
441 	if ( tess.numIndexes != ( tess.numVertexes >> 2 ) * 6 ) {
442 		ri.Printf( PRINT_WARNING, "Autosprite2 shader %s had odd index count", tess.shader->name );
443 	}
444 
445 	if ( backEnd.currentEntity != &tr.worldEntity ) {
446 		GlobalVectorToLocal( backEnd.viewParms.or.axis[0], forward );
447 	} else {
448 		VectorCopy( backEnd.viewParms.or.axis[0], forward );
449 	}
450 
451 	// this is a lot of work for two triangles...
452 	// we could precalculate a lot of it is an issue, but it would mess up
453 	// the shader abstraction
454 	for ( i = 0, indexes = 0 ; i < tess.numVertexes ; i+=4, indexes+=6 ) {
455 		float	lengths[2];
456 		int		nums[2];
457 		vec3_t	mid[2];
458 		vec3_t	major, minor;
459 		float	*v1, *v2;
460 
461 		// find the midpoint
462 		xyz = tess.xyz[i];
463 
464 		// identify the two shortest edges
465 		nums[0] = nums[1] = 0;
466 		lengths[0] = lengths[1] = 999999;
467 
468 		for ( j = 0 ; j < 6 ; j++ ) {
469 			float	l;
470 			vec3_t	temp;
471 
472 			v1 = xyz + 4 * edgeVerts[j][0];
473 			v2 = xyz + 4 * edgeVerts[j][1];
474 
475 			VectorSubtract( v1, v2, temp );
476 
477 			l = DotProduct( temp, temp );
478 			if ( l < lengths[0] ) {
479 				nums[1] = nums[0];
480 				lengths[1] = lengths[0];
481 				nums[0] = j;
482 				lengths[0] = l;
483 			} else if ( l < lengths[1] ) {
484 				nums[1] = j;
485 				lengths[1] = l;
486 			}
487 		}
488 
489 		for ( j = 0 ; j < 2 ; j++ ) {
490 			v1 = xyz + 4 * edgeVerts[nums[j]][0];
491 			v2 = xyz + 4 * edgeVerts[nums[j]][1];
492 
493 			mid[j][0] = 0.5f * (v1[0] + v2[0]);
494 			mid[j][1] = 0.5f * (v1[1] + v2[1]);
495 			mid[j][2] = 0.5f * (v1[2] + v2[2]);
496 		}
497 
498 		// find the vector of the major axis
499 		VectorSubtract( mid[1], mid[0], major );
500 
501 		// cross this with the view direction to get minor axis
502 		CrossProduct( major, forward, minor );
503 		VectorNormalize( minor );
504 
505 		// re-project the points
506 		for ( j = 0 ; j < 2 ; j++ ) {
507 			float	l;
508 
509 			v1 = xyz + 4 * edgeVerts[nums[j]][0];
510 			v2 = xyz + 4 * edgeVerts[nums[j]][1];
511 
512 			l = 0.5 * sqrt( lengths[j] );
513 
514 			// we need to see which direction this edge
515 			// is used to determine direction of projection
516 			for ( k = 0 ; k < 5 ; k++ ) {
517 				if ( tess.indexes[ indexes + k ] == i + edgeVerts[nums[j]][0]
518 					&& tess.indexes[ indexes + k + 1 ] == i + edgeVerts[nums[j]][1] ) {
519 					break;
520 				}
521 			}
522 
523 			if ( k == 5 ) {
524 				VectorMA( mid[j], l, minor, v1 );
525 				VectorMA( mid[j], -l, minor, v2 );
526 			} else {
527 				VectorMA( mid[j], -l, minor, v1 );
528 				VectorMA( mid[j], l, minor, v2 );
529 			}
530 		}
531 	}
532 }
533 
534 
535 /*
536 =====================
537 RB_DeformTessGeometry
538 
539 =====================
540 */
RB_DeformTessGeometry(void)541 void RB_DeformTessGeometry( void ) {
542 	int		i;
543 	deformStage_t	*ds;
544 
545 	for ( i = 0 ; i < tess.shader->numDeforms ; i++ ) {
546 		ds = &tess.shader->deforms[ i ];
547 
548 		switch ( ds->deformation ) {
549         case DEFORM_NONE:
550             break;
551 		case DEFORM_NORMALS:
552 			RB_CalcDeformNormals( ds );
553 			break;
554 		case DEFORM_WAVE:
555 			RB_CalcDeformVertexes( ds );
556 			break;
557 		case DEFORM_BULGE:
558 			RB_CalcBulgeVertexes( ds );
559 			break;
560 		case DEFORM_MOVE:
561 			RB_CalcMoveVertexes( ds );
562 			break;
563 		case DEFORM_PROJECTION_SHADOW:
564 			RB_ProjectionShadowDeform();
565 			break;
566 		case DEFORM_AUTOSPRITE:
567 			AutospriteDeform();
568 			break;
569 		case DEFORM_AUTOSPRITE2:
570 			Autosprite2Deform();
571 			break;
572 		case DEFORM_TEXT0:
573 		case DEFORM_TEXT1:
574 		case DEFORM_TEXT2:
575 		case DEFORM_TEXT3:
576 		case DEFORM_TEXT4:
577 		case DEFORM_TEXT5:
578 		case DEFORM_TEXT6:
579 		case DEFORM_TEXT7:
580 			DeformText( backEnd.refdef.text[ds->deformation - DEFORM_TEXT0] );
581 			break;
582 		}
583 	}
584 }
585 
586 /*
587 ====================================================================
588 
589 COLORS
590 
591 ====================================================================
592 */
593 
594 
595 /*
596 ** RB_CalcColorFromEntity
597 */
RB_CalcColorFromEntity(unsigned char * dstColors)598 void RB_CalcColorFromEntity( unsigned char *dstColors )
599 {
600 	int	i;
601 	int *pColors = ( int * ) dstColors;
602 	int c;
603 
604 	if ( !backEnd.currentEntity )
605 		return;
606 
607 	c = * ( int * ) backEnd.currentEntity->e.shaderRGBA;
608 
609 	for ( i = 0; i < tess.numVertexes; i++, pColors++ )
610 	{
611 		*pColors = c;
612 	}
613 }
614 
615 /*
616 ** RB_CalcColorFromOneMinusEntity
617 */
RB_CalcColorFromOneMinusEntity(unsigned char * dstColors)618 void RB_CalcColorFromOneMinusEntity( unsigned char *dstColors )
619 {
620 	int	i;
621 	int *pColors = ( int * ) dstColors;
622 	unsigned char invModulate[4];
623 	int c;
624 
625 	if ( !backEnd.currentEntity )
626 		return;
627 
628 	invModulate[0] = 255 - backEnd.currentEntity->e.shaderRGBA[0];
629 	invModulate[1] = 255 - backEnd.currentEntity->e.shaderRGBA[1];
630 	invModulate[2] = 255 - backEnd.currentEntity->e.shaderRGBA[2];
631 	invModulate[3] = 255 - backEnd.currentEntity->e.shaderRGBA[3];	// this trashes alpha, but the AGEN block fixes it
632 
633 	c = * ( int * ) invModulate;
634 
635 	for ( i = 0; i < tess.numVertexes; i++, pColors++ )
636 	{
637 		*pColors = * ( int * ) invModulate;
638 	}
639 }
640 
641 /*
642 ** RB_CalcAlphaFromEntity
643 */
RB_CalcAlphaFromEntity(unsigned char * dstColors)644 void RB_CalcAlphaFromEntity( unsigned char *dstColors )
645 {
646 	int	i;
647 
648 	if ( !backEnd.currentEntity )
649 		return;
650 
651 	dstColors += 3;
652 
653 	for ( i = 0; i < tess.numVertexes; i++, dstColors += 4 )
654 	{
655 		*dstColors = backEnd.currentEntity->e.shaderRGBA[3];
656 	}
657 }
658 
659 /*
660 ** RB_CalcAlphaFromOneMinusEntity
661 */
RB_CalcAlphaFromOneMinusEntity(unsigned char * dstColors)662 void RB_CalcAlphaFromOneMinusEntity( unsigned char *dstColors )
663 {
664 	int	i;
665 
666 	if ( !backEnd.currentEntity )
667 		return;
668 
669 	dstColors += 3;
670 
671 	for ( i = 0; i < tess.numVertexes; i++, dstColors += 4 )
672 	{
673 		*dstColors = 0xff - backEnd.currentEntity->e.shaderRGBA[3];
674 	}
675 }
676 
677 /*
678 ** RB_CalcWaveColor
679 */
RB_CalcWaveColor(const waveForm_t * wf,unsigned char * dstColors)680 void RB_CalcWaveColor( const waveForm_t *wf, unsigned char *dstColors )
681 {
682 	int i;
683 	int v;
684 	float glow;
685 	int *colors = ( int * ) dstColors;
686 	byte	color[4];
687 
688 
689   if ( wf->func == GF_NOISE ) {
690 		glow = wf->base + R_NoiseGet4f( 0, 0, 0, ( tess.shaderTime + wf->phase ) * wf->frequency ) * wf->amplitude;
691 	} else {
692 		glow = EvalWaveForm( wf ) * tr.identityLight;
693 	}
694 
695 	if ( glow < 0 ) {
696 		glow = 0;
697 	}
698 	else if ( glow > 1 ) {
699 		glow = 1;
700 	}
701 
702 	v = myftol( 255 * glow );
703 	color[0] = color[1] = color[2] = v;
704 	color[3] = 255;
705 	v = *(int *)color;
706 
707 	for ( i = 0; i < tess.numVertexes; i++, colors++ ) {
708 		*colors = v;
709 	}
710 }
711 
712 /*
713 ** RB_CalcWaveAlpha
714 */
RB_CalcWaveAlpha(const waveForm_t * wf,unsigned char * dstColors)715 void RB_CalcWaveAlpha( const waveForm_t *wf, unsigned char *dstColors )
716 {
717 	int i;
718 	int v;
719 	float glow;
720 
721 	glow = EvalWaveFormClamped( wf );
722 
723 	v = 255 * glow;
724 
725 	for ( i = 0; i < tess.numVertexes; i++, dstColors += 4 )
726 	{
727 		dstColors[3] = v;
728 	}
729 }
730 
731 /*
732 ** RB_CalcModulateColorsByFog
733 */
RB_CalcModulateColorsByFog(unsigned char * colors)734 void RB_CalcModulateColorsByFog( unsigned char *colors ) {
735 	int		i;
736 	float	texCoords[SHADER_MAX_VERTEXES][2];
737 
738 	// calculate texcoords so we can derive density
739 	// this is not wasted, because it would only have
740 	// been previously called if the surface was opaque
741 	RB_CalcFogTexCoords( texCoords[0] );
742 
743 	for ( i = 0; i < tess.numVertexes; i++, colors += 4 ) {
744 		float f = 1.0 - R_FogFactor( texCoords[i][0], texCoords[i][1] );
745 		colors[0] *= f;
746 		colors[1] *= f;
747 		colors[2] *= f;
748 	}
749 }
750 
751 /*
752 ** RB_CalcModulateAlphasByFog
753 */
RB_CalcModulateAlphasByFog(unsigned char * colors)754 void RB_CalcModulateAlphasByFog( unsigned char *colors ) {
755 	int		i;
756 	float	texCoords[SHADER_MAX_VERTEXES][2];
757 
758 	// calculate texcoords so we can derive density
759 	// this is not wasted, because it would only have
760 	// been previously called if the surface was opaque
761 	RB_CalcFogTexCoords( texCoords[0] );
762 
763 	for ( i = 0; i < tess.numVertexes; i++, colors += 4 ) {
764 		float f = 1.0 - R_FogFactor( texCoords[i][0], texCoords[i][1] );
765 		colors[3] *= f;
766 	}
767 }
768 
769 /*
770 ** RB_CalcModulateRGBAsByFog
771 */
RB_CalcModulateRGBAsByFog(unsigned char * colors)772 void RB_CalcModulateRGBAsByFog( unsigned char *colors ) {
773 	int		i;
774 	float	texCoords[SHADER_MAX_VERTEXES][2];
775 
776 	// calculate texcoords so we can derive density
777 	// this is not wasted, because it would only have
778 	// been previously called if the surface was opaque
779 	RB_CalcFogTexCoords( texCoords[0] );
780 
781 	for ( i = 0; i < tess.numVertexes; i++, colors += 4 ) {
782 		float f = 1.0 - R_FogFactor( texCoords[i][0], texCoords[i][1] );
783 		colors[0] *= f;
784 		colors[1] *= f;
785 		colors[2] *= f;
786 		colors[3] *= f;
787 	}
788 }
789 
790 
791 /*
792 ====================================================================
793 
794 TEX COORDS
795 
796 ====================================================================
797 */
798 
799 /*
800 ========================
801 RB_CalcFogTexCoords
802 
803 To do the clipped fog plane really correctly, we should use
804 projected textures, but I don't trust the drivers and it
805 doesn't fit our shader data.
806 ========================
807 */
RB_CalcFogTexCoords(float * st)808 void RB_CalcFogTexCoords( float *st ) {
809 	int			i;
810 	float		*v;
811 	float		s, t;
812 	float		eyeT;
813 	qboolean	eyeOutside;
814 	fog_t		*fog;
815 	vec3_t		local;
816 	vec4_t		fogDistanceVector, fogDepthVector = {0, 0, 0, 0};
817 
818 	fog = tr.world->fogs + tess.fogNum;
819 
820 	// all fogging distance is based on world Z units
821 	VectorSubtract( backEnd.or.origin, backEnd.viewParms.or.origin, local );
822 	fogDistanceVector[0] = -backEnd.or.modelMatrix[2];
823 	fogDistanceVector[1] = -backEnd.or.modelMatrix[6];
824 	fogDistanceVector[2] = -backEnd.or.modelMatrix[10];
825 	fogDistanceVector[3] = DotProduct( local, backEnd.viewParms.or.axis[0] );
826 
827 	// scale the fog vectors based on the fog's thickness
828 	fogDistanceVector[0] *= fog->tcScale;
829 	fogDistanceVector[1] *= fog->tcScale;
830 	fogDistanceVector[2] *= fog->tcScale;
831 	fogDistanceVector[3] *= fog->tcScale;
832 
833 	// rotate the gradient vector for this orientation
834 	if ( fog->hasSurface ) {
835 		fogDepthVector[0] = fog->surface[0] * backEnd.or.axis[0][0] +
836 			fog->surface[1] * backEnd.or.axis[0][1] + fog->surface[2] * backEnd.or.axis[0][2];
837 		fogDepthVector[1] = fog->surface[0] * backEnd.or.axis[1][0] +
838 			fog->surface[1] * backEnd.or.axis[1][1] + fog->surface[2] * backEnd.or.axis[1][2];
839 		fogDepthVector[2] = fog->surface[0] * backEnd.or.axis[2][0] +
840 			fog->surface[1] * backEnd.or.axis[2][1] + fog->surface[2] * backEnd.or.axis[2][2];
841 		fogDepthVector[3] = -fog->surface[3] + DotProduct( backEnd.or.origin, fog->surface );
842 
843 		eyeT = DotProduct( backEnd.or.viewOrigin, fogDepthVector ) + fogDepthVector[3];
844 	} else {
845 		eyeT = 1;	// non-surface fog always has eye inside
846 	}
847 
848 	// see if the viewpoint is outside
849 	// this is needed for clipping distance even for constant fog
850 
851 	if ( eyeT < 0 ) {
852 		eyeOutside = qtrue;
853 	} else {
854 		eyeOutside = qfalse;
855 	}
856 
857 	fogDistanceVector[3] += 1.0/512;
858 
859 	// calculate density for each point
860 	for (i = 0, v = tess.xyz[0] ; i < tess.numVertexes ; i++, v += 4) {
861 		// calculate the length in fog
862 		s = DotProduct( v, fogDistanceVector ) + fogDistanceVector[3];
863 		t = DotProduct( v, fogDepthVector ) + fogDepthVector[3];
864 
865 		// partially clipped fogs use the T axis
866 		if ( eyeOutside ) {
867 			if ( t < 1.0 ) {
868 				t = 1.0/32;	// point is outside, so no fogging
869 			} else {
870 				t = 1.0/32 + 30.0/32 * t / ( t - eyeT );	// cut the distance at the fog plane
871 			}
872 		} else {
873 			if ( t < 0 ) {
874 				t = 1.0/32;	// point is outside, so no fogging
875 			} else {
876 				t = 31.0/32;
877 			}
878 		}
879 
880 		st[0] = s;
881 		st[1] = t;
882 		st += 2;
883 	}
884 }
885 
886 
887 
888 /*
889 ** RB_CalcEnvironmentTexCoords
890 */
RB_CalcEnvironmentTexCoords(float * st)891 void RB_CalcEnvironmentTexCoords( float *st )
892 {
893 	int			i;
894 	float		*v, *normal;
895 	vec3_t		viewer, reflected;
896 	float		d;
897 
898 	v = tess.xyz[0];
899 	normal = tess.normal[0];
900 
901 	for (i = 0 ; i < tess.numVertexes ; i++, v += 4, normal += 4, st += 2 )
902 	{
903 		VectorSubtract (backEnd.or.viewOrigin, v, viewer);
904 		VectorNormalizeFast (viewer);
905 
906 		d = DotProduct (normal, viewer);
907 
908 		reflected[0] = normal[0]*2*d - viewer[0];
909 		reflected[1] = normal[1]*2*d - viewer[1];
910 		reflected[2] = normal[2]*2*d - viewer[2];
911 
912 		st[0] = 0.5 + reflected[1] * 0.5;
913 		st[1] = 0.5 - reflected[2] * 0.5;
914 	}
915 }
916 
917 /*
918 ** RB_CalcTurbulentTexCoords
919 */
RB_CalcTurbulentTexCoords(const waveForm_t * wf,float * st)920 void RB_CalcTurbulentTexCoords( const waveForm_t *wf, float *st )
921 {
922 	int i;
923 	float now;
924 
925 	now = ( wf->phase + tess.shaderTime * wf->frequency );
926 
927 	for ( i = 0; i < tess.numVertexes; i++, st += 2 )
928 	{
929 		float s = st[0];
930 		float t = st[1];
931 
932 		st[0] = s + tr.sinTable[ ( ( int ) ( ( ( tess.xyz[i][0] + tess.xyz[i][2] )* 1.0/128 * 0.125 + now ) * FUNCTABLE_SIZE ) ) & ( FUNCTABLE_MASK ) ] * wf->amplitude;
933 		st[1] = t + tr.sinTable[ ( ( int ) ( ( tess.xyz[i][1] * 1.0/128 * 0.125 + now ) * FUNCTABLE_SIZE ) ) & ( FUNCTABLE_MASK ) ] * wf->amplitude;
934 	}
935 }
936 
937 /*
938 ** RB_CalcScaleTexCoords
939 */
RB_CalcScaleTexCoords(const float scale[2],float * st)940 void RB_CalcScaleTexCoords( const float scale[2], float *st )
941 {
942 	int i;
943 
944 	for ( i = 0; i < tess.numVertexes; i++, st += 2 )
945 	{
946 		st[0] *= scale[0];
947 		st[1] *= scale[1];
948 	}
949 }
950 
951 /*
952 ** RB_CalcScrollTexCoords
953 */
RB_CalcScrollTexCoords(const float scrollSpeed[2],float * st)954 void RB_CalcScrollTexCoords( const float scrollSpeed[2], float *st )
955 {
956 	int i;
957 	float timeScale = tess.shaderTime;
958 	float adjustedScrollS, adjustedScrollT;
959 
960 	adjustedScrollS = scrollSpeed[0] * timeScale;
961 	adjustedScrollT = scrollSpeed[1] * timeScale;
962 
963 	// clamp so coordinates don't continuously get larger, causing problems
964 	// with hardware limits
965 	adjustedScrollS = adjustedScrollS - floor( adjustedScrollS );
966 	adjustedScrollT = adjustedScrollT - floor( adjustedScrollT );
967 
968 	for ( i = 0; i < tess.numVertexes; i++, st += 2 )
969 	{
970 		st[0] += adjustedScrollS;
971 		st[1] += adjustedScrollT;
972 	}
973 }
974 
975 /*
976 ** RB_CalcTransformTexCoords
977 */
RB_CalcTransformTexCoords(const texModInfo_t * tmi,float * st)978 void RB_CalcTransformTexCoords( const texModInfo_t *tmi, float *st  )
979 {
980 	int i;
981 
982 	for ( i = 0; i < tess.numVertexes; i++, st += 2 )
983 	{
984 		float s = st[0];
985 		float t = st[1];
986 
987 		st[0] = s * tmi->matrix[0][0] + t * tmi->matrix[1][0] + tmi->translate[0];
988 		st[1] = s * tmi->matrix[0][1] + t * tmi->matrix[1][1] + tmi->translate[1];
989 	}
990 }
991 
992 /*
993 ** RB_CalcRotateTexCoords
994 */
RB_CalcRotateTexCoords(float degsPerSecond,float * st)995 void RB_CalcRotateTexCoords( float degsPerSecond, float *st )
996 {
997 	float timeScale = tess.shaderTime;
998 	float degs;
999 	int index;
1000 	float sinValue, cosValue;
1001 	texModInfo_t tmi;
1002 
1003 	degs = -degsPerSecond * timeScale;
1004 	index = degs * ( FUNCTABLE_SIZE / 360.0f );
1005 
1006 	sinValue = tr.sinTable[ index & FUNCTABLE_MASK ];
1007 	cosValue = tr.sinTable[ ( index + FUNCTABLE_SIZE / 4 ) & FUNCTABLE_MASK ];
1008 
1009 	tmi.matrix[0][0] = cosValue;
1010 	tmi.matrix[1][0] = -sinValue;
1011 	tmi.translate[0] = 0.5 - 0.5 * cosValue + 0.5 * sinValue;
1012 
1013 	tmi.matrix[0][1] = sinValue;
1014 	tmi.matrix[1][1] = cosValue;
1015 	tmi.translate[1] = 0.5 - 0.5 * sinValue - 0.5 * cosValue;
1016 
1017 	RB_CalcTransformTexCoords( &tmi, st );
1018 }
1019 
1020 
1021 
1022 
1023 
1024 
1025 #if id386 && !defined(__GNUC__)
1026 
myftol(float f)1027 long myftol( float f ) {
1028 	static int tmp;
1029 	__asm fld f
1030 	__asm fistp tmp
1031 	__asm mov eax, tmp
1032 }
1033 
1034 #endif
1035 
1036 /*
1037 ** RB_CalcSpecularAlpha
1038 **
1039 ** Calculates specular coefficient and places it in the alpha channel
1040 */
1041 vec3_t lightOrigin = { -960, 1980, 96 };		// FIXME: track dynamically
1042 
RB_CalcSpecularAlpha(unsigned char * alphas)1043 void RB_CalcSpecularAlpha( unsigned char *alphas ) {
1044 	int			i;
1045 	float		*v, *normal;
1046 	vec3_t		viewer,  reflected;
1047 	float		l, d;
1048 	int			b;
1049 	vec3_t		lightDir;
1050 	int			numVertexes;
1051 
1052 	v = tess.xyz[0];
1053 	normal = tess.normal[0];
1054 
1055 	alphas += 3;
1056 
1057 	numVertexes = tess.numVertexes;
1058 	for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4, alphas += 4) {
1059 		float ilength;
1060 
1061 		VectorSubtract( lightOrigin, v, lightDir );
1062 //		ilength = Q_rsqrt( DotProduct( lightDir, lightDir ) );
1063 		VectorNormalizeFast( lightDir );
1064 
1065 		// calculate the specular color
1066 		d = DotProduct (normal, lightDir);
1067 //		d *= ilength;
1068 
1069 		// we don't optimize for the d < 0 case since this tends to
1070 		// cause visual artifacts such as faceted "snapping"
1071 		reflected[0] = normal[0]*2*d - lightDir[0];
1072 		reflected[1] = normal[1]*2*d - lightDir[1];
1073 		reflected[2] = normal[2]*2*d - lightDir[2];
1074 
1075 		VectorSubtract (backEnd.or.viewOrigin, v, viewer);
1076 		ilength = Q_rsqrt( DotProduct( viewer, viewer ) );
1077 		l = DotProduct (reflected, viewer);
1078 		l *= ilength;
1079 
1080 		if (l < 0) {
1081 			b = 0;
1082 		} else {
1083 			l = l*l;
1084 			l = l*l;
1085 			b = l * 255;
1086 			if (b > 255) {
1087 				b = 255;
1088 			}
1089 		}
1090 
1091 		*alphas = b;
1092 	}
1093 }
1094 
1095 /*
1096 ** RB_CalcDiffuseColor
1097 **
1098 ** The basic vertex lighting calc
1099 */
1100 #if idppc_altivec
RB_CalcDiffuseColor_altivec(unsigned char * colors)1101 static void RB_CalcDiffuseColor_altivec( unsigned char *colors )
1102 {
1103 	int				i;
1104 	float			*v, *normal;
1105 	trRefEntity_t	*ent;
1106 	int				ambientLightInt;
1107 	vec3_t			lightDir;
1108 	int				numVertexes;
1109 	vector unsigned char vSel = VECCONST_UINT8(0x00, 0x00, 0x00, 0xff,
1110                                                0x00, 0x00, 0x00, 0xff,
1111                                                0x00, 0x00, 0x00, 0xff,
1112                                                0x00, 0x00, 0x00, 0xff);
1113 	vector float ambientLightVec;
1114 	vector float directedLightVec;
1115 	vector float lightDirVec;
1116 	vector float normalVec0, normalVec1;
1117 	vector float incomingVec0, incomingVec1, incomingVec2;
1118 	vector float zero, jVec;
1119 	vector signed int jVecInt;
1120 	vector signed short jVecShort;
1121 	vector unsigned char jVecChar, normalPerm;
1122 	ent = backEnd.currentEntity;
1123 	ambientLightInt = ent->ambientLightInt;
1124 	// A lot of this could be simplified if we made sure
1125 	// entities light info was 16-byte aligned.
1126 	jVecChar = vec_lvsl(0, ent->ambientLight);
1127 	ambientLightVec = vec_ld(0, (vector float *)ent->ambientLight);
1128 	jVec = vec_ld(11, (vector float *)ent->ambientLight);
1129 	ambientLightVec = vec_perm(ambientLightVec,jVec,jVecChar);
1130 
1131 	jVecChar = vec_lvsl(0, ent->directedLight);
1132 	directedLightVec = vec_ld(0,(vector float *)ent->directedLight);
1133 	jVec = vec_ld(11,(vector float *)ent->directedLight);
1134 	directedLightVec = vec_perm(directedLightVec,jVec,jVecChar);
1135 
1136 	jVecChar = vec_lvsl(0, ent->lightDir);
1137 	lightDirVec = vec_ld(0,(vector float *)ent->lightDir);
1138 	jVec = vec_ld(11,(vector float *)ent->lightDir);
1139 	lightDirVec = vec_perm(lightDirVec,jVec,jVecChar);
1140 
1141 	zero = (vector float)vec_splat_s8(0);
1142 	VectorCopy( ent->lightDir, lightDir );
1143 
1144 	v = tess.xyz[0];
1145 	normal = tess.normal[0];
1146 
1147 	normalPerm = vec_lvsl(0,normal);
1148 	numVertexes = tess.numVertexes;
1149 	for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4) {
1150 		normalVec0 = vec_ld(0,(vector float *)normal);
1151 		normalVec1 = vec_ld(11,(vector float *)normal);
1152 		normalVec0 = vec_perm(normalVec0,normalVec1,normalPerm);
1153 		incomingVec0 = vec_madd(normalVec0, lightDirVec, zero);
1154 		incomingVec1 = vec_sld(incomingVec0,incomingVec0,4);
1155 		incomingVec2 = vec_add(incomingVec0,incomingVec1);
1156 		incomingVec1 = vec_sld(incomingVec1,incomingVec1,4);
1157 		incomingVec2 = vec_add(incomingVec2,incomingVec1);
1158 		incomingVec0 = vec_splat(incomingVec2,0);
1159 		incomingVec0 = vec_max(incomingVec0,zero);
1160 		normalPerm = vec_lvsl(12,normal);
1161 		jVec = vec_madd(incomingVec0, directedLightVec, ambientLightVec);
1162 		jVecInt = vec_cts(jVec,0);	// RGBx
1163 		jVecShort = vec_pack(jVecInt,jVecInt);		// RGBxRGBx
1164 		jVecChar = vec_packsu(jVecShort,jVecShort);	// RGBxRGBxRGBxRGBx
1165 		jVecChar = vec_sel(jVecChar,vSel,vSel);		// RGBARGBARGBARGBA replace alpha with 255
1166 		vec_ste((vector unsigned int)jVecChar,0,(unsigned int *)&colors[i*4]);	// store color
1167 	}
1168 }
1169 #endif
1170 
RB_CalcDiffuseColor_scalar(unsigned char * colors)1171 static void RB_CalcDiffuseColor_scalar( unsigned char *colors )
1172 {
1173 	int				i, j;
1174 	float			*v, *normal;
1175 	float			incoming;
1176 	trRefEntity_t	*ent;
1177 	int				ambientLightInt;
1178 	vec3_t			ambientLight;
1179 	vec3_t			lightDir;
1180 	vec3_t			directedLight;
1181 	int				numVertexes;
1182 	ent = backEnd.currentEntity;
1183 	ambientLightInt = ent->ambientLightInt;
1184 	VectorCopy( ent->ambientLight, ambientLight );
1185 	VectorCopy( ent->directedLight, directedLight );
1186 	VectorCopy( ent->lightDir, lightDir );
1187 
1188 	v = tess.xyz[0];
1189 	normal = tess.normal[0];
1190 
1191 	numVertexes = tess.numVertexes;
1192 	for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4) {
1193 		incoming = DotProduct (normal, lightDir);
1194 		if ( incoming <= 0 ) {
1195 			*(int *)&colors[i*4] = ambientLightInt;
1196 			continue;
1197 		}
1198 		j = myftol( ambientLight[0] + incoming * directedLight[0] );
1199 		if ( j > 255 ) {
1200 			j = 255;
1201 		}
1202 		colors[i*4+0] = j;
1203 
1204 		j = myftol( ambientLight[1] + incoming * directedLight[1] );
1205 		if ( j > 255 ) {
1206 			j = 255;
1207 		}
1208 		colors[i*4+1] = j;
1209 
1210 		j = myftol( ambientLight[2] + incoming * directedLight[2] );
1211 		if ( j > 255 ) {
1212 			j = 255;
1213 		}
1214 		colors[i*4+2] = j;
1215 
1216 		colors[i*4+3] = 255;
1217 	}
1218 }
1219 
RB_CalcDiffuseColor(unsigned char * colors)1220 void RB_CalcDiffuseColor( unsigned char *colors )
1221 {
1222 #if idppc_altivec
1223 	if (com_altivec->integer) {
1224 		// must be in a seperate function or G3 systems will crash.
1225 		RB_CalcDiffuseColor_altivec( colors );
1226 		return;
1227 	}
1228 #endif
1229 	RB_CalcDiffuseColor_scalar( colors );
1230 }
1231 
1232