Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

tr_shade_calc.c (28766B)


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