00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "tr_local.h"
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 static void APIENTRY R_ArrayElementDiscrete( GLint index ) {
00041 qglColor4ubv( tess.svars.colors[ index ] );
00042 if ( glState.currenttmu ) {
00043 qglMultiTexCoord2fARB( 0, tess.svars.texcoords[ 0 ][ index ][0], tess.svars.texcoords[ 0 ][ index ][1] );
00044 qglMultiTexCoord2fARB( 1, tess.svars.texcoords[ 1 ][ index ][0], tess.svars.texcoords[ 1 ][ index ][1] );
00045 } else {
00046 qglTexCoord2fv( tess.svars.texcoords[ 0 ][ index ] );
00047 }
00048 qglVertex3fv( tess.xyz[ index ] );
00049 }
00050
00051
00052
00053
00054
00055
00056
00057 static int c_vertexes;
00058 static int c_begins;
00059 static void R_DrawStripElements( int numIndexes, const glIndex_t *indexes, void ( APIENTRY *element )(GLint) ) {
00060 int i;
00061 int last[3] = { -1, -1, -1 };
00062 qboolean even;
00063
00064 c_begins++;
00065
00066 if ( numIndexes <= 0 ) {
00067 return;
00068 }
00069
00070 qglBegin( GL_TRIANGLE_STRIP );
00071
00072
00073 element( indexes[0] );
00074 element( indexes[1] );
00075 element( indexes[2] );
00076 c_vertexes += 3;
00077
00078 last[0] = indexes[0];
00079 last[1] = indexes[1];
00080 last[2] = indexes[2];
00081
00082 even = qfalse;
00083
00084 for ( i = 3; i < numIndexes; i += 3 )
00085 {
00086
00087 if ( !even )
00088 {
00089
00090 if ( ( indexes[i+0] == last[2] ) && ( indexes[i+1] == last[1] ) )
00091 {
00092 element( indexes[i+2] );
00093 c_vertexes++;
00094 assert( indexes[i+2] < tess.numVertexes );
00095 even = qtrue;
00096 }
00097
00098
00099 else
00100 {
00101 qglEnd();
00102
00103 qglBegin( GL_TRIANGLE_STRIP );
00104 c_begins++;
00105
00106 element( indexes[i+0] );
00107 element( indexes[i+1] );
00108 element( indexes[i+2] );
00109
00110 c_vertexes += 3;
00111
00112 even = qfalse;
00113 }
00114 }
00115 else
00116 {
00117
00118 if ( ( last[2] == indexes[i+1] ) && ( last[0] == indexes[i+0] ) )
00119 {
00120 element( indexes[i+2] );
00121 c_vertexes++;
00122
00123 even = qfalse;
00124 }
00125
00126
00127 else
00128 {
00129 qglEnd();
00130
00131 qglBegin( GL_TRIANGLE_STRIP );
00132 c_begins++;
00133
00134 element( indexes[i+0] );
00135 element( indexes[i+1] );
00136 element( indexes[i+2] );
00137 c_vertexes += 3;
00138
00139 even = qfalse;
00140 }
00141 }
00142
00143
00144 last[0] = indexes[i+0];
00145 last[1] = indexes[i+1];
00146 last[2] = indexes[i+2];
00147 }
00148
00149 qglEnd();
00150 }
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 static void R_DrawElements( int numIndexes, const glIndex_t *indexes ) {
00164 int primitives;
00165
00166 primitives = r_primitives->integer;
00167
00168
00169 if ( primitives == 0 ) {
00170 if ( qglLockArraysEXT ) {
00171 primitives = 2;
00172 } else {
00173 primitives = 1;
00174 }
00175 }
00176
00177
00178 if ( primitives == 2 ) {
00179 qglDrawElements( GL_TRIANGLES,
00180 numIndexes,
00181 GL_INDEX_TYPE,
00182 indexes );
00183 return;
00184 }
00185
00186 if ( primitives == 1 ) {
00187 R_DrawStripElements( numIndexes, indexes, qglArrayElement );
00188 return;
00189 }
00190
00191 if ( primitives == 3 ) {
00192 R_DrawStripElements( numIndexes, indexes, R_ArrayElementDiscrete );
00193 return;
00194 }
00195
00196
00197 }
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208 shaderCommands_t tess;
00209 static qboolean setArraysOnce;
00210
00211
00212
00213
00214
00215
00216
00217 static void R_BindAnimatedImage( textureBundle_t *bundle ) {
00218 int index;
00219
00220 if ( bundle->isVideoMap ) {
00221 ri.CIN_RunCinematic(bundle->videoMapHandle);
00222 ri.CIN_UploadCinematic(bundle->videoMapHandle);
00223 return;
00224 }
00225
00226 if ( bundle->numImageAnimations <= 1 ) {
00227 GL_Bind( bundle->image[0] );
00228 return;
00229 }
00230
00231
00232
00233 index = myftol( tess.shaderTime * bundle->imageAnimationSpeed * FUNCTABLE_SIZE );
00234 index >>= FUNCTABLE_SIZE2;
00235
00236 if ( index < 0 ) {
00237 index = 0;
00238 }
00239 index %= bundle->numImageAnimations;
00240
00241 GL_Bind( bundle->image[ index ] );
00242 }
00243
00244
00245
00246
00247
00248
00249
00250
00251 static void DrawTris (shaderCommands_t *input) {
00252 GL_Bind( tr.whiteImage );
00253 qglColor3f (1,1,1);
00254
00255 GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE );
00256 qglDepthRange( 0, 0 );
00257
00258 qglDisableClientState (GL_COLOR_ARRAY);
00259 qglDisableClientState (GL_TEXTURE_COORD_ARRAY);
00260
00261 qglVertexPointer (3, GL_FLOAT, 16, input->xyz);
00262
00263 if (qglLockArraysEXT) {
00264 qglLockArraysEXT(0, input->numVertexes);
00265 GLimp_LogComment( "glLockArraysEXT\n" );
00266 }
00267
00268 R_DrawElements( input->numIndexes, input->indexes );
00269
00270 if (qglUnlockArraysEXT) {
00271 qglUnlockArraysEXT();
00272 GLimp_LogComment( "glUnlockArraysEXT\n" );
00273 }
00274 qglDepthRange( 0, 1 );
00275 }
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285 static void DrawNormals (shaderCommands_t *input) {
00286 int i;
00287 vec3_t temp;
00288
00289 GL_Bind( tr.whiteImage );
00290 qglColor3f (1,1,1);
00291 qglDepthRange( 0, 0 );
00292 GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE );
00293
00294 qglBegin (GL_LINES);
00295 for (i = 0 ; i < input->numVertexes ; i++) {
00296 qglVertex3fv (input->xyz[i]);
00297 VectorMA (input->xyz[i], 2, input->normal[i], temp);
00298 qglVertex3fv (temp);
00299 }
00300 qglEnd ();
00301
00302 qglDepthRange( 0, 1 );
00303 }
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314 void RB_BeginSurface( shader_t *shader, int fogNum ) {
00315
00316 shader_t *state = (shader->remappedShader) ? shader->remappedShader : shader;
00317
00318 tess.numIndexes = 0;
00319 tess.numVertexes = 0;
00320 tess.shader = state;
00321 tess.fogNum = fogNum;
00322 tess.dlightBits = 0;
00323 tess.xstages = state->stages;
00324 tess.numPasses = state->numUnfoggedPasses;
00325 tess.currentStageIteratorFunc = state->optimalStageIteratorFunc;
00326
00327 tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;
00328 if (tess.shader->clampTime && tess.shaderTime >= tess.shader->clampTime) {
00329 tess.shaderTime = tess.shader->clampTime;
00330 }
00331
00332
00333 }
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345 static void DrawMultitextured( shaderCommands_t *input, int stage ) {
00346 shaderStage_t *pStage;
00347
00348 pStage = tess.xstages[stage];
00349
00350 GL_State( pStage->stateBits );
00351
00352
00353
00354 if ( backEnd.viewParms.isPortal ) {
00355 qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
00356 }
00357
00358
00359
00360
00361 GL_SelectTexture( 0 );
00362 qglTexCoordPointer( 2, GL_FLOAT, 0, input->svars.texcoords[0] );
00363 R_BindAnimatedImage( &pStage->bundle[0] );
00364
00365
00366
00367
00368 GL_SelectTexture( 1 );
00369 qglEnable( GL_TEXTURE_2D );
00370 qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
00371
00372 if ( r_lightmap->integer ) {
00373 GL_TexEnv( GL_REPLACE );
00374 } else {
00375 GL_TexEnv( tess.shader->multitextureEnv );
00376 }
00377
00378 qglTexCoordPointer( 2, GL_FLOAT, 0, input->svars.texcoords[1] );
00379
00380 R_BindAnimatedImage( &pStage->bundle[1] );
00381
00382 R_DrawElements( input->numIndexes, input->indexes );
00383
00384
00385
00386
00387
00388 qglDisable( GL_TEXTURE_2D );
00389
00390 GL_SelectTexture( 0 );
00391 }
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402 static void ProjectDlightTexture( void ) {
00403 int i, l;
00404 #if idppc_altivec
00405 vec_t origin0, origin1, origin2;
00406 float texCoords0, texCoords1;
00407 vector float floatColorVec0, floatColorVec1;
00408 vector float modulateVec, colorVec, zero;
00409 vector short colorShort;
00410 vector signed int colorInt;
00411 vector unsigned char floatColorVecPerm, modulatePerm, colorChar;
00412 vector unsigned char vSel = (vector unsigned char)(0x00, 0x00, 0x00, 0xff,
00413 0x00, 0x00, 0x00, 0xff,
00414 0x00, 0x00, 0x00, 0xff,
00415 0x00, 0x00, 0x00, 0xff);
00416 #else
00417 vec3_t origin;
00418 #endif
00419 float *texCoords;
00420 byte *colors;
00421 byte clipBits[SHADER_MAX_VERTEXES];
00422 MAC_STATIC float texCoordsArray[SHADER_MAX_VERTEXES][2];
00423 byte colorArray[SHADER_MAX_VERTEXES][4];
00424 unsigned hitIndexes[SHADER_MAX_INDEXES];
00425 int numIndexes;
00426 float scale;
00427 float radius;
00428 vec3_t floatColor;
00429 float modulate;
00430
00431 if ( !backEnd.refdef.num_dlights ) {
00432 return;
00433 }
00434
00435 #if idppc_altivec
00436
00437
00438 floatColorVecPerm = vec_lvsl(0,(float *)floatColor);
00439 modulatePerm = vec_lvsl(0,(float *)&modulate);
00440 modulatePerm = (vector unsigned char)vec_splat((vector unsigned int)modulatePerm,0);
00441 zero = (vector float)vec_splat_s8(0);
00442 #endif
00443
00444 for ( l = 0 ; l < backEnd.refdef.num_dlights ; l++ ) {
00445 dlight_t *dl;
00446
00447 if ( !( tess.dlightBits & ( 1 << l ) ) ) {
00448 continue;
00449 }
00450 texCoords = texCoordsArray[0];
00451 colors = colorArray[0];
00452
00453 dl = &backEnd.refdef.dlights[l];
00454 #if idppc_altivec
00455 origin0 = dl->transformed[0];
00456 origin1 = dl->transformed[1];
00457 origin2 = dl->transformed[2];
00458 #else
00459 VectorCopy( dl->transformed, origin );
00460 #endif
00461 radius = dl->radius;
00462 scale = 1.0f / radius;
00463
00464 floatColor[0] = dl->color[0] * 255.0f;
00465 floatColor[1] = dl->color[1] * 255.0f;
00466 floatColor[2] = dl->color[2] * 255.0f;
00467 #if idppc_altivec
00468 floatColorVec0 = vec_ld(0, floatColor);
00469 floatColorVec1 = vec_ld(11, floatColor);
00470 floatColorVec0 = vec_perm(floatColorVec0,floatColorVec0,floatColorVecPerm);
00471 #endif
00472 for ( i = 0 ; i < tess.numVertexes ; i++, texCoords += 2, colors += 4 ) {
00473 #if idppc_altivec
00474 vec_t dist0, dist1, dist2;
00475 #else
00476 vec3_t dist;
00477 #endif
00478 int clip;
00479
00480 backEnd.pc.c_dlightVertexes++;
00481
00482 #if idppc_altivec
00483
00484 dist0 = origin0 - tess.xyz[i][0];
00485 dist1 = origin1 - tess.xyz[i][1];
00486 dist2 = origin2 - tess.xyz[i][2];
00487 texCoords0 = 0.5f + dist0 * scale;
00488 texCoords1 = 0.5f + dist1 * scale;
00489
00490 clip = 0;
00491 if ( texCoords0 < 0.0f ) {
00492 clip |= 1;
00493 } else if ( texCoords0 > 1.0f ) {
00494 clip |= 2;
00495 }
00496 if ( texCoords1 < 0.0f ) {
00497 clip |= 4;
00498 } else if ( texCoords1 > 1.0f ) {
00499 clip |= 8;
00500 }
00501 texCoords[0] = texCoords0;
00502 texCoords[1] = texCoords1;
00503
00504
00505 if ( dist2 > radius ) {
00506 clip |= 16;
00507 modulate = 0.0f;
00508 } else if ( dist2 < -radius ) {
00509 clip |= 32;
00510 modulate = 0.0f;
00511 } else {
00512 dist2 = Q_fabs(dist2);
00513 if ( dist2 < radius * 0.5f ) {
00514 modulate = 1.0f;
00515 } else {
00516 modulate = 2.0f * (radius - dist2) * scale;
00517 }
00518 }
00519 clipBits[i] = clip;
00520
00521 modulateVec = vec_ld(0,(float *)&modulate);
00522 modulateVec = vec_perm(modulateVec,modulateVec,modulatePerm);
00523 colorVec = vec_madd(floatColorVec0,modulateVec,zero);
00524 colorInt = vec_cts(colorVec,0);
00525 colorShort = vec_pack(colorInt,colorInt);
00526 colorChar = vec_packsu(colorShort,colorShort);
00527 colorChar = vec_sel(colorChar,vSel,vSel);
00528 vec_ste((vector unsigned int)colorChar,0,(unsigned int *)colors);
00529 #else
00530 VectorSubtract( origin, tess.xyz[i], dist );
00531 texCoords[0] = 0.5f + dist[0] * scale;
00532 texCoords[1] = 0.5f + dist[1] * scale;
00533
00534 clip = 0;
00535 if ( texCoords[0] < 0.0f ) {
00536 clip |= 1;
00537 } else if ( texCoords[0] > 1.0f ) {
00538 clip |= 2;
00539 }
00540 if ( texCoords[1] < 0.0f ) {
00541 clip |= 4;
00542 } else if ( texCoords[1] > 1.0f ) {
00543 clip |= 8;
00544 }
00545
00546 if ( dist[2] > radius ) {
00547 clip |= 16;
00548 modulate = 0.0f;
00549 } else if ( dist[2] < -radius ) {
00550 clip |= 32;
00551 modulate = 0.0f;
00552 } else {
00553 dist[2] = Q_fabs(dist[2]);
00554 if ( dist[2] < radius * 0.5f ) {
00555 modulate = 1.0f;
00556 } else {
00557 modulate = 2.0f * (radius - dist[2]) * scale;
00558 }
00559 }
00560 clipBits[i] = clip;
00561
00562 colors[0] = myftol(floatColor[0] * modulate);
00563 colors[1] = myftol(floatColor[1] * modulate);
00564 colors[2] = myftol(floatColor[2] * modulate);
00565 colors[3] = 255;
00566 #endif
00567 }
00568
00569
00570 numIndexes = 0;
00571 for ( i = 0 ; i < tess.numIndexes ; i += 3 ) {
00572 int a, b, c;
00573
00574 a = tess.indexes[i];
00575 b = tess.indexes[i+1];
00576 c = tess.indexes[i+2];
00577 if ( clipBits[a] & clipBits[b] & clipBits[c] ) {
00578 continue;
00579 }
00580 hitIndexes[numIndexes] = a;
00581 hitIndexes[numIndexes+1] = b;
00582 hitIndexes[numIndexes+2] = c;
00583 numIndexes += 3;
00584 }
00585
00586 if ( !numIndexes ) {
00587 continue;
00588 }
00589
00590 qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
00591 qglTexCoordPointer( 2, GL_FLOAT, 0, texCoordsArray[0] );
00592
00593 qglEnableClientState( GL_COLOR_ARRAY );
00594 qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, colorArray );
00595
00596 GL_Bind( tr.dlightImage );
00597
00598
00599 if ( dl->additive ) {
00600 GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL );
00601 }
00602 else {
00603 GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL );
00604 }
00605 R_DrawElements( numIndexes, hitIndexes );
00606 backEnd.pc.c_totalIndexes += numIndexes;
00607 backEnd.pc.c_dlightIndexes += numIndexes;
00608 }
00609 }
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619 static void RB_FogPass( void ) {
00620 fog_t *fog;
00621 int i;
00622
00623 qglEnableClientState( GL_COLOR_ARRAY );
00624 qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.svars.colors );
00625
00626 qglEnableClientState( GL_TEXTURE_COORD_ARRAY);
00627 qglTexCoordPointer( 2, GL_FLOAT, 0, tess.svars.texcoords[0] );
00628
00629 fog = tr.world->fogs + tess.fogNum;
00630
00631 for ( i = 0; i < tess.numVertexes; i++ ) {
00632 * ( int * )&tess.svars.colors[i] = fog->colorInt;
00633 }
00634
00635 RB_CalcFogTexCoords( ( float * ) tess.svars.texcoords[0] );
00636
00637 GL_Bind( tr.fogImage );
00638
00639 if ( tess.shader->fogPass == FP_EQUAL ) {
00640 GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_EQUAL );
00641 } else {
00642 GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
00643 }
00644
00645 R_DrawElements( tess.numIndexes, tess.indexes );
00646 }
00647
00648
00649
00650
00651
00652
00653 static void ComputeColors( shaderStage_t *pStage )
00654 {
00655 int i;
00656
00657
00658
00659
00660 switch ( pStage->rgbGen )
00661 {
00662 case CGEN_IDENTITY:
00663 Com_Memset( tess.svars.colors, 0xff, tess.numVertexes * 4 );
00664 break;
00665 default:
00666 case CGEN_IDENTITY_LIGHTING:
00667 Com_Memset( tess.svars.colors, tr.identityLightByte, tess.numVertexes * 4 );
00668 break;
00669 case CGEN_LIGHTING_DIFFUSE:
00670 RB_CalcDiffuseColor( ( unsigned char * ) tess.svars.colors );
00671 break;
00672 case CGEN_EXACT_VERTEX:
00673 Com_Memcpy( tess.svars.colors, tess.vertexColors, tess.numVertexes * sizeof( tess.vertexColors[0] ) );
00674 break;
00675 case CGEN_CONST:
00676 for ( i = 0; i < tess.numVertexes; i++ ) {
00677 *(int *)tess.svars.colors[i] = *(int *)pStage->constantColor;
00678 }
00679 break;
00680 case CGEN_VERTEX:
00681 if ( tr.identityLight == 1 )
00682 {
00683 Com_Memcpy( tess.svars.colors, tess.vertexColors, tess.numVertexes * sizeof( tess.vertexColors[0] ) );
00684 }
00685 else
00686 {
00687 for ( i = 0; i < tess.numVertexes; i++ )
00688 {
00689 tess.svars.colors[i][0] = tess.vertexColors[i][0] * tr.identityLight;
00690 tess.svars.colors[i][1] = tess.vertexColors[i][1] * tr.identityLight;
00691 tess.svars.colors[i][2] = tess.vertexColors[i][2] * tr.identityLight;
00692 tess.svars.colors[i][3] = tess.vertexColors[i][3];
00693 }
00694 }
00695 break;
00696 case CGEN_ONE_MINUS_VERTEX:
00697 if ( tr.identityLight == 1 )
00698 {
00699 for ( i = 0; i < tess.numVertexes; i++ )
00700 {
00701 tess.svars.colors[i][0] = 255 - tess.vertexColors[i][0];
00702 tess.svars.colors[i][1] = 255 - tess.vertexColors[i][1];
00703 tess.svars.colors[i][2] = 255 - tess.vertexColors[i][2];
00704 }
00705 }
00706 else
00707 {
00708 for ( i = 0; i < tess.numVertexes; i++ )
00709 {
00710 tess.svars.colors[i][0] = ( 255 - tess.vertexColors[i][0] ) * tr.identityLight;
00711 tess.svars.colors[i][1] = ( 255 - tess.vertexColors[i][1] ) * tr.identityLight;
00712 tess.svars.colors[i][2] = ( 255 - tess.vertexColors[i][2] ) * tr.identityLight;
00713 }
00714 }
00715 break;
00716 case CGEN_FOG:
00717 {
00718 fog_t *fog;
00719
00720 fog = tr.world->fogs + tess.fogNum;
00721
00722 for ( i = 0; i < tess.numVertexes; i++ ) {
00723 * ( int * )&tess.svars.colors[i] = fog->colorInt;
00724 }
00725 }
00726 break;
00727 case CGEN_WAVEFORM:
00728 RB_CalcWaveColor( &pStage->rgbWave, ( unsigned char * ) tess.svars.colors );
00729 break;
00730 case CGEN_ENTITY:
00731 RB_CalcColorFromEntity( ( unsigned char * ) tess.svars.colors );
00732 break;
00733 case CGEN_ONE_MINUS_ENTITY:
00734 RB_CalcColorFromOneMinusEntity( ( unsigned char * ) tess.svars.colors );
00735 break;
00736 }
00737
00738
00739
00740
00741 switch ( pStage->alphaGen )
00742 {
00743 case AGEN_SKIP:
00744 break;
00745 case AGEN_IDENTITY:
00746 if ( pStage->rgbGen != CGEN_IDENTITY ) {
00747 if ( ( pStage->rgbGen == CGEN_VERTEX && tr.identityLight != 1 ) ||
00748 pStage->rgbGen != CGEN_VERTEX ) {
00749 for ( i = 0; i < tess.numVertexes; i++ ) {
00750 tess.svars.colors[i][3] = 0xff;
00751 }
00752 }
00753 }
00754 break;
00755 case AGEN_CONST:
00756 if ( pStage->rgbGen != CGEN_CONST ) {
00757 for ( i = 0; i < tess.numVertexes; i++ ) {
00758 tess.svars.colors[i][3] = pStage->constantColor[3];
00759 }
00760 }
00761 break;
00762 case AGEN_WAVEFORM:
00763 RB_CalcWaveAlpha( &pStage->alphaWave, ( unsigned char * ) tess.svars.colors );
00764 break;
00765 case AGEN_LIGHTING_SPECULAR:
00766 RB_CalcSpecularAlpha( ( unsigned char * ) tess.svars.colors );
00767 break;
00768 case AGEN_ENTITY:
00769 RB_CalcAlphaFromEntity( ( unsigned char * ) tess.svars.colors );
00770 break;
00771 case AGEN_ONE_MINUS_ENTITY:
00772 RB_CalcAlphaFromOneMinusEntity( ( unsigned char * ) tess.svars.colors );
00773 break;
00774 case AGEN_VERTEX:
00775 if ( pStage->rgbGen != CGEN_VERTEX ) {
00776 for ( i = 0; i < tess.numVertexes; i++ ) {
00777 tess.svars.colors[i][3] = tess.vertexColors[i][3];
00778 }
00779 }
00780 break;
00781 case AGEN_ONE_MINUS_VERTEX:
00782 for ( i = 0; i < tess.numVertexes; i++ )
00783 {
00784 tess.svars.colors[i][3] = 255 - tess.vertexColors[i][3];
00785 }
00786 break;
00787 case AGEN_PORTAL:
00788 {
00789 unsigned char alpha;
00790
00791 for ( i = 0; i < tess.numVertexes; i++ )
00792 {
00793 float len;
00794 vec3_t v;
00795
00796 VectorSubtract( tess.xyz[i], backEnd.viewParms.or.origin, v );
00797 len = VectorLength( v );
00798
00799 len /= tess.shader->portalRange;
00800
00801 if ( len < 0 )
00802 {
00803 alpha = 0;
00804 }
00805 else if ( len > 1 )
00806 {
00807 alpha = 0xff;
00808 }
00809 else
00810 {
00811 alpha = len * 0xff;
00812 }
00813
00814 tess.svars.colors[i][3] = alpha;
00815 }
00816 }
00817 break;
00818 }
00819
00820
00821
00822
00823 if ( tess.fogNum )
00824 {
00825 switch ( pStage->adjustColorsForFog )
00826 {
00827 case ACFF_MODULATE_RGB:
00828 RB_CalcModulateColorsByFog( ( unsigned char * ) tess.svars.colors );
00829 break;
00830 case ACFF_MODULATE_ALPHA:
00831 RB_CalcModulateAlphasByFog( ( unsigned char * ) tess.svars.colors );
00832 break;
00833 case ACFF_MODULATE_RGBA:
00834 RB_CalcModulateRGBAsByFog( ( unsigned char * ) tess.svars.colors );
00835 break;
00836 case ACFF_NONE:
00837 break;
00838 }
00839 }
00840 }
00841
00842
00843
00844
00845
00846
00847 static void ComputeTexCoords( shaderStage_t *pStage ) {
00848 int i;
00849 int b;
00850
00851 for ( b = 0; b < NUM_TEXTURE_BUNDLES; b++ ) {
00852 int tm;
00853
00854
00855
00856
00857 switch ( pStage->bundle[b].tcGen )
00858 {
00859 case TCGEN_IDENTITY:
00860 Com_Memset( tess.svars.texcoords[b], 0, sizeof( float ) * 2 * tess.numVertexes );
00861 break;
00862 case TCGEN_TEXTURE:
00863 for ( i = 0 ; i < tess.numVertexes ; i++ ) {
00864 tess.svars.texcoords[b][i][0] = tess.texCoords[i][0][0];
00865 tess.svars.texcoords[b][i][1] = tess.texCoords[i][0][1];
00866 }
00867 break;
00868 case TCGEN_LIGHTMAP:
00869 for ( i = 0 ; i < tess.numVertexes ; i++ ) {
00870 tess.svars.texcoords[b][i][0] = tess.texCoords[i][1][0];
00871 tess.svars.texcoords[b][i][1] = tess.texCoords[i][1][1];
00872 }
00873 break;
00874 case TCGEN_VECTOR:
00875 for ( i = 0 ; i < tess.numVertexes ; i++ ) {
00876 tess.svars.texcoords[b][i][0] = DotProduct( tess.xyz[i], pStage->bundle[b].tcGenVectors[0] );
00877 tess.svars.texcoords[b][i][1] = DotProduct( tess.xyz[i], pStage->bundle[b].tcGenVectors[1] );
00878 }
00879 break;
00880 case TCGEN_FOG:
00881 RB_CalcFogTexCoords( ( float * ) tess.svars.texcoords[b] );
00882 break;
00883 case TCGEN_ENVIRONMENT_MAPPED:
00884 RB_CalcEnvironmentTexCoords( ( float * ) tess.svars.texcoords[b] );
00885 break;
00886 case TCGEN_BAD:
00887 return;
00888 }
00889
00890
00891
00892
00893 for ( tm = 0; tm < pStage->bundle[b].numTexMods ; tm++ ) {
00894 switch ( pStage->bundle[b].texMods[tm].type )
00895 {
00896 case TMOD_NONE:
00897 tm = TR_MAX_TEXMODS;
00898 break;
00899
00900 case TMOD_TURBULENT:
00901 RB_CalcTurbulentTexCoords( &pStage->bundle[b].texMods[tm].wave,
00902 ( float * ) tess.svars.texcoords[b] );
00903 break;
00904
00905 case TMOD_ENTITY_TRANSLATE:
00906 RB_CalcScrollTexCoords( backEnd.currentEntity->e.shaderTexCoord,
00907 ( float * ) tess.svars.texcoords[b] );
00908 break;
00909
00910 case TMOD_SCROLL:
00911 RB_CalcScrollTexCoords( pStage->bundle[b].texMods[tm].scroll,
00912 ( float * ) tess.svars.texcoords[b] );
00913 break;
00914
00915 case TMOD_SCALE:
00916 RB_CalcScaleTexCoords( pStage->bundle[b].texMods[tm].scale,
00917 ( float * ) tess.svars.texcoords[b] );
00918 break;
00919
00920 case TMOD_STRETCH:
00921 RB_CalcStretchTexCoords( &pStage->bundle[b].texMods[tm].wave,
00922 ( float * ) tess.svars.texcoords[b] );
00923 break;
00924
00925 case TMOD_TRANSFORM:
00926 RB_CalcTransformTexCoords( &pStage->bundle[b].texMods[tm],
00927 ( float * ) tess.svars.texcoords[b] );
00928 break;
00929
00930 case TMOD_ROTATE:
00931 RB_CalcRotateTexCoords( pStage->bundle[b].texMods[tm].rotateSpeed,
00932 ( float * ) tess.svars.texcoords[b] );
00933 break;
00934
00935 default:
00936 ri.Error( ERR_DROP, "ERROR: unknown texmod '%d' in shader '%s'\n", pStage->bundle[b].texMods[tm].type, tess.shader->name );
00937 break;
00938 }
00939 }
00940 }
00941 }
00942
00943
00944
00945
00946 static void RB_IterateStagesGeneric( shaderCommands_t *input )
00947 {
00948 int stage;
00949
00950 for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ )
00951 {
00952 shaderStage_t *pStage = tess.xstages[stage];
00953
00954 if ( !pStage )
00955 {
00956 break;
00957 }
00958
00959 ComputeColors( pStage );
00960 ComputeTexCoords( pStage );
00961
00962 if ( !setArraysOnce )
00963 {
00964 qglEnableClientState( GL_COLOR_ARRAY );
00965 qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, input->svars.colors );
00966 }
00967
00968
00969
00970
00971 if ( pStage->bundle[1].image[0] != 0 )
00972 {
00973 DrawMultitextured( input, stage );
00974 }
00975 else
00976 {
00977 if ( !setArraysOnce )
00978 {
00979 qglTexCoordPointer( 2, GL_FLOAT, 0, input->svars.texcoords[0] );
00980 }
00981
00982
00983
00984
00985 if ( pStage->bundle[0].vertexLightmap && ( (r_vertexLight->integer && !r_uiFullScreen->integer) || glConfig.hardwareType == GLHW_PERMEDIA2 ) && r_lightmap->integer )
00986 {
00987 GL_Bind( tr.whiteImage );
00988 }
00989 else
00990 R_BindAnimatedImage( &pStage->bundle[0] );
00991
00992 GL_State( pStage->stateBits );
00993
00994
00995
00996
00997 R_DrawElements( input->numIndexes, input->indexes );
00998 }
00999
01000 if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap || pStage->bundle[0].vertexLightmap ) )
01001 {
01002 break;
01003 }
01004 }
01005 }
01006
01007
01008
01009
01010
01011 void RB_StageIteratorGeneric( void )
01012 {
01013 shaderCommands_t *input;
01014
01015 input = &tess;
01016
01017 RB_DeformTessGeometry();
01018
01019
01020
01021
01022 if ( r_logFile->integer )
01023 {
01024
01025
01026 GLimp_LogComment( va("--- RB_StageIteratorGeneric( %s ) ---\n", tess.shader->name) );
01027 }
01028
01029
01030
01031
01032 GL_Cull( input->shader->cullType );
01033
01034
01035 if ( input->shader->polygonOffset )
01036 {
01037 qglEnable( GL_POLYGON_OFFSET_FILL );
01038 qglPolygonOffset( r_offsetFactor->value, r_offsetUnits->value );
01039 }
01040
01041
01042
01043
01044
01045
01046
01047 if ( tess.numPasses > 1 || input->shader->multitextureEnv )
01048 {
01049 setArraysOnce = qfalse;
01050 qglDisableClientState (GL_COLOR_ARRAY);
01051 qglDisableClientState (GL_TEXTURE_COORD_ARRAY);
01052 }
01053 else
01054 {
01055 setArraysOnce = qtrue;
01056
01057 qglEnableClientState( GL_COLOR_ARRAY);
01058 qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.svars.colors );
01059
01060 qglEnableClientState( GL_TEXTURE_COORD_ARRAY);
01061 qglTexCoordPointer( 2, GL_FLOAT, 0, tess.svars.texcoords[0] );
01062 }
01063
01064
01065
01066
01067 qglVertexPointer (3, GL_FLOAT, 16, input->xyz);
01068 if (qglLockArraysEXT)
01069 {
01070 qglLockArraysEXT(0, input->numVertexes);
01071 GLimp_LogComment( "glLockArraysEXT\n" );
01072 }
01073
01074
01075
01076
01077 if ( !setArraysOnce )
01078 {
01079 qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
01080 qglEnableClientState( GL_COLOR_ARRAY );
01081 }
01082
01083
01084
01085
01086 RB_IterateStagesGeneric( input );
01087
01088
01089
01090
01091 if ( tess.dlightBits && tess.shader->sort <= SS_OPAQUE
01092 && !(tess.shader->surfaceFlags & (SURF_NODLIGHT | SURF_SKY) ) ) {
01093 ProjectDlightTexture();
01094 }
01095
01096
01097
01098
01099 if ( tess.fogNum && tess.shader->fogPass ) {
01100 RB_FogPass();
01101 }
01102
01103
01104
01105
01106 if (qglUnlockArraysEXT)
01107 {
01108 qglUnlockArraysEXT();
01109 GLimp_LogComment( "glUnlockArraysEXT\n" );
01110 }
01111
01112
01113
01114
01115 if ( input->shader->polygonOffset )
01116 {
01117 qglDisable( GL_POLYGON_OFFSET_FILL );
01118 }
01119 }
01120
01121
01122
01123
01124
01125 void RB_StageIteratorVertexLitTexture( void )
01126 {
01127 shaderCommands_t *input;
01128 shader_t *shader;
01129
01130 input = &tess;
01131
01132 shader = input->shader;
01133
01134
01135
01136
01137 RB_CalcDiffuseColor( ( unsigned char * ) tess.svars.colors );
01138
01139
01140
01141
01142 if ( r_logFile->integer )
01143 {
01144
01145
01146 GLimp_LogComment( va("--- RB_StageIteratorVertexLitTexturedUnfogged( %s ) ---\n", tess.shader->name) );
01147 }
01148
01149
01150
01151
01152 GL_Cull( input->shader->cullType );
01153
01154
01155
01156
01157 qglEnableClientState( GL_COLOR_ARRAY);
01158 qglEnableClientState( GL_TEXTURE_COORD_ARRAY);
01159
01160 qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.svars.colors );
01161 qglTexCoordPointer( 2, GL_FLOAT, 16, tess.texCoords[0][0] );
01162 qglVertexPointer (3, GL_FLOAT, 16, input->xyz);
01163
01164 if ( qglLockArraysEXT )
01165 {
01166 qglLockArraysEXT(0, input->numVertexes);
01167 GLimp_LogComment( "glLockArraysEXT\n" );
01168 }
01169
01170
01171
01172
01173 R_BindAnimatedImage( &tess.xstages[0]->bundle[0] );
01174 GL_State( tess.xstages[0]->stateBits );
01175 R_DrawElements( input->numIndexes, input->indexes );
01176
01177
01178
01179
01180 if ( tess.dlightBits && tess.shader->sort <= SS_OPAQUE ) {
01181 ProjectDlightTexture();
01182 }
01183
01184
01185
01186
01187 if ( tess.fogNum && tess.shader->fogPass ) {
01188 RB_FogPass();
01189 }
01190
01191
01192
01193
01194 if (qglUnlockArraysEXT)
01195 {
01196 qglUnlockArraysEXT();
01197 GLimp_LogComment( "glUnlockArraysEXT\n" );
01198 }
01199 }
01200
01201
01202
01203 void RB_StageIteratorLightmappedMultitexture( void ) {
01204 shaderCommands_t *input;
01205
01206 input = &tess;
01207
01208
01209
01210
01211 if ( r_logFile->integer ) {
01212
01213
01214 GLimp_LogComment( va("--- RB_StageIteratorLightmappedMultitexture( %s ) ---\n", tess.shader->name) );
01215 }
01216
01217
01218
01219
01220 GL_Cull( input->shader->cullType );
01221
01222
01223
01224
01225 GL_State( GLS_DEFAULT );
01226 qglVertexPointer( 3, GL_FLOAT, 16, input->xyz );
01227
01228 #ifdef REPLACE_MODE
01229 qglDisableClientState( GL_COLOR_ARRAY );
01230 qglColor3f( 1, 1, 1 );
01231 qglShadeModel( GL_FLAT );
01232 #else
01233 qglEnableClientState( GL_COLOR_ARRAY );
01234 qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.constantColor255 );
01235 #endif
01236
01237
01238
01239
01240 GL_SelectTexture( 0 );
01241
01242 qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
01243 R_BindAnimatedImage( &tess.xstages[0]->bundle[0] );
01244 qglTexCoordPointer( 2, GL_FLOAT, 16, tess.texCoords[0][0] );
01245
01246
01247
01248
01249 GL_SelectTexture( 1 );
01250 qglEnable( GL_TEXTURE_2D );
01251 if ( r_lightmap->integer ) {
01252 GL_TexEnv( GL_REPLACE );
01253 } else {
01254 GL_TexEnv( GL_MODULATE );
01255 }
01256 R_BindAnimatedImage( &tess.xstages[0]->bundle[1] );
01257 qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
01258 qglTexCoordPointer( 2, GL_FLOAT, 16, tess.