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