Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

tr_shade_calc.c

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 // tr_shade_calc.c
00023 
00024 #include "tr_local.h"
00025 
00026 
00027 #define WAVEVALUE( table, base, amplitude, phase, freq )  ((base) + table[ myftol( ( ( (phase) + tess.shaderTime * (freq) ) * FUNCTABLE_SIZE ) ) & FUNCTABLE_MASK ] * (amplitude))
00028 
00029 static float *TableForFunc( genFunc_t func ) 
00030 {
00031     switch ( func )
00032     {
00033     case GF_SIN:
00034         return tr.sinTable;
00035     case GF_TRIANGLE:
00036         return tr.triangleTable;
00037     case GF_SQUARE:
00038         return tr.squareTable;
00039     case GF_SAWTOOTH:
00040         return tr.sawToothTable;
00041     case GF_INVERSE_SAWTOOTH:
00042         return tr.inverseSawToothTable;
00043     case GF_NONE:
00044     default:
00045         break;
00046     }
00047 
00048     ri.Error( ERR_DROP, "TableForFunc called with invalid function '%d' in shader '%s'\n", func, tess.shader->name );
00049     return NULL;
00050 }
00051 
00052 /*
00053 ** EvalWaveForm
00054 **
00055 ** Evaluates a given waveForm_t, referencing backEnd.refdef.time directly
00056 */
00057 static float EvalWaveForm( const waveForm_t *wf ) 
00058 {
00059     float   *table;
00060 
00061     table = TableForFunc( wf->func );
00062 
00063     return WAVEVALUE( table, wf->base, wf->amplitude, wf->phase, wf->frequency );
00064 }
00065 
00066 static float EvalWaveFormClamped( const waveForm_t *wf )
00067 {
00068     float glow  = EvalWaveForm( wf );
00069 
00070     if ( glow < 0 )
00071     {
00072         return 0;
00073     }
00074 
00075     if ( glow > 1 )
00076     {
00077         return 1;
00078     }
00079 
00080     return glow;
00081 }
00082 
00083 /*
00084 ** RB_CalcStretchTexCoords
00085 */
00086 void RB_CalcStretchTexCoords( const waveForm_t *wf, float *st )
00087 {
00088     float p;
00089     texModInfo_t tmi;
00090 
00091     p = 1.0f / EvalWaveForm( wf );
00092 
00093     tmi.matrix[0][0] = p;
00094     tmi.matrix[1][0] = 0;
00095     tmi.translate[0] = 0.5f - 0.5f * p;
00096 
00097     tmi.matrix[0][1] = 0;
00098     tmi.matrix[1][1] = p;
00099     tmi.translate[1] = 0.5f - 0.5f * p;
00100 
00101     RB_CalcTransformTexCoords( &tmi, st );
00102 }
00103 
00104 /*
00105 ====================================================================
00106 
00107 DEFORMATIONS
00108 
00109 ====================================================================
00110 */
00111 
00112 /*
00113 ========================
00114 RB_CalcDeformVertexes
00115 
00116 ========================
00117 */
00118 void RB_CalcDeformVertexes( deformStage_t *ds )
00119 {
00120     int i;
00121     vec3_t  offset;
00122     float   scale;
00123     float   *xyz = ( float * ) tess.xyz;
00124     float   *normal = ( float * ) tess.normal;
00125     float   *table;
00126 
00127     if ( ds->deformationWave.frequency == 0 )
00128     {
00129         scale = EvalWaveForm( &ds->deformationWave );
00130 
00131         for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal += 4 )
00132         {
00133             VectorScale( normal, scale, offset );
00134             
00135             xyz[0] += offset[0];
00136             xyz[1] += offset[1];
00137             xyz[2] += offset[2];
00138         }
00139     }
00140     else
00141     {
00142         table = TableForFunc( ds->deformationWave.func );
00143 
00144         for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal += 4 )
00145         {
00146             float off = ( xyz[0] + xyz[1] + xyz[2] ) * ds->deformationSpread;
00147 
00148             scale = WAVEVALUE( table, ds->deformationWave.base, 
00149                 ds->deformationWave.amplitude,
00150                 ds->deformationWave.phase + off,
00151                 ds->deformationWave.frequency );
00152 
00153             VectorScale( normal, scale, offset );
00154             
00155             xyz[0] += offset[0];
00156             xyz[1] += offset[1];
00157             xyz[2] += offset[2];
00158         }
00159     }
00160 }
00161 
00162 /*
00163 =========================
00164 RB_CalcDeformNormals
00165 
00166 Wiggle the normals for wavy environment mapping
00167 =========================
00168 */
00169 void RB_CalcDeformNormals( deformStage_t *ds ) {
00170     int i;
00171     float   scale;
00172     float   *xyz = ( float * ) tess.xyz;
00173     float   *normal = ( float * ) tess.normal;
00174 
00175     for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal += 4 ) {
00176         scale = 0.98f;
00177         scale = R_NoiseGet4f( xyz[0] * scale, xyz[1] * scale, xyz[2] * scale,
00178             tess.shaderTime * ds->deformationWave.frequency );
00179         normal[ 0 ] += ds->deformationWave.amplitude * scale;
00180 
00181         scale = 0.98f;
00182         scale = R_NoiseGet4f( 100 + xyz[0] * scale, xyz[1] * scale, xyz[2] * scale,
00183             tess.shaderTime * ds->deformationWave.frequency );
00184         normal[ 1 ] += ds->deformationWave.amplitude * scale;
00185 
00186         scale = 0.98f;
00187         scale = R_NoiseGet4f( 200 + xyz[0] * scale, xyz[1] * scale, xyz[2] * scale,
00188             tess.shaderTime * ds->deformationWave.frequency );
00189         normal[ 2 ] += ds->deformationWave.amplitude * scale;
00190 
00191         VectorNormalizeFast( normal );
00192     }
00193 }
00194 
00195 /*
00196 ========================
00197 RB_CalcBulgeVertexes
00198 
00199 ========================
00200 */
00201 void RB_CalcBulgeVertexes( deformStage_t *ds ) {
00202     int i;
00203     const float *st = ( const float * ) tess.texCoords[0];
00204     float       *xyz = ( float * ) tess.xyz;
00205     float       *normal = ( float * ) tess.normal;
00206     float       now;
00207 
00208     now = backEnd.refdef.time * ds->bulgeSpeed * 0.001f;
00209 
00210     for ( i = 0; i < tess.numVertexes; i++, xyz += 4, st += 4, normal += 4 ) {
00211         int     off;
00212         float scale;
00213 
00214         off = (float)( FUNCTABLE_SIZE / (M_PI*2) ) * ( st[0] * ds->bulgeWidth + now );
00215 
00216         scale = tr.sinTable[ off & FUNCTABLE_MASK ] * ds->bulgeHeight;
00217             
00218         xyz[0] += normal[0] * scale;
00219         xyz[1] += normal[1] * scale;
00220         xyz[2] += normal[2] * scale;
00221     }
00222 }
00223 
00224 
00225 /*
00226 ======================
00227 RB_CalcMoveVertexes
00228 
00229 A deformation that can move an entire surface along a wave path
00230 ======================
00231 */
00232 void RB_CalcMoveVertexes( deformStage_t *ds ) {
00233     int         i;
00234     float       *xyz;
00235     float       *table;
00236     float       scale;
00237     vec3_t      offset;
00238 
00239     table = TableForFunc( ds->deformationWave.func );
00240 
00241     scale = WAVEVALUE( table, ds->deformationWave.base, 
00242         ds->deformationWave.amplitude,
00243         ds->deformationWave.phase,
00244         ds->deformationWave.frequency );
00245 
00246     VectorScale( ds->moveVector, scale, offset );
00247 
00248     xyz = ( float * ) tess.xyz;
00249     for ( i = 0; i < tess.numVertexes; i++, xyz += 4 ) {
00250         VectorAdd( xyz, offset, xyz );
00251     }
00252 }
00253 
00254 
00255 /*
00256 =============
00257 DeformText
00258 
00259 Change a polygon into a bunch of text polygons
00260 =============
00261 */
00262 void DeformText( const char *text ) {
00263     int     i;
00264     vec3_t  origin, width, height;
00265     int     len;
00266     int     ch;
00267     byte    color[4];
00268     float   bottom, top;
00269     vec3_t  mid;
00270 
00271     height[0] = 0;
00272     height[1] = 0;
00273     height[2] = -1;
00274     CrossProduct( tess.normal[0], height, width );
00275 
00276     // find the midpoint of the box
00277     VectorClear( mid );
00278     bottom = 999999;
00279     top = -999999;
00280     for ( i = 0 ; i < 4 ; i++ ) {
00281         VectorAdd( tess.xyz[i], mid, mid );
00282         if ( tess.xyz[i][2] < bottom ) {
00283             bottom = tess.xyz[i][2];
00284         }
00285         if ( tess.xyz[i][2] > top ) {
00286             top = tess.xyz[i][2];
00287         }
00288     }
00289     VectorScale( mid, 0.25f, origin );
00290 
00291     // determine the individual character size
00292     height[0] = 0;
00293     height[1] = 0;
00294     height[2] = ( top - bottom ) * 0.5f;
00295 
00296     VectorScale( width, height[2] * -0.75f, width );
00297 
00298     // determine the starting position
00299     len = strlen( text );
00300     VectorMA( origin, (len-1), width, origin );
00301 
00302     // clear the shader indexes
00303     tess.numIndexes = 0;
00304     tess.numVertexes = 0;
00305 
00306     color[0] = color[1] = color[2] = color[3] = 255;
00307 
00308     // draw each character
00309     for ( i = 0 ; i < len ; i++ ) {
00310         ch = text[i];
00311         ch &= 255;
00312 
00313         if ( ch != ' ' ) {
00314             int     row, col;
00315             float   frow, fcol, size;
00316 
00317             row = ch>>4;
00318             col = ch&15;
00319 
00320             frow = row*0.0625f;
00321             fcol = col*0.0625f;
00322             size = 0.0625f;
00323 
00324             RB_AddQuadStampExt( origin, width, height, color, fcol, frow, fcol + size, frow + size );
00325         }
00326         VectorMA( origin, -2, width, origin );
00327     }
00328 }
00329 
00330 /*
00331 ==================
00332 GlobalVectorToLocal
00333 ==================
00334 */
00335 static void GlobalVectorToLocal( const vec3_t in, vec3_t out ) {
00336     out[0] = DotProduct( in, backEnd.or.axis[0] );
00337     out[1] = DotProduct( in, backEnd.or.axis[1] );
00338     out[2] = DotProduct( in, backEnd.or.axis[2] );
00339 }
00340 
00341 /*
00342 =====================
00343 AutospriteDeform
00344 
00345 Assuming all the triangles for this shader are independant
00346 quads, rebuild them as forward facing sprites
00347 =====================
00348 */
00349 static void AutospriteDeform( void ) {
00350     int     i;
00351     int     oldVerts;
00352     float   *xyz;
00353     vec3_t  mid, delta;
00354     float   radius;
00355     vec3_t  left, up;
00356     vec3_t  leftDir, upDir;
00357 
00358     if ( tess.numVertexes & 3 ) {
00359         ri.Printf( PRINT_WARNING, "Autosprite shader %s had odd vertex count", tess.shader->name );
00360     }
00361     if ( tess.numIndexes != ( tess.numVertexes >> 2 ) * 6 ) {
00362         ri.Printf( PRINT_WARNING, "Autosprite shader %s had odd index count", tess.shader->name );
00363     }
00364 
00365     oldVerts = tess.numVertexes;
00366     tess.numVertexes = 0;
00367     tess.numIndexes = 0;
00368 
00369     if ( backEnd.currentEntity != &tr.worldEntity ) {
00370         GlobalVectorToLocal( backEnd.viewParms.or.axis[1], leftDir );
00371         GlobalVectorToLocal( backEnd.viewParms.or.axis[2], upDir );
00372     } else {
00373         VectorCopy( backEnd.viewParms.or.axis[1], leftDir );
00374         VectorCopy( backEnd.viewParms.or.axis[2], upDir );
00375     }
00376 
00377     for ( i = 0 ; i < oldVerts ; i+=4 ) {
00378         // find the midpoint
00379         xyz = tess.xyz[i];
00380 
00381         mid[0] = 0.25f * (xyz[0] + xyz[4] + xyz[8] + xyz[12]);
00382         mid[1] = 0.25f * (xyz[1] + xyz[5] + xyz[9] + xyz[13]);
00383         mid[2] = 0.25f * (xyz[2] + xyz[6] + xyz[10] + xyz[14]);
00384 
00385         VectorSubtract( xyz, mid, delta );
00386         radius = VectorLength( delta ) * 0.707f;        // / sqrt(2)
00387 
00388         VectorScale( leftDir, radius, left );
00389         VectorScale( upDir, radius, up );
00390 
00391         if ( backEnd.viewParms.isMirror ) {
00392             VectorSubtract( vec3_origin, left, left );
00393         }
00394 
00395       // compensate for scale in the axes if necessary
00396     if ( backEnd.currentEntity->e.nonNormalizedAxes ) {
00397       float axisLength;
00398           axisLength = VectorLength( backEnd.currentEntity->e.axis[0] );
00399         if ( !axisLength ) {
00400             axisLength = 0;
00401         } else {
00402             axisLength = 1.0f / axisLength;
00403         }
00404       VectorScale(left, axisLength, left);
00405       VectorScale(up, axisLength, up);
00406     }
00407 
00408         RB_AddQuadStamp( mid, left, up, tess.vertexColors[i] );
00409     }
00410 }
00411 
00412 
00413 /*
00414 =====================
00415 Autosprite2Deform
00416 
00417 Autosprite2 will pivot a rectangular quad along the center of its long axis
00418 =====================
00419 */
00420 int edgeVerts[6][2] = {
00421     { 0, 1 },
00422     { 0, 2 },
00423     { 0, 3 },
00424     { 1, 2 },
00425     { 1, 3 },
00426     { 2, 3 }
00427 };
00428 
00429 static void Autosprite2Deform( void ) {
00430     int     i, j, k;
00431     int     indexes;
00432     float   *xyz;
00433     vec3_t  forward;
00434 
00435     if ( tess.numVertexes & 3 ) {
00436         ri.Printf( PRINT_WARNING, "Autosprite2 shader %s had odd vertex count", tess.shader->name );
00437     }
00438     if ( tess.numIndexes != ( tess.numVertexes >> 2 ) * 6 ) {
00439         ri.Printf( PRINT_WARNING, "Autosprite2 shader %s had odd index count", tess.shader->name );
00440     }
00441 
00442     if ( backEnd.currentEntity != &tr.worldEntity ) {
00443         GlobalVectorToLocal( backEnd.viewParms.or.axis[0], forward );
00444     } else {
00445         VectorCopy( backEnd.viewParms.or.axis[0], forward );
00446     }
00447 
00448     // this is a lot of work for two triangles...
00449     // we could precalculate a lot of it is an issue, but it would mess up
00450     // the shader abstraction
00451     for ( i = 0, indexes = 0 ; i < tess.numVertexes ; i+=4, indexes+=6 ) {
00452         float   lengths[2];
00453         int     nums[2];
00454         vec3_t  mid[2];
00455         vec3_t  major, minor;
00456         float   *v1, *v2;
00457 
00458         // find the midpoint
00459         xyz = tess.xyz[i];
00460 
00461         // identify the two shortest edges
00462         nums[0] = nums[1] = 0;
00463         lengths[0] = lengths[1] = 999999;
00464 
00465         for ( j = 0 ; j < 6 ; j++ ) {
00466             float   l;
00467             vec3_t  temp;
00468 
00469             v1 = xyz + 4 * edgeVerts[j][0];
00470             v2 = xyz + 4 * edgeVerts[j][1];
00471 
00472             VectorSubtract( v1, v2, temp );
00473             
00474             l = DotProduct( temp, temp );
00475             if ( l < lengths[0] ) {
00476                 nums[1] = nums[0];
00477                 lengths[1] = lengths[0];
00478                 nums[0] = j;
00479                 lengths[0] = l;
00480             } else if ( l < lengths[1] ) {
00481                 nums[1] = j;
00482                 lengths[1] = l;
00483             }
00484         }
00485 
00486         for ( j = 0 ; j < 2 ; j++ ) {
00487             v1 = xyz + 4 * edgeVerts[nums[j]][0];
00488             v2 = xyz + 4 * edgeVerts[nums[j]][1];
00489 
00490             mid[j][0] = 0.5f * (v1[0] + v2[0]);
00491             mid[j][1] = 0.5f * (v1[1] + v2[1]);
00492             mid[j][2] = 0.5f * (v1[2] + v2[2]);
00493         }
00494 
00495         // find the vector of the major axis
00496         VectorSubtract( mid[1], mid[0], major );
00497 
00498         // cross this with the view direction to get minor axis
00499         CrossProduct( major, forward, minor );
00500         VectorNormalize( minor );
00501         
00502         // re-project the points
00503         for ( j = 0 ; j < 2 ; j++ ) {
00504             float   l;
00505 
00506             v1 = xyz + 4 * edgeVerts[nums[j]][0];
00507             v2 = xyz + 4 * edgeVerts[nums[j]][1];
00508 
00509             l = 0.5 * sqrt( lengths[j] );
00510             
00511             // we need to see which direction this edge
00512             // is used to determine direction of projection
00513             for ( k = 0 ; k < 5 ; k++ ) {
00514                 if ( tess.indexes[ indexes + k ] == i + edgeVerts[nums[j]][0]
00515                     && tess.indexes[ indexes + k + 1 ] == i + edgeVerts[nums[j]][1] ) {
00516                     break;
00517                 }
00518             }
00519 
00520             if ( k == 5 ) {
00521                 VectorMA( mid[j], l, minor, v1 );
00522                 VectorMA( mid[j], -l, minor, v2 );
00523             } else {
00524                 VectorMA( mid[j], -l, minor, v1 );
00525                 VectorMA( mid[j], l, minor, v2 );
00526             }
00527         }
00528     }
00529 }
00530 
00531 
00532 /*
00533 =====================
00534 RB_DeformTessGeometry
00535 
00536 =====================
00537 */
00538 void RB_DeformTessGeometry( void ) {
00539     int     i;
00540     deformStage_t   *ds;
00541 
00542     for ( i = 0 ; i < tess.shader->numDeforms ; i++ ) {
00543         ds = &tess.shader->deforms[ i ];
00544 
00545         switch ( ds->deformation ) {
00546         case DEFORM_NONE:
00547             break;
00548         case DEFORM_NORMALS:
00549             RB_CalcDeformNormals( ds );
00550             break;
00551         case DEFORM_WAVE:
00552             RB_CalcDeformVertexes( ds );
00553             break;
00554         case DEFORM_BULGE:
00555             RB_CalcBulgeVertexes( ds );
00556             break;
00557         case DEFORM_MOVE:
00558             RB_CalcMoveVertexes( ds );
00559             break;
00560         case DEFORM_PROJECTION_SHADOW:
00561             RB_ProjectionShadowDeform();
00562             break;
00563         case DEFORM_AUTOSPRITE:
00564             AutospriteDeform();
00565             break;
00566         case DEFORM_AUTOSPRITE2:
00567             Autosprite2Deform();
00568             break;
00569         case DEFORM_TEXT0:
00570         case DEFORM_TEXT1:
00571         case DEFORM_TEXT2:
00572         case DEFORM_TEXT3:
00573         case DEFORM_TEXT4:
00574         case DEFORM_TEXT5:
00575         case DEFORM_TEXT6:
00576         case DEFORM_TEXT7:
00577             DeformText( backEnd.refdef.text[ds->deformation - DEFORM_TEXT0] );
00578             break;
00579         }
00580     }
00581 }
00582 
00583 /*
00584 ====================================================================
00585 
00586 COLORS
00587 
00588 ====================================================================
00589 */
00590 
00591 
00592 /*
00593 ** RB_CalcColorFromEntity
00594 */
00595 void RB_CalcColorFromEntity( unsigned char *dstColors )
00596 {
00597     int i;
00598     int *pColors = ( int * ) dstColors;
00599     int c;
00600 
00601     if ( !backEnd.currentEntity )
00602         return;
00603 
00604     c = * ( int * ) backEnd.currentEntity->e.shaderRGBA;
00605 
00606     for ( i = 0; i < tess.numVertexes; i++, pColors++ )
00607     {
00608         *pColors = c;
00609     }
00610 }
00611 
00612 /*
00613 ** RB_CalcColorFromOneMinusEntity
00614 */
00615 void RB_CalcColorFromOneMinusEntity( unsigned char *dstColors )
00616 {
00617     int i;
00618     int *pColors = ( int * ) dstColors;
00619     unsigned char invModulate[3];
00620     int c;
00621 
00622     if ( !backEnd.currentEntity )
00623         return;
00624 
00625     invModulate[0] = 255 - backEnd.currentEntity->e.shaderRGBA[0];
00626     invModulate[1] = 255 - backEnd.currentEntity->e.shaderRGBA[1];
00627     invModulate[2] = 255 - backEnd.currentEntity->e.shaderRGBA[2];
00628     invModulate[3] = 255 - backEnd.currentEntity->e.shaderRGBA[3];  // this trashes alpha, but the AGEN block fixes it
00629 
00630     c = * ( int * ) invModulate;
00631 
00632     for ( i = 0; i < tess.numVertexes; i++, pColors++ )
00633     {
00634         *pColors = * ( int * ) invModulate;
00635     }
00636 }
00637 
00638 /*
00639 ** RB_CalcAlphaFromEntity
00640 */
00641 void RB_CalcAlphaFromEntity( unsigned char *dstColors )
00642 {
00643     int i;
00644 
00645     if ( !backEnd.currentEntity )
00646         return;
00647 
00648     dstColors += 3;
00649 
00650     for ( i = 0; i < tess.numVertexes; i++, dstColors += 4 )
00651     {
00652         *dstColors = backEnd.currentEntity->e.shaderRGBA[3];
00653     }
00654 }
00655 
00656 /*
00657 ** RB_CalcAlphaFromOneMinusEntity
00658 */
00659 void RB_CalcAlphaFromOneMinusEntity( unsigned char *dstColors )
00660 {
00661     int i;
00662 
00663     if ( !backEnd.currentEntity )
00664         return;
00665 
00666     dstColors += 3;
00667 
00668     for ( i = 0; i < tess.numVertexes; i++, dstColors += 4 )
00669     {
00670         *dstColors = 0xff - backEnd.currentEntity->e.shaderRGBA[3];
00671     }
00672 }
00673 
00674 /*
00675 ** RB_CalcWaveColor
00676 */
00677 void RB_CalcWaveColor( const waveForm_t *wf, unsigned char *dstColors )
00678 {
00679     int i;
00680     int v;
00681     float glow;
00682     int *colors = ( int * ) dstColors;
00683     byte    color[4];
00684 
00685 
00686   if ( wf->func == GF_NOISE ) {
00687         glow = wf->base + R_NoiseGet4f( 0, 0, 0, ( tess.shaderTime + wf->phase ) * wf->frequency ) * wf->amplitude;
00688     } else {
00689         glow = EvalWaveForm( wf ) * tr.identityLight;
00690     }
00691     
00692     if ( glow < 0 ) {
00693         glow = 0;
00694     }
00695     else if ( glow > 1 ) {
00696         glow = 1;
00697     }
00698 
00699     v = myftol( 255 * glow );
00700     color[0] = color[1] = color[2] = v;
00701     color[3] = 255;
00702     v = *(int *)color;
00703     
00704     for ( i = 0; i < tess.numVertexes; i++, colors++ ) {
00705         *colors = v;
00706     }
00707 }
00708 
00709 /*
00710 ** RB_CalcWaveAlpha
00711 */
00712 void RB_CalcWaveAlpha( const waveForm_t *wf, unsigned char *dstColors )
00713 {
00714     int i;
00715     int v;
00716     float glow;
00717 
00718     glow = EvalWaveFormClamped( wf );
00719 
00720     v = 255 * glow;
00721 
00722     for ( i = 0; i < tess.numVertexes; i++, dstColors += 4 )
00723     {
00724         dstColors[3] = v;
00725     }
00726 }
00727 
00728 /*
00729 ** RB_CalcModulateColorsByFog
00730 */
00731 void RB_CalcModulateColorsByFog( unsigned char *colors ) {
00732     int     i;
00733     float   texCoords[SHADER_MAX_VERTEXES][2];
00734 
00735     // calculate texcoords so we can derive density
00736     // this is not wasted, because it would only have
00737     // been previously called if the surface was opaque
00738     RB_CalcFogTexCoords( texCoords[0] );
00739 
00740     for ( i = 0; i < tess.numVertexes; i++, colors += 4 ) {
00741         float f = 1.0 - R_FogFactor( texCoords[i][0], texCoords[i][1] );
00742         colors[0] *= f;
00743         colors[1] *= f;
00744         colors[2] *= f;
00745     }
00746 }
00747 
00748 /*
00749 ** RB_CalcModulateAlphasByFog
00750 */
00751 void RB_CalcModulateAlphasByFog( unsigned char *colors ) {
00752     int     i;
00753     float   texCoords[SHADER_MAX_VERTEXES][2];
00754 
00755     // calculate texcoords so we can derive density
00756     // this is not wasted, because it would only have
00757     // been previously called if the surface was opaque
00758     RB_CalcFogTexCoords( texCoords[0] );
00759 
00760     for ( i = 0; i < tess.numVertexes; i++, colors += 4 ) {
00761         float f = 1.0 - R_FogFactor( texCoords[i][0], texCoords[i][1] );
00762         colors[3] *= f;
00763     }
00764 }
00765 
00766 /*
00767 ** RB_CalcModulateRGBAsByFog
00768 */
00769 void RB_CalcModulateRGBAsByFog( unsigned char *colors ) {
00770     int     i;
00771     float   texCoords[SHADER_MAX_VERTEXES][2];
00772 
00773     // calculate texcoords so we can derive density
00774     // this is not wasted, because it would only have
00775     // been previously called if the surface was opaque
00776     RB_CalcFogTexCoords( texCoords[0] );
00777 
00778     for ( i = 0; i < tess.numVertexes; i++, colors += 4 ) {
00779         float f = 1.0 - R_FogFactor( texCoords[i][0], texCoords[i][1] );
00780         colors[0] *= f;
00781         colors[1] *= f;
00782         colors[2] *= f;
00783         colors[3] *= f;
00784     }
00785 }
00786 
00787 
00788 /*
00789 ====================================================================
00790 
00791 TEX COORDS
00792 
00793 ====================================================================
00794 */
00795 
00796 /*
00797 ========================
00798 RB_CalcFogTexCoords
00799 
00800 To do the clipped fog plane really correctly, we should use
00801 projected textures, but I don't trust the drivers and it
00802 doesn't fit our shader data.
00803 ========================
00804 */
00805 void RB_CalcFogTexCoords( float *st ) {
00806     int         i;
00807     float       *v;
00808     float       s, t;
00809     float       eyeT;
00810     qboolean    eyeOutside;
00811     fog_t       *fog;
00812     vec3_t      local;
00813     vec4_t      fogDistanceVector, fogDepthVector;
00814 
00815     fog = tr.world->fogs + tess.fogNum;
00816 
00817     // all fogging distance is based on world Z units
00818     VectorSubtract( backEnd.or.origin, backEnd.viewParms.or.origin, local );
00819     fogDistanceVector[0] = -backEnd.or.modelMatrix[2];
00820     fogDistanceVector[1] = -backEnd.or.modelMatrix[6];
00821     fogDistanceVector[2] = -backEnd.or.modelMatrix[10];
00822     fogDistanceVector[3] = DotProduct( local, backEnd.viewParms.or.axis[0] );
00823 
00824     // scale the fog vectors based on the fog's thickness
00825     fogDistanceVector[0] *= fog->tcScale;
00826     fogDistanceVector[1] *= fog->tcScale;
00827     fogDistanceVector[2] *= fog->tcScale;
00828     fogDistanceVector[3] *= fog->tcScale;
00829 
00830     // rotate the gradient vector for this orientation
00831     if ( fog->hasSurface ) {
00832         fogDepthVector[0] = fog->surface[0] * backEnd.or.axis[0][0] + 
00833             fog->surface[1] * backEnd.or.axis[0][1] + fog->surface[2] * backEnd.or.axis[0][2];
00834         fogDepthVector[1] = fog->surface[0] * backEnd.or.axis[1][0] + 
00835             fog->surface[1] * backEnd.or.axis[1][1] + fog->surface[2] * backEnd.or.axis[1][2];
00836         fogDepthVector[2] = fog->surface[0] * backEnd.or.axis[2][0] + 
00837             fog->surface[1] * backEnd.or.axis[2][1] + fog->surface[2] * backEnd.or.axis[2][2];
00838         fogDepthVector[3] = -fog->surface[3] + DotProduct( backEnd.or.origin, fog->surface );
00839 
00840         eyeT = DotProduct( backEnd.or.viewOrigin, fogDepthVector ) + fogDepthVector[3];
00841     } else {
00842         eyeT = 1;   // non-surface fog always has eye inside
00843     }
00844 
00845     // see if the viewpoint is outside
00846     // this is needed for clipping distance even for constant fog
00847 
00848     if ( eyeT < 0 ) {
00849         eyeOutside = qtrue;
00850     } else {
00851         eyeOutside = qfalse;
00852     }
00853 
00854     fogDistanceVector[3] += 1.0/512;
00855 
00856     // calculate density for each point
00857     for (i = 0, v = tess.xyz[0] ; i < tess.numVertexes ; i++, v += 4) {
00858         // calculate the length in fog
00859         s = DotProduct( v, fogDistanceVector ) + fogDistanceVector[3];
00860         t = DotProduct( v, fogDepthVector ) + fogDepthVector[3];
00861 
00862         // partially clipped fogs use the T axis        
00863         if ( eyeOutside ) {
00864             if ( t < 1.0 ) {
00865                 t = 1.0/32; // point is outside, so no fogging
00866             } else {
00867                 t = 1.0/32 + 30.0/32 * t / ( t - eyeT );    // cut the distance at the fog plane
00868             }
00869         } else {
00870             if ( t < 0 ) {
00871                 t = 1.0/32; // point is outside, so no fogging
00872             } else {
00873                 t = 31.0/32;
00874             }
00875         }
00876 
00877         st[0] = s;
00878         st[1] = t;
00879         st += 2;
00880     }
00881 }
00882 
00883 
00884 
00885 /*
00886 ** RB_CalcEnvironmentTexCoords
00887 */
00888 void RB_CalcEnvironmentTexCoords( float *st ) 
00889 {
00890     int         i;
00891     float       *v, *normal;
00892     vec3_t      viewer, reflected;
00893     float       d;
00894 
00895     v = tess.xyz[0];
00896     normal = tess.normal[0];
00897 
00898     for (i = 0 ; i < tess.numVertexes ; i++, v += 4, normal += 4, st += 2 ) 
00899     {
00900         VectorSubtract (backEnd.or.viewOrigin, v, viewer);
00901         VectorNormalizeFast (viewer);
00902 
00903         d = DotProduct (normal, viewer);
00904 
00905         reflected[0] = normal[0]*2*d - viewer[0];
00906         reflected[1] = normal[1]*2*d - viewer[1];
00907         reflected[2] = normal[2]*2*d - viewer[2];
00908 
00909         st[0] = 0.5 + reflected[1] * 0.5;
00910         st[1] = 0.5 - reflected[2] * 0.5;
00911     }
00912 }
00913 
00914 /*
00915 ** RB_CalcTurbulentTexCoords
00916 */
00917 void RB_CalcTurbulentTexCoords( const waveForm_t *wf, float *st )
00918 {
00919     int i;
00920     float now;
00921 
00922     now = ( wf->phase + tess.shaderTime * wf->frequency );
00923 
00924     for ( i = 0; i < tess.numVertexes; i++, st += 2 )
00925     {
00926         float s = st[0];
00927         float t = st[1];
00928 
00929         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;
00930         st[1] = t + tr.sinTable[ ( ( int ) ( ( tess.xyz[i][1] * 1.0/128 * 0.125 + now ) * FUNCTABLE_SIZE ) ) & ( FUNCTABLE_MASK ) ] * wf->amplitude;
00931     }
00932 }
00933 
00934 /*
00935 ** RB_CalcScaleTexCoords
00936 */
00937 void RB_CalcScaleTexCoords( const float scale[2], float *st )
00938 {
00939     int i;
00940 
00941     for ( i = 0; i < tess.numVertexes; i++, st += 2 )
00942     {
00943         st[0] *= scale[0];
00944         st[1] *= scale[1];
00945     }
00946 }
00947 
00948 /*
00949 ** RB_CalcScrollTexCoords
00950 */
00951 void RB_CalcScrollTexCoords( const float scrollSpeed[2], float *st )
00952 {
00953     int i;
00954     float timeScale = tess.shaderTime;
00955     float adjustedScrollS, adjustedScrollT;
00956 
00957     adjustedScrollS = scrollSpeed[0] * timeScale;
00958     adjustedScrollT = scrollSpeed[1] * timeScale;
00959 
00960     // clamp so coordinates don't continuously get larger, causing problems
00961     // with hardware limits
00962     adjustedScrollS = adjustedScrollS - floor( adjustedScrollS );
00963     adjustedScrollT = adjustedScrollT - floor( adjustedScrollT );
00964 
00965     for ( i = 0; i < tess.numVertexes; i++, st += 2 )
00966     {
00967         st[0] += adjustedScrollS;
00968         st[1] += adjustedScrollT;
00969     }
00970 }
00971 
00972 /*
00973 ** RB_CalcTransformTexCoords
00974 */
00975 void RB_CalcTransformTexCoords( const texModInfo_t *tmi, float *st  )
00976 {
00977     int i;
00978 
00979     for ( i = 0; i < tess.numVertexes; i++, st += 2 )
00980     {
00981         float s = st[0];
00982         float t = st[1];
00983 
00984         st[0] = s * tmi->matrix[0][0] + t * tmi->matrix[1][0] + tmi->translate[0];
00985         st[1] = s * tmi->matrix[0][1] + t * tmi->matrix[1][1] + tmi->translate[1];
00986     }
00987 }
00988 
00989 /*
00990 ** RB_CalcRotateTexCoords
00991 */
00992 void RB_CalcRotateTexCoords( float degsPerSecond, float *st )
00993 {
00994     float timeScale = tess.shaderTime;
00995     float degs;
00996     int index;
00997     float sinValue, cosValue;
00998     texModInfo_t tmi;
00999 
01000     degs = -degsPerSecond * timeScale;
01001     index = degs * ( FUNCTABLE_SIZE / 360.0f );
01002 
01003     sinValue = tr.sinTable[ index & FUNCTABLE_MASK ];
01004     cosValue = tr.sinTable[ ( index + FUNCTABLE_SIZE / 4 ) & FUNCTABLE_MASK ];
01005 
01006     tmi.matrix[0][0] = cosValue;
01007     tmi.matrix[1][0] = -sinValue;
01008     tmi.translate[0] = 0.5 - 0.5 * cosValue + 0.5 * sinValue;
01009 
01010     tmi.matrix[0][1] = sinValue;
01011     tmi.matrix[1][1] = cosValue;
01012     tmi.translate[1] = 0.5 - 0.5 * sinValue - 0.5 * cosValue;
01013 
01014     RB_CalcTransformTexCoords( &tmi, st );
01015 }
01016 
01017 
01018 
01019 
01020 
01021 
01022 #if id386 && !( (defined __linux__ || defined __FreeBSD__ ) && (defined __i386__ ) ) // rb010123
01023 
01024 long myftol( float f ) {
01025     static int tmp;
01026     __asm fld f
01027     __asm fistp tmp
01028     __asm mov eax, tmp
01029 }
01030 
01031 #endif
01032 
01033 /*
01034 ** RB_CalcSpecularAlpha
01035 **
01036 ** Calculates specular coefficient and places it in the alpha channel
01037 */
01038 vec3_t lightOrigin = { -960, 1980, 96 };        // FIXME: track dynamically
01039 
01040 void RB_CalcSpecularAlpha( unsigned char *alphas ) {
01041     int         i;
01042     float       *v, *normal;
01043     vec3_t      viewer,  reflected;
01044     float       l, d;
01045     int         b;
01046     vec3_t      lightDir;
01047     int         numVertexes;
01048 
01049     v = tess.xyz[0];
01050     normal = tess.normal[0];
01051 
01052     alphas += 3;
01053 
01054     numVertexes = tess.numVertexes;
01055     for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4, alphas += 4) {
01056         float ilength;
01057 
01058         VectorSubtract( lightOrigin, v, lightDir );
01059 //      ilength = Q_rsqrt( DotProduct( lightDir, lightDir ) );
01060         VectorNormalizeFast( lightDir );
01061 
01062         // calculate the specular color
01063         d = DotProduct (normal, lightDir);
01064 //      d *= ilength;
01065 
01066         // we don't optimize for the d < 0 case since this tends to
01067         // cause visual artifacts such as faceted "snapping"
01068         reflected[0] = normal[0]*2*d - lightDir[0];
01069         reflected[1] = normal[1]*2*d - lightDir[1];
01070         reflected[2] = normal[2]*2*d - lightDir[2];
01071 
01072         VectorSubtract (backEnd.or.viewOrigin, v, viewer);
01073         ilength = Q_rsqrt( DotProduct( viewer, viewer ) );
01074         l = DotProduct (reflected, viewer);
01075         l *= ilength;
01076 
01077         if (l < 0) {
01078             b = 0;
01079         } else {
01080             l = l*l;
01081             l = l*l;
01082             b = l * 255;
01083             if (b > 255) {
01084                 b = 255;
01085             }
01086         }
01087 
01088         *alphas = b;
01089     }
01090 }
01091 
01092 /*
01093 ** RB_CalcDiffuseColor
01094 **
01095 ** The basic vertex lighting calc
01096 */
01097 void RB_CalcDiffuseColor( unsigned char *colors )
01098 {
01099     int             i, j;
01100     float           *v, *normal;
01101     float           incoming;
01102     trRefEntity_t   *ent;
01103     int             ambientLightInt;
01104     vec3_t          ambientLight;
01105     vec3_t          lightDir;
01106     vec3_t          directedLight;
01107     int             numVertexes;
01108 #if idppc_altivec
01109     vector unsigned char vSel = (vector unsigned char)(0x00, 0x00, 0x00, 0xff,
01110                                0x00, 0x00, 0x00, 0xff,
01111                                0x00, 0x00, 0x00, 0xff,
01112                                0x00, 0x00, 0x00, 0xff);
01113     vector float ambientLightVec;
01114     vector float directedLightVec;
01115     vector float lightDirVec;
01116     vector float normalVec0, normalVec1;
01117     vector float incomingVec0, incomingVec1, incomingVec2;
01118     vector float zero, jVec;
01119     vector signed int jVecInt;
01120     vector signed short jVecShort;
01121     vector unsigned char jVecChar, normalPerm;
01122 #endif
01123     ent = backEnd.currentEntity;
01124     ambientLightInt = ent->ambientLightInt;
01125 #if idppc_altivec
01126     // A lot of this could be simplified if we made sure
01127     // entities light info was 16-byte aligned.
01128     jVecChar = vec_lvsl(0, ent->ambientLight);
01129     ambientLightVec = vec_ld(0, (vector float *)ent->ambientLight);
01130     jVec = vec_ld(11, (vector float *)ent->ambientLight);
01131     ambientLightVec = vec_perm(ambientLightVec,jVec,jVecChar);
01132 
01133     jVecChar = vec_lvsl(0, ent->directedLight);
01134     directedLightVec = vec_ld(0,(vector float *)ent->directedLight);
01135     jVec = vec_ld(11,(vector float *)ent->directedLight);
01136     directedLightVec = vec_perm(directedLightVec,jVec,jVecChar);     
01137 
01138     jVecChar = vec_lvsl(0, ent->lightDir);
01139     lightDirVec = vec_ld(0,(vector float *)ent->lightDir);
01140     jVec = vec_ld(11,(vector float *)ent->lightDir);
01141     lightDirVec = vec_perm(lightDirVec,jVec,jVecChar);   
01142 
01143     zero = (vector float)vec_splat_s8(0);
01144     VectorCopy( ent->lightDir, lightDir );
01145 #else
01146     VectorCopy( ent->ambientLight, ambientLight );
01147     VectorCopy( ent->directedLight, directedLight );
01148     VectorCopy( ent->lightDir, lightDir );
01149 #endif
01150 
01151     v = tess.xyz[0];
01152     normal = tess.normal[0];
01153 
01154 #if idppc_altivec
01155     normalPerm = vec_lvsl(0,normal);
01156 #endif
01157     numVertexes = tess.numVertexes;
01158     for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4) {
01159 #if idppc_altivec
01160         normalVec0 = vec_ld(0,(vector float *)normal);
01161         normalVec1 = vec_ld(11,(vector float *)normal);
01162         normalVec0 = vec_perm(normalVec0,normalVec1,normalPerm);
01163         incomingVec0 = vec_madd(normalVec0, lightDirVec, zero);
01164         incomingVec1 = vec_sld(incomingVec0,incomingVec0,4);
01165         incomingVec2 = vec_add(incomingVec0,incomingVec1);
01166         incomingVec1 = vec_sld(incomingVec1,incomingVec1,4);
01167         incomingVec2 = vec_add(incomingVec2,incomingVec1);
01168         incomingVec0 = vec_splat(incomingVec2,0);
01169         incomingVec0 = vec_max(incomingVec0,zero);
01170         normalPerm = vec_lvsl(12,normal);
01171         jVec = vec_madd(incomingVec0, directedLightVec, ambientLightVec);
01172         jVecInt = vec_cts(jVec,0);  // RGBx
01173         jVecShort = vec_pack(jVecInt,jVecInt);      // RGBxRGBx
01174         jVecChar = vec_packsu(jVecShort,jVecShort); // RGBxRGBxRGBxRGBx
01175         jVecChar = vec_sel(jVecChar,vSel,vSel);     // RGBARGBARGBARGBA replace alpha with 255
01176         vec_ste((vector unsigned int)jVecChar,0,(unsigned int *)&colors[i*4]);  // store color
01177 #else
01178         incoming = DotProduct (normal, lightDir);
01179         if ( incoming <= 0 ) {
01180             *(int *)&colors[i*4] = ambientLightInt;
01181             continue;
01182         } 
01183         j = myftol( ambientLight[0] + incoming * directedLight[0] );
01184         if ( j > 255 ) {
01185             j = 255;
01186         }
01187         colors[i*4+0] = j;
01188 
01189         j = myftol( ambientLight[1] + incoming * directedLight[1] );
01190         if ( j > 255 ) {
01191             j = 255;
01192         }
01193         colors[i*4+1] = j;
01194 
01195         j = myftol( ambientLight[2] + incoming * directedLight[2] );
01196         if ( j > 255 ) {
01197             j = 255;
01198         }
01199         colors[i*4+2] = j;
01200 
01201         colors[i*4+3] = 255;
01202 #endif
01203     }
01204 }
01205 

Generated on Thu Aug 25 12:37:54 2005 for Quake III Arena by  doxygen 1.3.9.1