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\n", tess.shader->name );
363 	}
364 	if ( tess.numIndexes != ( tess.numVertexes >> 2 ) * 6 ) {
365 		ri.Printf( PRINT_WARNING, "Autosprite shader %s had odd index count\n", 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_CalcEnvironmentTexCoordsNew
919 
920 	This one also is offset by origin and axis which makes it look better on moving
921 	objects and weapons. May be slow.
922 
923 */
RB_CalcEnvironmentTexCoordsNew(float * st)924 void RB_CalcEnvironmentTexCoordsNew( float *st )
925 {
926 
927 	int			i;
928 	float		*v, *normal;
929 	vec3_t		viewer, reflected, where, what, why, who;
930 	float		d, a;
931 
932 	v = tess.xyz[0];
933 	normal = tess.normal[0];
934 
935 	for (i = 0 ; i < tess.numVertexes ; i++, v += 4, normal += 4, st += 2 )
936 	{
937 
938 		VectorSubtract (backEnd.or.axis[0], v, what);
939 		VectorSubtract (backEnd.or.axis[1], v, why);
940 		VectorSubtract (backEnd.or.axis[2], v, who);
941 
942 		VectorSubtract (backEnd.or.origin, v, where);
943 		VectorSubtract (backEnd.or.viewOrigin, v, viewer);
944 
945 		VectorNormalizeFast (viewer);
946 		VectorNormalizeFast (where);
947 		VectorNormalizeFast (what);
948 		VectorNormalizeFast (why);
949 		VectorNormalizeFast (who);
950 
951 		d = DotProduct (normal, viewer);
952 		a = DotProduct (normal, where);
953 
954 		if ( backEnd.currentEntity == &tr.worldEntity ){
955 
956 		reflected[0] = normal[0]*2*d - viewer[0];
957 		reflected[1] = normal[1]*2*d - viewer[1];
958 		reflected[2] = normal[2]*2*d - viewer[2];
959 
960 		}
961 	else
962 		{
963 		reflected[0] = normal[0]*2*d - viewer[0] - (where[0] * 5) + (what[0] * 4);
964 		reflected[1] = normal[1]*2*d - viewer[1] - (where[1] * 5) + (why[1] * 4);
965 		reflected[2] = normal[2]*2*d - viewer[2] - (where[2] * 5) + (who[2] * 4);
966 
967 
968 		}
969 		st[0] = 0.33 + reflected[1] * 0.33;
970 		st[1] = 0.33 - reflected[2] * 0.33;
971 	}
972 }
973 
974 
975 /*
976 ** RB_CalcEnvironmentTexCoordsHW
977 
978 	Hardware-native cubemapping (or sphere mapping if the former is unsupported)
979 
980 	adapted from this tremulous patch by Odin
981 
982 	NOTE: THIS BREAKS OTHER TCMODS IN A STAGE
983 */
RB_CalcEnvironmentTexCoordsHW()984 void RB_CalcEnvironmentTexCoordsHW()
985 {
986 	qglTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
987 	qglTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
988 	qglTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
989 	qglEnable(GL_TEXTURE_GEN_S);
990 	qglEnable(GL_TEXTURE_GEN_T);
991 	qglEnable(GL_TEXTURE_GEN_R);
992 }
993 
994 /*
995 ** RB_CalcEnvironmentCelShadeTexCoords
996 **
997 ** RiO; celshade 1D environment map
998 */
999 
RB_CalcEnvironmentCelShadeTexCoords(float * st)1000 void RB_CalcEnvironmentCelShadeTexCoords( float *st )
1001 {
1002     int    i;
1003     float  *v, *normal;
1004     vec3_t lightDir;
1005     float  d;
1006 
1007     normal = tess.normal[0];
1008 	v = tess.xyz[0];
1009 
1010 	// Calculate only once
1011 //	VectorCopy( backEnd.currentEntity->lightDir, lightDir );
1012 //	if ( backEnd.currentEntity == &tr.worldEntity )
1013 //		VectorSubtract( lightOrigin, v, lightDir );
1014 //	else
1015 		VectorCopy( backEnd.currentEntity->lightDir, lightDir );
1016 	VectorNormalizeFast( lightDir );
1017 
1018     for (i = 0 ; i < tess.numVertexes ; i++, v += 4, normal += 4, st += 2 ) {
1019 		d= DotProduct( normal, lightDir );
1020 
1021 		st[0] = 0.5 + d * 0.5;
1022 		st[1] = 0.5;
1023     }
1024 }
1025 
1026 /*
1027 ** RB_CalcTurbulentTexCoords
1028 */
RB_CalcTurbulentTexCoords(const waveForm_t * wf,float * st)1029 void RB_CalcTurbulentTexCoords( const waveForm_t *wf, float *st )
1030 {
1031 	int i;
1032 	float now;
1033 
1034 	now = ( wf->phase + tess.shaderTime * wf->frequency );
1035 
1036 	for ( i = 0; i < tess.numVertexes; i++, st += 2 )
1037 	{
1038 		float s = st[0];
1039 		float t = st[1];
1040 
1041 		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;
1042 		st[1] = t + tr.sinTable[ ( ( int ) ( ( tess.xyz[i][1] * 1.0/128 * 0.125 + now ) * FUNCTABLE_SIZE ) ) & ( FUNCTABLE_MASK ) ] * wf->amplitude;
1043 	}
1044 }
1045 
1046 /*
1047 ** RB_CalcScaleTexCoords
1048 */
RB_CalcScaleTexCoords(const float scale[2],float * st)1049 void RB_CalcScaleTexCoords( const float scale[2], float *st )
1050 {
1051 	int i;
1052 
1053 	for ( i = 0; i < tess.numVertexes; i++, st += 2 )
1054 	{
1055 		st[0] *= scale[0];
1056 		st[1] *= scale[1];
1057 	}
1058 }
1059 
1060 /*
1061 ** RB_CalcScrollTexCoords
1062 */
RB_CalcScrollTexCoords(const float scrollSpeed[2],float * st)1063 void RB_CalcScrollTexCoords( const float scrollSpeed[2], float *st )
1064 {
1065 	int i;
1066 	float timeScale = tess.shaderTime;
1067 	float adjustedScrollS, adjustedScrollT;
1068 
1069 	adjustedScrollS = scrollSpeed[0] * timeScale;
1070 	adjustedScrollT = scrollSpeed[1] * timeScale;
1071 
1072 	// clamp so coordinates don't continuously get larger, causing problems
1073 	// with hardware limits
1074 	adjustedScrollS = adjustedScrollS - floor( adjustedScrollS );
1075 	adjustedScrollT = adjustedScrollT - floor( adjustedScrollT );
1076 
1077 	for ( i = 0; i < tess.numVertexes; i++, st += 2 )
1078 	{
1079 		st[0] += adjustedScrollS;
1080 		st[1] += adjustedScrollT;
1081 	}
1082 }
1083 
1084 /*
1085 ** RB_CalcTransformTexCoords
1086 */
RB_CalcTransformTexCoords(const texModInfo_t * tmi,float * st)1087 void RB_CalcTransformTexCoords( const texModInfo_t *tmi, float *st  )
1088 {
1089 	int i;
1090 
1091 	for ( i = 0; i < tess.numVertexes; i++, st += 2 )
1092 	{
1093 		float s = st[0];
1094 		float t = st[1];
1095 
1096 		st[0] = s * tmi->matrix[0][0] + t * tmi->matrix[1][0] + tmi->translate[0];
1097 		st[1] = s * tmi->matrix[0][1] + t * tmi->matrix[1][1] + tmi->translate[1];
1098 	}
1099 }
1100 
1101 /*
1102 ** RB_CalcRotateTexCoords
1103 */
RB_CalcRotateTexCoords(float degsPerSecond,float * st)1104 void RB_CalcRotateTexCoords( float degsPerSecond, float *st )
1105 {
1106 	float timeScale = tess.shaderTime;
1107 	float degs;
1108 	int index;
1109 	float sinValue, cosValue;
1110 	texModInfo_t tmi;
1111 
1112 	degs = -degsPerSecond * timeScale;
1113 	index = degs * ( FUNCTABLE_SIZE / 360.0f );
1114 
1115 	sinValue = tr.sinTable[ index & FUNCTABLE_MASK ];
1116 	cosValue = tr.sinTable[ ( index + FUNCTABLE_SIZE / 4 ) & FUNCTABLE_MASK ];
1117 
1118 	tmi.matrix[0][0] = cosValue;
1119 	tmi.matrix[1][0] = -sinValue;
1120 	tmi.translate[0] = 0.5 - 0.5 * cosValue + 0.5 * sinValue;
1121 
1122 	tmi.matrix[0][1] = sinValue;
1123 	tmi.matrix[1][1] = cosValue;
1124 	tmi.translate[1] = 0.5 - 0.5 * sinValue - 0.5 * cosValue;
1125 
1126 	RB_CalcTransformTexCoords( &tmi, st );
1127 }
1128 
1129 
1130 
1131 
1132 
1133 
1134 #if id386 && !defined(__GNUC__)
1135 
myftol(float f)1136 long myftol( float f ) {
1137 	static int tmp;
1138 	__asm fld f
1139 	__asm fistp tmp
1140 	__asm mov eax, tmp
1141 }
1142 
1143 #endif
1144 
1145 /*
1146 ** RB_CalcSpecularAlpha
1147 **
1148 ** Calculates specular coefficient and places it in the alpha channel
1149 */
1150 vec3_t lightOrigin = { -960, 1980, 96 };		// FIXME: track dynamically
1151 
RB_CalcSpecularAlpha(unsigned char * alphas)1152 void RB_CalcSpecularAlpha( unsigned char *alphas ) {
1153 	int			i;
1154 	float		*v, *normal;
1155 	vec3_t		viewer,  reflected;
1156 	float		l, d;
1157 	int			b;
1158 	vec3_t		lightDir;
1159 	int			numVertexes;
1160 
1161 	v = tess.xyz[0];
1162 	normal = tess.normal[0];
1163 
1164 	alphas += 3;
1165 
1166 	numVertexes = tess.numVertexes;
1167 	for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4, alphas += 4) {
1168 		float ilength;
1169 
1170 		VectorSubtract( lightOrigin, v, lightDir );
1171 //		ilength = Q_rsqrt( DotProduct( lightDir, lightDir ) );
1172 		VectorNormalizeFast( lightDir );
1173 
1174 		// calculate the specular color
1175 		d = DotProduct (normal, lightDir);
1176 //		d *= ilength;
1177 
1178 		// we don't optimize for the d < 0 case since this tends to
1179 		// cause visual artifacts such as faceted "snapping"
1180 		reflected[0] = normal[0]*2*d - lightDir[0];
1181 		reflected[1] = normal[1]*2*d - lightDir[1];
1182 		reflected[2] = normal[2]*2*d - lightDir[2];
1183 
1184 		VectorSubtract (backEnd.or.viewOrigin, v, viewer);
1185 		ilength = Q_rsqrt( DotProduct( viewer, viewer ) );
1186 		l = DotProduct (reflected, viewer);
1187 		l *= ilength;
1188 
1189 		if (l < 0) {
1190 			b = 0;
1191 		} else {
1192 			l = l*l;
1193 			l = l*l;
1194 			b = l * 255;
1195 			if (b > 255) {
1196 				b = 255;
1197 			}
1198 		}
1199 
1200 		*alphas = b;
1201 	}
1202 }
1203 
1204 // This fixed version comes from ZEQ2Lite
RB_CalcSpecularAlphaNew(unsigned char * alphas)1205 void RB_CalcSpecularAlphaNew( unsigned char *alphas ) {
1206 int			i;
1207 	float		*v, *normal;
1208 	vec3_t		viewer,  reflected;
1209 	float		l, d;
1210 	int			b;
1211 	vec3_t		lightDir;
1212 	int			numVertexes;
1213 
1214 	v = tess.xyz[0];
1215 	normal = tess.normal[0];
1216 
1217 	alphas += 3;
1218 
1219 	numVertexes = tess.numVertexes;
1220 	for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4, alphas += 4) {
1221 		float ilength;
1222 
1223 		if ( backEnd.currentEntity == &tr.worldEntity )
1224 			VectorSubtract( lightOrigin, v, lightDir );	// old compatibility with maps that use it on some models
1225 		else
1226 			VectorCopy( backEnd.currentEntity->lightDir, lightDir );
1227 
1228 		VectorNormalizeFast( lightDir );
1229 
1230 		// calculate the specular color
1231 		d = DotProduct (normal, lightDir);
1232 
1233 		// we don't optimize for the d < 0 case since this tends to
1234 		// cause visual artifacts such as faceted "snapping"
1235 		reflected[0] = normal[0]*2*d - lightDir[0];
1236 		reflected[1] = normal[1]*2*d - lightDir[1];
1237 		reflected[2] = normal[2]*2*d - lightDir[2];
1238 
1239 		VectorSubtract (backEnd.or.viewOrigin, v, viewer);
1240 		ilength = Q_rsqrt( DotProduct( viewer, viewer ) );
1241 		l = DotProduct (reflected, viewer);
1242 		l *= ilength;
1243 
1244 		if (l < 0) {
1245 			b = 0;
1246 		} else {
1247 			l = l*l;
1248 			l = l*l;
1249 			b = l * 255;
1250 			if (b > 255) {
1251 				b = 255;
1252 			}
1253 		}
1254 
1255 		*alphas = b;
1256 	}
1257 
1258 }
1259 
1260 /*
1261 ** RB_CalcDiffuseColor
1262 **
1263 ** The basic vertex lighting calc
1264 */
1265 #if idppc_altivec
RB_CalcDiffuseColor_altivec(unsigned char * colors)1266 static void RB_CalcDiffuseColor_altivec( unsigned char *colors )
1267 {
1268 	int				i;
1269 	float			*v, *normal;
1270 	trRefEntity_t	*ent;
1271 	int				ambientLightInt;
1272 	vec3_t			lightDir;
1273 	int				numVertexes;
1274 	vector unsigned char vSel = VECCONST_UINT8(0x00, 0x00, 0x00, 0xff,
1275                                                0x00, 0x00, 0x00, 0xff,
1276                                                0x00, 0x00, 0x00, 0xff,
1277                                                0x00, 0x00, 0x00, 0xff);
1278 	vector float ambientLightVec;
1279 	vector float directedLightVec;
1280 	vector float lightDirVec;
1281 	vector float normalVec0, normalVec1;
1282 	vector float incomingVec0, incomingVec1, incomingVec2;
1283 	vector float zero, jVec;
1284 	vector signed int jVecInt;
1285 	vector signed short jVecShort;
1286 	vector unsigned char jVecChar, normalPerm;
1287 	ent = backEnd.currentEntity;
1288 	ambientLightInt = ent->ambientLightInt;
1289 	// A lot of this could be simplified if we made sure
1290 	// entities light info was 16-byte aligned.
1291 	jVecChar = vec_lvsl(0, ent->ambientLight);
1292 	ambientLightVec = vec_ld(0, (vector float *)ent->ambientLight);
1293 	jVec = vec_ld(11, (vector float *)ent->ambientLight);
1294 	ambientLightVec = vec_perm(ambientLightVec,jVec,jVecChar);
1295 
1296 	jVecChar = vec_lvsl(0, ent->directedLight);
1297 	directedLightVec = vec_ld(0,(vector float *)ent->directedLight);
1298 	jVec = vec_ld(11,(vector float *)ent->directedLight);
1299 	directedLightVec = vec_perm(directedLightVec,jVec,jVecChar);
1300 
1301 	jVecChar = vec_lvsl(0, ent->lightDir);
1302 	lightDirVec = vec_ld(0,(vector float *)ent->lightDir);
1303 	jVec = vec_ld(11,(vector float *)ent->lightDir);
1304 	lightDirVec = vec_perm(lightDirVec,jVec,jVecChar);
1305 
1306 	zero = (vector float)vec_splat_s8(0);
1307 	VectorCopy( ent->lightDir, lightDir );
1308 
1309 	v = tess.xyz[0];
1310 	normal = tess.normal[0];
1311 
1312 	normalPerm = vec_lvsl(0,normal);
1313 	numVertexes = tess.numVertexes;
1314 	for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4) {
1315 		normalVec0 = vec_ld(0,(vector float *)normal);
1316 		normalVec1 = vec_ld(11,(vector float *)normal);
1317 		normalVec0 = vec_perm(normalVec0,normalVec1,normalPerm);
1318 		incomingVec0 = vec_madd(normalVec0, lightDirVec, zero);
1319 		incomingVec1 = vec_sld(incomingVec0,incomingVec0,4);
1320 		incomingVec2 = vec_add(incomingVec0,incomingVec1);
1321 		incomingVec1 = vec_sld(incomingVec1,incomingVec1,4);
1322 		incomingVec2 = vec_add(incomingVec2,incomingVec1);
1323 		incomingVec0 = vec_splat(incomingVec2,0);
1324 		incomingVec0 = vec_max(incomingVec0,zero);
1325 		normalPerm = vec_lvsl(12,normal);
1326 		jVec = vec_madd(incomingVec0, directedLightVec, ambientLightVec);
1327 		jVecInt = vec_cts(jVec,0);	// RGBx
1328 		jVecShort = vec_pack(jVecInt,jVecInt);		// RGBxRGBx
1329 		jVecChar = vec_packsu(jVecShort,jVecShort);	// RGBxRGBxRGBxRGBx
1330 		jVecChar = vec_sel(jVecChar,vSel,vSel);		// RGBARGBARGBARGBA replace alpha with 255
1331 		vec_ste((vector unsigned int)jVecChar,0,(unsigned int *)&colors[i*4]);	// store color
1332 	}
1333 }
1334 #endif
1335 
RB_CalcDiffuseColor_scalar(unsigned char * colors)1336 static void RB_CalcDiffuseColor_scalar( unsigned char *colors )
1337 {
1338 	int				i, j;
1339 	float			*v, *normal;
1340 	float			incoming;
1341 	trRefEntity_t	*ent;
1342 	int				ambientLightInt;
1343 	vec3_t			ambientLight;
1344 	vec3_t			lightDir;
1345 	vec3_t			directedLight;
1346 	int				numVertexes;
1347 	ent = backEnd.currentEntity;
1348 	ambientLightInt = ent->ambientLightInt;
1349 	VectorCopy( ent->ambientLight, ambientLight );
1350 	VectorCopy( ent->directedLight, directedLight );
1351 	VectorCopy( ent->lightDir, lightDir );
1352 
1353 	v = tess.xyz[0];
1354 	normal = tess.normal[0];
1355 
1356 	numVertexes = tess.numVertexes;
1357 	for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4) {
1358 		incoming = DotProduct (normal, lightDir);
1359 		if ( incoming <= 0 ) {
1360 			*(int *)&colors[i*4] = ambientLightInt;
1361 			continue;
1362 		}
1363 		j = myftol( ambientLight[0] + incoming * directedLight[0] );
1364 		if ( j > 255 ) {
1365 			j = 255;
1366 		}
1367 		colors[i*4+0] = j;
1368 
1369 		j = myftol( ambientLight[1] + incoming * directedLight[1] );
1370 		if ( j > 255 ) {
1371 			j = 255;
1372 		}
1373 		colors[i*4+1] = j;
1374 
1375 		j = myftol( ambientLight[2] + incoming * directedLight[2] );
1376 		if ( j > 255 ) {
1377 			j = 255;
1378 		}
1379 		colors[i*4+2] = j;
1380 
1381 		colors[i*4+3] = 255;
1382 	}
1383 }
1384 
RB_CalcDiffuseColor(unsigned char * colors)1385 void RB_CalcDiffuseColor( unsigned char *colors )
1386 {
1387 #if idppc_altivec
1388 	if (com_altivec->integer) {
1389 		// must be in a seperate function or G3 systems will crash.
1390 		RB_CalcDiffuseColor_altivec( colors );
1391 		return;
1392 	}
1393 #endif
1394 	RB_CalcDiffuseColor_scalar( colors );
1395 }
1396 
1397 /*
1398 ** RB_CalcUniformColor
1399 **
1400 ** RiO; Uniform vertex color lighting for cel shading
1401 */
RB_CalcUniformColor(unsigned char * colors)1402 void RB_CalcUniformColor( unsigned char *colors )
1403 {
1404 
1405 	int				i;
1406 	trRefEntity_t	*ent;
1407 	vec3_t			ambientLight;
1408 	vec3_t			directedLight;
1409 	vec4_t			uniformLight;
1410 	int				numVertexes;
1411 	float			normalize;
1412 
1413 	ent = backEnd.currentEntity;
1414 
1415 	VectorCopy( ent->ambientLight, ambientLight );
1416 	VectorCopy( ent->directedLight, directedLight );
1417 
1418 	VectorAdd( ambientLight, ambientLight/*directedLight*/, uniformLight );
1419 
1420 	normalize = NormalizeColor( uniformLight, uniformLight );
1421 	if ( normalize > 255 ) normalize = 255;
1422 	VectorScale( uniformLight, normalize, uniformLight );
1423 	uniformLight[3] = 255;
1424 
1425 	numVertexes = tess.numVertexes;
1426 	for (i = 0 ; i < numVertexes ; i++ ) {
1427 		colors[i*4+0] = uniformLight[0];
1428 		colors[i*4+1] = uniformLight[1];
1429 		colors[i*4+2] = uniformLight[2];
1430 		colors[i*4+3] = uniformLight[3];
1431 	}
1432 }
1433 
1434 /*
1435 ** RB_CalcDynamicColor
1436 **
1437 ** MDave; Vertex color dynamic lighting for cel shading
1438 */
RB_CalcDynamicColor(unsigned char * colors)1439 void RB_CalcDynamicColor( unsigned char *colors )
1440 {
1441 	int				i;
1442 	trRefEntity_t	*ent;
1443 	vec4_t			dynamic;
1444 	int				numVertexes;
1445 	float			normalize;
1446 
1447 	ent = backEnd.currentEntity;
1448 
1449 	VectorCopy( ent->dynamicLight, dynamic );
1450 
1451 	normalize = NormalizeColor( dynamic, dynamic );
1452 	if ( normalize > 255 ) normalize = 255;
1453 	VectorScale( dynamic, normalize, dynamic );
1454 	dynamic[3] = 255;
1455 
1456 	numVertexes = tess.numVertexes;
1457 	for (i = 0 ; i < numVertexes ; i++ ) {
1458 		colors[i*4+0] = dynamic[0];
1459 		colors[i*4+1] = dynamic[1];
1460 		colors[i*4+2] = dynamic[2];
1461 		colors[i*4+3] = dynamic[3];
1462 	}
1463 }
1464