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