00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "tr_local.h"
00023
00024
00025
00026 static char *s_shaderText;
00027
00028
00029
00030 static shaderStage_t stages[MAX_SHADER_STAGES];
00031 static shader_t shader;
00032 static texModInfo_t texMods[MAX_SHADER_STAGES][TR_MAX_TEXMODS];
00033 static qboolean deferLoad;
00034
00035 #define FILE_HASH_SIZE 1024
00036 static shader_t* hashTable[FILE_HASH_SIZE];
00037
00038 #define MAX_SHADERTEXT_HASH 2048
00039 static char **shaderTextHashTable[MAX_SHADERTEXT_HASH];
00040
00041
00042
00043
00044
00045
00046 static long generateHashValue( const char *fname, const int size ) {
00047 int i;
00048 long hash;
00049 char letter;
00050
00051 hash = 0;
00052 i = 0;
00053 while (fname[i] != '\0') {
00054 letter = tolower(fname[i]);
00055 if (letter =='.') break;
00056 if (letter =='\\') letter = '/';
00057 if (letter == PATH_SEP) letter = '/';
00058 hash+=(long)(letter)*(i+119);
00059 i++;
00060 }
00061 hash = (hash ^ (hash >> 10) ^ (hash >> 20));
00062 hash &= (size-1);
00063 return hash;
00064 }
00065
00066 void R_RemapShader(const char *shaderName, const char *newShaderName, const char *timeOffset) {
00067 char strippedName[MAX_QPATH];
00068 int hash;
00069 shader_t *sh, *sh2;
00070 qhandle_t h;
00071
00072 sh = R_FindShaderByName( shaderName );
00073 if (sh == NULL || sh == tr.defaultShader) {
00074 h = RE_RegisterShaderLightMap(shaderName, 0);
00075 sh = R_GetShaderByHandle(h);
00076 }
00077 if (sh == NULL || sh == tr.defaultShader) {
00078 ri.Printf( PRINT_WARNING, "WARNING: R_RemapShader: shader %s not found\n", shaderName );
00079 return;
00080 }
00081
00082 sh2 = R_FindShaderByName( newShaderName );
00083 if (sh2 == NULL || sh2 == tr.defaultShader) {
00084 h = RE_RegisterShaderLightMap(newShaderName, 0);
00085 sh2 = R_GetShaderByHandle(h);
00086 }
00087
00088 if (sh2 == NULL || sh2 == tr.defaultShader) {
00089 ri.Printf( PRINT_WARNING, "WARNING: R_RemapShader: new shader %s not found\n", newShaderName );
00090 return;
00091 }
00092
00093
00094
00095 COM_StripExtension( shaderName, strippedName );
00096 hash = generateHashValue(strippedName, FILE_HASH_SIZE);
00097 for (sh = hashTable[hash]; sh; sh = sh->next) {
00098 if (Q_stricmp(sh->name, strippedName) == 0) {
00099 if (sh != sh2) {
00100 sh->remappedShader = sh2;
00101 } else {
00102 sh->remappedShader = NULL;
00103 }
00104 }
00105 }
00106 if (timeOffset) {
00107 sh2->timeOffset = atof(timeOffset);
00108 }
00109 }
00110
00111
00112
00113
00114
00115
00116 static qboolean ParseVector( char **text, int count, float *v ) {
00117 char *token;
00118 int i;
00119
00120
00121 token = COM_ParseExt( text, qfalse );
00122 if ( strcmp( token, "(" ) ) {
00123 ri.Printf( PRINT_WARNING, "WARNING: missing parenthesis in shader '%s'\n", shader.name );
00124 return qfalse;
00125 }
00126
00127 for ( i = 0 ; i < count ; i++ ) {
00128 token = COM_ParseExt( text, qfalse );
00129 if ( !token[0] ) {
00130 ri.Printf( PRINT_WARNING, "WARNING: missing vector element in shader '%s'\n", shader.name );
00131 return qfalse;
00132 }
00133 v[i] = atof( token );
00134 }
00135
00136 token = COM_ParseExt( text, qfalse );
00137 if ( strcmp( token, ")" ) ) {
00138 ri.Printf( PRINT_WARNING, "WARNING: missing parenthesis in shader '%s'\n", shader.name );
00139 return qfalse;
00140 }
00141
00142 return qtrue;
00143 }
00144
00145
00146
00147
00148
00149
00150
00151 static unsigned NameToAFunc( const char *funcname )
00152 {
00153 if ( !Q_stricmp( funcname, "GT0" ) )
00154 {
00155 return GLS_ATEST_GT_0;
00156 }
00157 else if ( !Q_stricmp( funcname, "LT128" ) )
00158 {
00159 return GLS_ATEST_LT_80;
00160 }
00161 else if ( !Q_stricmp( funcname, "GE128" ) )
00162 {
00163 return GLS_ATEST_GE_80;
00164 }
00165
00166 ri.Printf( PRINT_WARNING, "WARNING: invalid alphaFunc name '%s' in shader '%s'\n", funcname, shader.name );
00167 return 0;
00168 }
00169
00170
00171
00172
00173
00174
00175
00176 static int NameToSrcBlendMode( const char *name )
00177 {
00178 if ( !Q_stricmp( name, "GL_ONE" ) )
00179 {
00180 return GLS_SRCBLEND_ONE;
00181 }
00182 else if ( !Q_stricmp( name, "GL_ZERO" ) )
00183 {
00184 return GLS_SRCBLEND_ZERO;
00185 }
00186 else if ( !Q_stricmp( name, "GL_DST_COLOR" ) )
00187 {
00188 return GLS_SRCBLEND_DST_COLOR;
00189 }
00190 else if ( !Q_stricmp( name, "GL_ONE_MINUS_DST_COLOR" ) )
00191 {
00192 return GLS_SRCBLEND_ONE_MINUS_DST_COLOR;
00193 }
00194 else if ( !Q_stricmp( name, "GL_SRC_ALPHA" ) )
00195 {
00196 return GLS_SRCBLEND_SRC_ALPHA;
00197 }
00198 else if ( !Q_stricmp( name, "GL_ONE_MINUS_SRC_ALPHA" ) )
00199 {
00200 return GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA;
00201 }
00202 else if ( !Q_stricmp( name, "GL_DST_ALPHA" ) )
00203 {
00204 return GLS_SRCBLEND_DST_ALPHA;
00205 }
00206 else if ( !Q_stricmp( name, "GL_ONE_MINUS_DST_ALPHA" ) )
00207 {
00208 return GLS_SRCBLEND_ONE_MINUS_DST_ALPHA;
00209 }
00210 else if ( !Q_stricmp( name, "GL_SRC_ALPHA_SATURATE" ) )
00211 {
00212 return GLS_SRCBLEND_ALPHA_SATURATE;
00213 }
00214
00215 ri.Printf( PRINT_WARNING, "WARNING: unknown blend mode '%s' in shader '%s', substituting GL_ONE\n", name, shader.name );
00216 return GLS_SRCBLEND_ONE;
00217 }
00218
00219
00220
00221
00222
00223
00224 static int NameToDstBlendMode( const char *name )
00225 {
00226 if ( !Q_stricmp( name, "GL_ONE" ) )
00227 {
00228 return GLS_DSTBLEND_ONE;
00229 }
00230 else if ( !Q_stricmp( name, "GL_ZERO" ) )
00231 {
00232 return GLS_DSTBLEND_ZERO;
00233 }
00234 else if ( !Q_stricmp( name, "GL_SRC_ALPHA" ) )
00235 {
00236 return GLS_DSTBLEND_SRC_ALPHA;
00237 }
00238 else if ( !Q_stricmp( name, "GL_ONE_MINUS_SRC_ALPHA" ) )
00239 {
00240 return GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA;
00241 }
00242 else if ( !Q_stricmp( name, "GL_DST_ALPHA" ) )
00243 {
00244 return GLS_DSTBLEND_DST_ALPHA;
00245 }
00246 else if ( !Q_stricmp( name, "GL_ONE_MINUS_DST_ALPHA" ) )
00247 {
00248 return GLS_DSTBLEND_ONE_MINUS_DST_ALPHA;
00249 }
00250 else if ( !Q_stricmp( name, "GL_SRC_COLOR" ) )
00251 {
00252 return GLS_DSTBLEND_SRC_COLOR;
00253 }
00254 else if ( !Q_stricmp( name, "GL_ONE_MINUS_SRC_COLOR" ) )
00255 {
00256 return GLS_DSTBLEND_ONE_MINUS_SRC_COLOR;
00257 }
00258
00259 ri.Printf( PRINT_WARNING, "WARNING: unknown blend mode '%s' in shader '%s', substituting GL_ONE\n", name, shader.name );
00260 return GLS_DSTBLEND_ONE;
00261 }
00262
00263
00264
00265
00266
00267
00268 static genFunc_t NameToGenFunc( const char *funcname )
00269 {
00270 if ( !Q_stricmp( funcname, "sin" ) )
00271 {
00272 return GF_SIN;
00273 }
00274 else if ( !Q_stricmp( funcname, "square" ) )
00275 {
00276 return GF_SQUARE;
00277 }
00278 else if ( !Q_stricmp( funcname, "triangle" ) )
00279 {
00280 return GF_TRIANGLE;
00281 }
00282 else if ( !Q_stricmp( funcname, "sawtooth" ) )
00283 {
00284 return GF_SAWTOOTH;
00285 }
00286 else if ( !Q_stricmp( funcname, "inversesawtooth" ) )
00287 {
00288 return GF_INVERSE_SAWTOOTH;
00289 }
00290 else if ( !Q_stricmp( funcname, "noise" ) )
00291 {
00292 return GF_NOISE;
00293 }
00294
00295 ri.Printf( PRINT_WARNING, "WARNING: invalid genfunc name '%s' in shader '%s'\n", funcname, shader.name );
00296 return GF_SIN;
00297 }
00298
00299
00300
00301
00302
00303
00304
00305 static void ParseWaveForm( char **text, waveForm_t *wave )
00306 {
00307 char *token;
00308
00309 token = COM_ParseExt( text, qfalse );
00310 if ( token[0] == 0 )
00311 {
00312 ri.Printf( PRINT_WARNING, "WARNING: missing waveform parm in shader '%s'\n", shader.name );
00313 return;
00314 }
00315 wave->func = NameToGenFunc( token );
00316
00317
00318 token = COM_ParseExt( text, qfalse );
00319 if ( token[0] == 0 )
00320 {
00321 ri.Printf( PRINT_WARNING, "WARNING: missing waveform parm in shader '%s'\n", shader.name );
00322 return;
00323 }
00324 wave->base = atof( token );
00325
00326 token = COM_ParseExt( text, qfalse );
00327 if ( token[0] == 0 )
00328 {
00329 ri.Printf( PRINT_WARNING, "WARNING: missing waveform parm in shader '%s'\n", shader.name );
00330 return;
00331 }
00332 wave->amplitude = atof( token );
00333
00334 token = COM_ParseExt( text, qfalse );
00335 if ( token[0] == 0 )
00336 {
00337 ri.Printf( PRINT_WARNING, "WARNING: missing waveform parm in shader '%s'\n", shader.name );
00338 return;
00339 }
00340 wave->phase = atof( token );
00341
00342 token = COM_ParseExt( text, qfalse );
00343 if ( token[0] == 0 )
00344 {
00345 ri.Printf( PRINT_WARNING, "WARNING: missing waveform parm in shader '%s'\n", shader.name );
00346 return;
00347 }
00348 wave->frequency = atof( token );
00349 }
00350
00351
00352
00353
00354
00355
00356
00357 static void ParseTexMod( char *_text, shaderStage_t *stage )
00358 {
00359 const char *token;
00360 char **text = &_text;
00361 texModInfo_t *tmi;
00362
00363 if ( stage->bundle[0].numTexMods == TR_MAX_TEXMODS ) {
00364 ri.Error( ERR_DROP, "ERROR: too many tcMod stages in shader '%s'\n", shader.name );
00365 return;
00366 }
00367
00368 tmi = &stage->bundle[0].texMods[stage->bundle[0].numTexMods];
00369 stage->bundle[0].numTexMods++;
00370
00371 token = COM_ParseExt( text, qfalse );
00372
00373
00374
00375
00376 if ( !Q_stricmp( token, "turb" ) )
00377 {
00378 token = COM_ParseExt( text, qfalse );
00379 if ( token[0] == 0 )
00380 {
00381 ri.Printf( PRINT_WARNING, "WARNING: missing tcMod turb parms in shader '%s'\n", shader.name );
00382 return;
00383 }
00384 tmi->wave.base = atof( token );
00385 token = COM_ParseExt( text, qfalse );
00386 if ( token[0] == 0 )
00387 {
00388 ri.Printf( PRINT_WARNING, "WARNING: missing tcMod turb in shader '%s'\n", shader.name );
00389 return;
00390 }
00391 tmi->wave.amplitude = atof( token );
00392 token = COM_ParseExt( text, qfalse );
00393 if ( token[0] == 0 )
00394 {
00395 ri.Printf( PRINT_WARNING, "WARNING: missing tcMod turb in shader '%s'\n", shader.name );
00396 return;
00397 }
00398 tmi->wave.phase = atof( token );
00399 token = COM_ParseExt( text, qfalse );
00400 if ( token[0] == 0 )
00401 {
00402 ri.Printf( PRINT_WARNING, "WARNING: missing tcMod turb in shader '%s'\n", shader.name );
00403 return;
00404 }
00405 tmi->wave.frequency = atof( token );
00406
00407 tmi->type = TMOD_TURBULENT;
00408 }
00409
00410
00411
00412 else if ( !Q_stricmp( token, "scale" ) )
00413 {
00414 token = COM_ParseExt( text, qfalse );
00415 if ( token[0] == 0 )
00416 {
00417 ri.Printf( PRINT_WARNING, "WARNING: missing scale parms in shader '%s'\n", shader.name );
00418 return;
00419 }
00420 tmi->scale[0] = atof( token );
00421
00422 token = COM_ParseExt( text, qfalse );
00423 if ( token[0] == 0 )
00424 {
00425 ri.Printf( PRINT_WARNING, "WARNING: missing scale parms in shader '%s'\n", shader.name );
00426 return;
00427 }
00428 tmi->scale[1] = atof( token );
00429 tmi->type = TMOD_SCALE;
00430 }
00431
00432
00433
00434 else if ( !Q_stricmp( token, "scroll" ) )
00435 {
00436 token = COM_ParseExt( text, qfalse );
00437 if ( token[0] == 0 )
00438 {
00439 ri.Printf( PRINT_WARNING, "WARNING: missing scale scroll parms in shader '%s'\n", shader.name );
00440 return;
00441 }
00442 tmi->scroll[0] = atof( token );
00443 token = COM_ParseExt( text, qfalse );
00444 if ( token[0] == 0 )
00445 {
00446 ri.Printf( PRINT_WARNING, "WARNING: missing scale scroll parms in shader '%s'\n", shader.name );
00447 return;
00448 }
00449 tmi->scroll[1] = atof( token );
00450 tmi->type = TMOD_SCROLL;
00451 }
00452
00453
00454
00455 else if ( !Q_stricmp( token, "stretch" ) )
00456 {
00457 token = COM_ParseExt( text, qfalse );
00458 if ( token[0] == 0 )
00459 {
00460 ri.Printf( PRINT_WARNING, "WARNING: missing stretch parms in shader '%s'\n", shader.name );
00461 return;
00462 }
00463 tmi->wave.func = NameToGenFunc( token );
00464
00465 token = COM_ParseExt( text, qfalse );
00466 if ( token[0] == 0 )
00467 {
00468 ri.Printf( PRINT_WARNING, "WARNING: missing stretch parms in shader '%s'\n", shader.name );
00469 return;
00470 }
00471 tmi->wave.base = atof( token );
00472
00473 token = COM_ParseExt( text, qfalse );
00474 if ( token[0] == 0 )
00475 {
00476 ri.Printf( PRINT_WARNING, "WARNING: missing stretch parms in shader '%s'\n", shader.name );
00477 return;
00478 }
00479 tmi->wave.amplitude = atof( token );
00480
00481 token = COM_ParseExt( text, qfalse );
00482 if ( token[0] == 0 )
00483 {
00484 ri.Printf( PRINT_WARNING, "WARNING: missing stretch parms in shader '%s'\n", shader.name );
00485 return;
00486 }
00487 tmi->wave.phase = atof( token );
00488
00489 token = COM_ParseExt( text, qfalse );
00490 if ( token[0] == 0 )
00491 {
00492 ri.Printf( PRINT_WARNING, "WARNING: missing stretch parms in shader '%s'\n", shader.name );
00493 return;
00494 }
00495 tmi->wave.frequency = atof( token );
00496
00497 tmi->type = TMOD_STRETCH;
00498 }
00499
00500
00501
00502 else if ( !Q_stricmp( token, "transform" ) )
00503 {
00504 token = COM_ParseExt( text, qfalse );
00505 if ( token[0] == 0 )
00506 {
00507 ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name );
00508 return;
00509 }
00510 tmi->matrix[0][0] = atof( token );
00511
00512 token = COM_ParseExt( text, qfalse );
00513 if ( token[0] == 0 )
00514 {
00515 ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name );
00516 return;
00517 }
00518 tmi->matrix[0][1] = atof( token );
00519
00520 token = COM_ParseExt( text, qfalse );
00521 if ( token[0] == 0 )
00522 {
00523 ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name );
00524 return;
00525 }
00526 tmi->matrix[1][0] = atof( token );
00527
00528 token = COM_ParseExt( text, qfalse );
00529 if ( token[0] == 0 )
00530 {
00531 ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name );
00532 return;
00533 }
00534 tmi->matrix[1][1] = atof( token );
00535
00536 token = COM_ParseExt( text, qfalse );
00537 if ( token[0] == 0 )
00538 {
00539 ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name );
00540 return;
00541 }
00542 tmi->translate[0] = atof( token );
00543
00544 token = COM_ParseExt( text, qfalse );
00545 if ( token[0] == 0 )
00546 {
00547 ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name );
00548 return;
00549 }
00550 tmi->translate[1] = atof( token );
00551
00552 tmi->type = TMOD_TRANSFORM;
00553 }
00554
00555
00556
00557 else if ( !Q_stricmp( token, "rotate" ) )
00558 {
00559 token = COM_ParseExt( text, qfalse );
00560 if ( token[0] == 0 )
00561 {
00562 ri.Printf( PRINT_WARNING, "WARNING: missing tcMod rotate parms in shader '%s'\n", shader.name );
00563 return;
00564 }
00565 tmi->rotateSpeed = atof( token );
00566 tmi->type = TMOD_ROTATE;
00567 }
00568
00569
00570
00571 else if ( !Q_stricmp( token, "entityTranslate" ) )
00572 {
00573 tmi->type = TMOD_ENTITY_TRANSLATE;
00574 }
00575 else
00576 {
00577 ri.Printf( PRINT_WARNING, "WARNING: unknown tcMod '%s' in shader '%s'\n", token, shader.name );
00578 }
00579 }
00580
00581
00582
00583
00584
00585
00586
00587 static qboolean ParseStage( shaderStage_t *stage, char **text )
00588 {
00589 char *token;
00590 int depthMaskBits = GLS_DEPTHMASK_TRUE, blendSrcBits = 0, blendDstBits = 0, atestBits = 0, depthFuncBits = 0;
00591 qboolean depthMaskExplicit = qfalse;
00592
00593 stage->active = qtrue;
00594
00595 while ( 1 )
00596 {
00597 token = COM_ParseExt( text, qtrue );
00598 if ( !token[0] )
00599 {
00600 ri.Printf( PRINT_WARNING, "WARNING: no matching '}' found\n" );
00601 return qfalse;
00602 }
00603
00604 if ( token[0] == '}' )
00605 {
00606 break;
00607 }
00608
00609
00610
00611 else if ( !Q_stricmp( token, "map" ) )
00612 {
00613 token = COM_ParseExt( text, qfalse );
00614 if ( !token[0] )
00615 {
00616 ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'map' keyword in shader '%s'\n", shader.name );
00617 return qfalse;
00618 }
00619
00620 if ( !Q_stricmp( token, "$whiteimage" ) )
00621 {
00622 stage->bundle[0].image[0] = tr.whiteImage;
00623 continue;
00624 }
00625 else if ( !Q_stricmp( token, "$lightmap" ) )
00626 {
00627 stage->bundle[0].isLightmap = qtrue;
00628 if ( shader.lightmapIndex < 0 ) {
00629 stage->bundle[0].image[0] = tr.whiteImage;
00630 } else {
00631 stage->bundle[0].image[0] = tr.lightmaps[shader.lightmapIndex];
00632 }
00633 continue;
00634 }
00635 else
00636 {
00637 stage->bundle[0].image[0] = R_FindImageFile( token, !shader.noMipMaps, !shader.noPicMip, GL_REPEAT );
00638 if ( !stage->bundle[0].image[0] )
00639 {
00640 ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name );
00641 return qfalse;
00642 }
00643 }
00644 }
00645
00646
00647
00648 else if ( !Q_stricmp( token, "clampmap" ) )
00649 {
00650 token = COM_ParseExt( text, qfalse );
00651 if ( !token[0] )
00652 {
00653 ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'clampmap' keyword in shader '%s'\n", shader.name );
00654 return qfalse;
00655 }
00656
00657 stage->bundle[0].image[0] = R_FindImageFile( token, !shader.noMipMaps, !shader.noPicMip, GL_CLAMP );
00658 if ( !stage->bundle[0].image[0] )
00659 {
00660 ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name );
00661 return qfalse;
00662 }
00663 }
00664
00665
00666
00667 else if ( !Q_stricmp( token, "animMap" ) )
00668 {
00669 token = COM_ParseExt( text, qfalse );
00670 if ( !token[0] )
00671 {
00672 ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'animMmap' keyword in shader '%s'\n", shader.name );
00673 return qfalse;
00674 }
00675 stage->bundle[0].imageAnimationSpeed = atof( token );
00676
00677
00678 while ( 1 ) {
00679 int num;
00680
00681 token = COM_ParseExt( text, qfalse );
00682 if ( !token[0] ) {
00683 break;
00684 }
00685 num = stage->bundle[0].numImageAnimations;
00686 if ( num < MAX_IMAGE_ANIMATIONS ) {
00687 stage->bundle[0].image[num] = R_FindImageFile( token, !shader.noMipMaps, !shader.noPicMip, GL_REPEAT );
00688 if ( !stage->bundle[0].image[num] )
00689 {
00690 ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name );
00691 return qfalse;
00692 }
00693 stage->bundle[0].numImageAnimations++;
00694 }
00695 }
00696 }
00697 else if ( !Q_stricmp( token, "videoMap" ) )
00698 {
00699 token = COM_ParseExt( text, qfalse );
00700 if ( !token[0] )
00701 {
00702 ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'videoMmap' keyword in shader '%s'\n", shader.name );
00703 return qfalse;
00704 }
00705 stage->bundle[0].videoMapHandle = ri.CIN_PlayCinematic( token, 0, 0, 256, 256, (CIN_loop | CIN_silent | CIN_shader));
00706 if (stage->bundle[0].videoMapHandle != -1) {
00707 stage->bundle[0].isVideoMap = qtrue;
00708 stage->bundle[0].image[0] = tr.scratchImage[stage->bundle[0].videoMapHandle];
00709 }
00710 }
00711
00712
00713
00714 else if ( !Q_stricmp( token, "alphaFunc" ) )
00715 {
00716 token = COM_ParseExt( text, qfalse );
00717 if ( !token[0] )
00718 {
00719 ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'alphaFunc' keyword in shader '%s'\n", shader.name );
00720 return qfalse;
00721 }
00722
00723 atestBits = NameToAFunc( token );
00724 }
00725
00726
00727
00728 else if ( !Q_stricmp( token, "depthfunc" ) )
00729 {
00730 token = COM_ParseExt( text, qfalse );
00731
00732 if ( !token[0] )
00733 {
00734 ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'depthfunc' keyword in shader '%s'\n", shader.name );
00735 return qfalse;
00736 }
00737
00738 if ( !Q_stricmp( token, "lequal" ) )
00739 {
00740 depthFuncBits = 0;
00741 }
00742 else if ( !Q_stricmp( token, "equal" ) )
00743 {
00744 depthFuncBits = GLS_DEPTHFUNC_EQUAL;
00745 }
00746 else
00747 {
00748 ri.Printf( PRINT_WARNING, "WARNING: unknown depthfunc '%s' in shader '%s'\n", token, shader.name );
00749 continue;
00750 }
00751 }
00752
00753
00754
00755 else if ( !Q_stricmp( token, "detail" ) )
00756 {
00757 stage->isDetail = qtrue;
00758 }
00759
00760
00761
00762
00763 else if ( !Q_stricmp( token, "blendfunc" ) )
00764 {
00765 token = COM_ParseExt( text, qfalse );
00766 if ( token[0] == 0 )
00767 {
00768 ri.Printf( PRINT_WARNING, "WARNING: missing parm for blendFunc in shader '%s'\n", shader.name );
00769 continue;
00770 }
00771
00772 if ( !Q_stricmp( token, "add" ) ) {
00773 blendSrcBits = GLS_SRCBLEND_ONE;
00774 blendDstBits = GLS_DSTBLEND_ONE;
00775 } else if ( !Q_stricmp( token, "filter" ) ) {
00776 blendSrcBits = GLS_SRCBLEND_DST_COLOR;
00777 blendDstBits = GLS_DSTBLEND_ZERO;
00778 } else if ( !Q_stricmp( token, "blend" ) ) {
00779 blendSrcBits = GLS_SRCBLEND_SRC_ALPHA;
00780 blendDstBits = GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA;
00781 } else {
00782
00783 blendSrcBits = NameToSrcBlendMode( token );
00784
00785 token = COM_ParseExt( text, qfalse );
00786 if ( token[0] == 0 )
00787 {
00788 ri.Printf( PRINT_WARNING, "WARNING: missing parm for blendFunc in shader '%s'\n", shader.name );
00789 continue;
00790 }
00791 blendDstBits = NameToDstBlendMode( token );
00792 }
00793
00794
00795 if ( !depthMaskExplicit )
00796 {
00797 depthMaskBits = 0;
00798 }
00799 }
00800
00801
00802
00803 else if ( !Q_stricmp( token, "rgbGen" ) )
00804 {
00805 token = COM_ParseExt( text, qfalse );
00806 if ( token[0] == 0 )
00807 {
00808 ri.Printf( PRINT_WARNING, "WARNING: missing parameters for rgbGen in shader '%s'\n", shader.name );
00809 continue;
00810 }
00811
00812 if ( !Q_stricmp( token, "wave" ) )
00813 {
00814 ParseWaveForm( text, &stage->rgbWave );
00815 stage->rgbGen = CGEN_WAVEFORM;
00816 }
00817 else if ( !Q_stricmp( token, "const" ) )
00818 {
00819 vec3_t color;
00820
00821 ParseVector( text, 3, color );
00822 stage->constantColor[0] = 255 * color[0];
00823 stage->constantColor[1] = 255 * color[1];
00824 stage->constantColor[2] = 255 * color[2];
00825
00826 stage->rgbGen = CGEN_CONST;
00827 }
00828 else if ( !Q_stricmp( token, "identity" ) )
00829 {
00830 stage->rgbGen = CGEN_IDENTITY;
00831 }
00832 else if ( !Q_stricmp( token, "identityLighting" ) )
00833 {
00834 stage->rgbGen = CGEN_IDENTITY_LIGHTING;
00835 }
00836 else if ( !Q_stricmp( token, "entity" ) )
00837 {
00838 stage->rgbGen = CGEN_ENTITY;
00839 }
00840 else if ( !Q_stricmp( token, "oneMinusEntity" ) )
00841 {
00842 stage->rgbGen = CGEN_ONE_MINUS_ENTITY;
00843 }
00844 else if ( !Q_stricmp( token, "vertex" ) )
00845 {
00846 stage->rgbGen = CGEN_VERTEX;
00847 if ( stage->alphaGen == 0 ) {
00848 stage->alphaGen = AGEN_VERTEX;
00849 }
00850 }
00851 else if ( !Q_stricmp( token, "exactVertex" ) )
00852 {
00853 stage->rgbGen = CGEN_EXACT_VERTEX;
00854 }
00855 else if ( !Q_stricmp( token, "lightingDiffuse" ) )
00856 {
00857 stage->rgbGen = CGEN_LIGHTING_DIFFUSE;
00858 }
00859 else if ( !Q_stricmp( token, "oneMinusVertex" ) )
00860 {
00861 stage->rgbGen = CGEN_ONE_MINUS_VERTEX;
00862 }
00863 else
00864 {
00865 ri.Printf( PRINT_WARNING, "WARNING: unknown rgbGen parameter '%s' in shader '%s'\n", token, shader.name );
00866 continue;
00867 }
00868 }
00869
00870
00871
00872 else if ( !Q_stricmp( token, "alphaGen" ) )
00873 {
00874 token = COM_ParseExt( text, qfalse );
00875 if ( token[0] == 0 )
00876 {
00877 ri.Printf( PRINT_WARNING, "WARNING: missing parameters for alphaGen in shader '%s'\n", shader.name );
00878 continue;
00879 }
00880
00881 if ( !Q_stricmp( token, "wave" ) )
00882 {
00883 ParseWaveForm( text, &stage->alphaWave );
00884 stage->alphaGen = AGEN_WAVEFORM;
00885 }
00886 else if ( !Q_stricmp( token, "const" ) )
00887 {
00888 token = COM_ParseExt( text, qfalse );
00889 stage->constantColor[3] = 255 * atof( token );
00890 stage->alphaGen = AGEN_CONST;
00891 }
00892 else if ( !Q_stricmp( token, "identity" ) )
00893 {
00894 stage->alphaGen = AGEN_IDENTITY;
00895 }
00896 else if ( !Q_stricmp( token, "entity" ) )
00897 {
00898 stage->alphaGen = AGEN_ENTITY;
00899 }
00900 else if ( !Q_stricmp( token, "oneMinusEntity" ) )
00901 {
00902 stage->alphaGen = AGEN_ONE_MINUS_ENTITY;
00903 }
00904 else if ( !Q_stricmp( token, "vertex" ) )
00905 {
00906 stage->alphaGen = AGEN_VERTEX;
00907 }
00908 else if ( !Q_stricmp( token, "lightingSpecular" ) )
00909 {
00910 stage->alphaGen = AGEN_LIGHTING_SPECULAR;
00911 }
00912 else if ( !Q_stricmp( token, "oneMinusVertex" ) )
00913 {
00914 stage->alphaGen = AGEN_ONE_MINUS_VERTEX;
00915 }
00916 else if ( !Q_stricmp( token, "portal" ) )
00917 {
00918 stage->alphaGen = AGEN_PORTAL;
00919 token = COM_ParseExt( text, qfalse );
00920 if ( token[0] == 0 )
00921 {
00922 shader.portalRange = 256;
00923 ri.Printf( PRINT_WARNING, "WARNING: missing range parameter for alphaGen portal in shader '%s', defaulting to 256\n", shader.name );
00924 }
00925 else
00926 {
00927 shader.portalRange = atof( token );
00928 }
00929 }
00930 else
00931 {
00932 ri.Printf( PRINT_WARNING, "WARNING: unknown alphaGen parameter '%s' in shader '%s'\n", token, shader.name );
00933 continue;
00934 }
00935 }
00936
00937
00938
00939 else if ( !Q_stricmp(token, "texgen") || !Q_stricmp( token, "tcGen" ) )
00940 {
00941 token = COM_ParseExt( text, qfalse );
00942 if ( token[0] == 0 )
00943 {
00944 ri.Printf( PRINT_WARNING, "WARNING: missing texgen parm in shader '%s'\n", shader.name );
00945 continue;
00946 }
00947
00948 if ( !Q_stricmp( token, "environment" ) )
00949 {
00950 stage->bundle[0].tcGen = TCGEN_ENVIRONMENT_MAPPED;
00951 }
00952 else if ( !Q_stricmp( token, "lightmap" ) )
00953 {
00954 stage->bundle[0].tcGen = TCGEN_LIGHTMAP;
00955 }
00956 else if ( !Q_stricmp( token, "texture" ) || !Q_stricmp( token, "base" ) )
00957 {
00958 stage->bundle[0].tcGen = TCGEN_TEXTURE;
00959 }
00960 else if ( !Q_stricmp( token, "vector" ) )
00961 {
00962 ParseVector( text, 3, stage->bundle[0].tcGenVectors[0] );
00963 ParseVector( text, 3, stage->bundle[0].tcGenVectors[1] );
00964
00965 stage->bundle[0].tcGen = TCGEN_VECTOR;
00966 }
00967 else
00968 {
00969 ri.Printf( PRINT_WARNING, "WARNING: unknown texgen parm in shader '%s'\n", shader.name );
00970 }
00971 }
00972
00973
00974
00975 else if ( !Q_stricmp( token, "tcMod" ) )
00976 {
00977 char buffer[1024] = "";
00978
00979 while ( 1 )
00980 {
00981 token = COM_ParseExt( text, qfalse );
00982 if ( token[0] == 0 )
00983 break;
00984 strcat( buffer, token );
00985 strcat( buffer, " " );
00986 }
00987
00988 ParseTexMod( buffer, stage );
00989
00990 continue;
00991 }
00992
00993
00994
00995 else if ( !Q_stricmp( token, "depthwrite" ) )
00996 {
00997 depthMaskBits = GLS_DEPTHMASK_TRUE;
00998 depthMaskExplicit = qtrue;
00999
01000 continue;
01001 }
01002 else
01003 {
01004 ri.Printf( PRINT_WARNING, "WARNING: unknown parameter '%s' in shader '%s'\n", token, shader.name );
01005 return qfalse;
01006 }
01007 }
01008
01009
01010
01011
01012 if ( stage->rgbGen == CGEN_BAD ) {
01013 if ( blendSrcBits == 0 ||
01014 blendSrcBits == GLS_SRCBLEND_ONE ||
01015 blendSrcBits == GLS_SRCBLEND_SRC_ALPHA ) {
01016 stage->rgbGen = CGEN_IDENTITY_LIGHTING;
01017 } else {
01018 stage->rgbGen = CGEN_IDENTITY;
01019 }
01020 }
01021
01022
01023
01024
01025
01026 if ( ( blendSrcBits == GLS_SRCBLEND_ONE ) &&
01027 ( blendDstBits == GLS_DSTBLEND_ZERO ) )
01028 {
01029 blendDstBits = blendSrcBits = 0;
01030 depthMaskBits = GLS_DEPTHMASK_TRUE;
01031 }
01032
01033
01034 if ( stage->alphaGen == CGEN_IDENTITY ) {
01035 if ( stage->rgbGen == CGEN_IDENTITY
01036 || stage->rgbGen == CGEN_LIGHTING_DIFFUSE ) {
01037 stage->alphaGen = AGEN_SKIP;
01038 }
01039 }
01040
01041
01042
01043
01044 stage->stateBits = depthMaskBits |
01045 blendSrcBits | blendDstBits |
01046 atestBits |
01047 depthFuncBits;
01048
01049 return qtrue;
01050 }
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066 static void ParseDeform( char **text ) {
01067 char *token;
01068 deformStage_t *ds;
01069
01070 token = COM_ParseExt( text, qfalse );
01071 if ( token[0] == 0 )
01072 {
01073 ri.Printf( PRINT_WARNING, "WARNING: missing deform parm in shader '%s'\n", shader.name );
01074 return;
01075 }
01076
01077 if ( shader.numDeforms == MAX_SHADER_DEFORMS ) {
01078 ri.Printf( PRINT_WARNING, "WARNING: MAX_SHADER_DEFORMS in '%s'\n", shader.name );
01079 return;
01080 }
01081
01082 ds = &shader.deforms[ shader.numDeforms ];
01083 shader.numDeforms++;
01084
01085 if ( !Q_stricmp( token, "projectionShadow" ) ) {
01086 ds->deformation = DEFORM_PROJECTION_SHADOW;
01087 return;
01088 }
01089
01090 if ( !Q_stricmp( token, "autosprite" ) ) {
01091 ds->deformation = DEFORM_AUTOSPRITE;
01092 return;
01093 }
01094
01095 if ( !Q_stricmp( token, "autosprite2" ) ) {
01096 ds->deformation = DEFORM_AUTOSPRITE2;
01097 return;
01098 }
01099
01100 if ( !Q_stricmpn( token, "text", 4 ) ) {
01101 int n;
01102
01103 n = token[4] - '0';
01104 if ( n < 0 || n > 7 ) {
01105 n = 0;
01106 }
01107 ds->deformation = DEFORM_TEXT0 + n;
01108 return;
01109 }
01110
01111 if ( !Q_stricmp( token, "bulge" ) ) {
01112 token = COM_ParseExt( text, qfalse );
01113 if ( token[0] == 0 )
01114 {
01115 ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes bulge parm in shader '%s'\n", shader.name );
01116 return;
01117 }
01118 ds->bulgeWidth = atof( token );
01119
01120 token = COM_ParseExt( text, qfalse );
01121 if ( token[0] == 0 )
01122 {
01123 ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes bulge parm in shader '%s'\n", shader.name );
01124 return;
01125 }
01126 ds->bulgeHeight = atof( token );
01127
01128 token = COM_ParseExt( text, qfalse );
01129 if ( token[0] == 0 )
01130 {
01131 ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes bulge parm in shader '%s'\n", shader.name );
01132 return;
01133 }
01134 ds->bulgeSpeed = atof( token );
01135
01136 ds->deformation = DEFORM_BULGE;
01137 return;
01138 }
01139
01140 if ( !Q_stricmp( token, "wave" ) )
01141 {
01142 token = COM_ParseExt( text, qfalse );
01143 if ( token[0] == 0 )
01144 {
01145 ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes parm in shader '%s'\n", shader.name );
01146 return;
01147 }
01148
01149 if ( atof( token ) != 0 )
01150 {
01151 ds->deformationSpread = 1.0f / atof( token );
01152 }
01153 else
01154 {
01155 ds->deformationSpread = 100.0f;
01156 ri.Printf( PRINT_WARNING, "WARNING: illegal div value of 0 in deformVertexes command for shader '%s'\n", shader.name );
01157 }
01158
01159 ParseWaveForm( text, &ds->deformationWave );
01160 ds->deformation = DEFORM_WAVE;
01161 return;
01162 }
01163
01164 if ( !Q_stricmp( token, "normal" ) )
01165 {
01166 token = COM_ParseExt( text, qfalse );
01167 if ( token[0] == 0 )
01168 {
01169 ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes parm in shader '%s'\n", shader.name );
01170 return;
01171 }
01172 ds->deformationWave.amplitude = atof( token );
01173
01174 token = COM_ParseExt( text, qfalse );
01175 if ( token[0] == 0 )
01176 {
01177 ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes parm in shader '%s'\n", shader.name );
01178 return;
01179 }
01180 ds->deformationWave.frequency = atof( token );
01181
01182 ds->deformation = DEFORM_NORMALS;
01183 return;
01184 }
01185
01186 if ( !Q_stricmp( token, "move" ) ) {
01187 int i;
01188
01189 for ( i = 0 ; i < 3 ; i++ ) {
01190 token = COM_ParseExt( text, qfalse );
01191 if ( token[0] == 0 ) {
01192 ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes parm in shader '%s'\n", shader.name );
01193 return;
01194 }
01195 ds->moveVector[i] = atof( token );
01196 }
01197
01198 ParseWaveForm( text, &ds->deformationWave );
01199 ds->deformation = DEFORM_MOVE;
01200 return;
01201 }
01202
01203 ri.Printf( PRINT_WARNING, "WARNING: unknown deformVertexes subtype '%s' found in shader '%s'\n", token, shader.name );
01204 }
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214 static void ParseSkyParms( char **text ) {
01215 char *token;
01216 static char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
01217 char pathname[MAX_QPATH];
01218 int i;
01219
01220
01221 token = COM_ParseExt( text, qfalse );
01222 if ( token[0] == 0 ) {
01223 ri.Printf( PRINT_WARNING, "WARNING: 'skyParms' missing parameter in shader '%s'\n", shader.name );
01224 return;
01225 }
01226 if ( strcmp( token, "-" ) ) {
01227 for (i=0 ; i<6 ; i++) {
01228 Com_sprintf( pathname, sizeof(pathname), "%s_%s.tga"
01229 , token, suf[i] );
01230 shader.sky.outerbox[i] = R_FindImageFile( ( char * ) pathname, qtrue, qtrue, GL_CLAMP );
01231 if ( !shader.sky.outerbox[i] ) {
01232 shader.sky.outerbox[i] = tr.defaultImage;
01233 }
01234 }
01235 }
01236
01237
01238 token = COM_ParseExt( text, qfalse );
01239 if ( token[0] == 0 ) {
01240 ri.Printf( PRINT_WARNING, "WARNING: 'skyParms' missing parameter in shader '%s'\n", shader.name );
01241 return;
01242 }
01243 shader.sky.cloudHeight = atof( token );
01244 if ( !shader.sky.cloudHeight ) {
01245 shader.sky.cloudHeight = 512;
01246 }
01247 R_InitSkyTexCoords( shader.sky.cloudHeight );
01248
01249
01250
01251 token = COM_ParseExt( text, qfalse );
01252 if ( token[0] == 0 ) {
01253 ri.Printf( PRINT_WARNING, "WARNING: 'skyParms' missing parameter in shader '%s'\n", shader.name );
01254 return;
01255 }
01256 if ( strcmp( token, "-" ) ) {
01257 for (i=0 ; i<6 ; i++) {
01258 Com_sprintf( pathname, sizeof(pathname), "%s_%s.tga"
01259 , token, suf[i] );
01260 shader.sky.innerbox[i] = R_FindImageFile( ( char * ) pathname, qtrue, qtrue, GL_REPEAT );
01261 if ( !shader.sky.innerbox[i] ) {
01262 shader.sky.innerbox[i] = tr.defaultImage;
01263 }
01264 }
01265 }
01266
01267 shader.isSky = qtrue;
01268 }
01269
01270
01271
01272
01273
01274
01275
01276 void ParseSort( char **text ) {
01277 char *token;
01278
01279 token = COM_ParseExt( text, qfalse );
01280 if ( token[0] == 0 ) {
01281 ri.Printf( PRINT_WARNING, "WARNING: missing sort parameter in shader '%s'\n", shader.name );
01282 return;
01283 }
01284
01285 if ( !Q_stricmp( token, "portal" ) ) {
01286 shader.sort = SS_PORTAL;
01287 } else if ( !Q_stricmp( token, "sky" ) ) {
01288 shader.sort = SS_ENVIRONMENT;
01289 } else if ( !Q_stricmp( token, "opaque" ) ) {
01290 shader.sort = SS_OPAQUE;
01291 }else if ( !Q_stricmp( token, "decal" ) ) {
01292 shader.sort = SS_DECAL;
01293 } else if ( !Q_stricmp( token, "seeThrough" ) ) {
01294 shader.sort = SS_SEE_THROUGH;
01295 } else if ( !Q_stricmp( token, "banner" ) ) {
01296 shader.sort = SS_BANNER;
01297 } else if ( !Q_stricmp( token, "additive" ) ) {
01298 shader.sort = SS_BLEND1;
01299 } else if ( !Q_stricmp( token, "nearest" ) ) {
01300 shader.sort = SS_NEAREST;
01301 } else if ( !Q_stricmp( token, "underwater" ) ) {
01302 shader.sort = SS_UNDERWATER;
01303 } else {
01304 shader.sort = atof( token );
01305 }
01306 }
01307
01308
01309
01310
01311
01312 typedef struct {
01313 char *name;
01314 int clearSolid, surfaceFlags, contents;
01315 } infoParm_t;
01316
01317 infoParm_t infoParms[] = {
01318
01319 {"water", 1, 0, CONTENTS_WATER },
01320 {"slime", 1, 0, CONTENTS_SLIME },
01321 {"lava", 1, 0, CONTENTS_LAVA },
01322 {"playerclip", 1, 0, CONTENTS_PLAYERCLIP },
01323 {"monsterclip", 1, 0, CONTENTS_MONSTERCLIP },
01324 {"nodrop", 1, 0, CONTENTS_NODROP },
01325 {"nonsolid", 1, SURF_NONSOLID, 0},
01326
01327
01328 {"origin", 1, 0, CONTENTS_ORIGIN },
01329 {"trans", 0, 0, CONTENTS_TRANSLUCENT },
01330 {"detail", 0, 0, CONTENTS_DETAIL },
01331 {"structural", 0, 0, CONTENTS_STRUCTURAL },
01332 {"areaportal", 1, 0, CONTENTS_AREAPORTAL },
01333 {"clusterportal", 1,0, CONTENTS_CLUSTERPORTAL },
01334 {"donotenter", 1, 0, CONTENTS_DONOTENTER },
01335
01336 {"fog", 1, 0, CONTENTS_FOG},
01337 {"sky", 0, SURF_SKY, 0 },
01338 {"lightfilter", 0, SURF_LIGHTFILTER, 0 },
01339 {"alphashadow", 0, SURF_ALPHASHADOW, 0 },
01340 {"hint", 0, SURF_HINT, 0 },
01341
01342
01343 {"slick", 0, SURF_SLICK, 0 },
01344 {"noimpact", 0, SURF_NOIMPACT, 0 },
01345 {"nomarks", 0, SURF_NOMARKS, 0 },
01346 {"ladder", 0, SURF_LADDER, 0 },
01347 {"nodamage", 0, SURF_NODAMAGE, 0 },
01348 {"metalsteps", 0, SURF_METALSTEPS,0 },
01349 {"flesh", 0, SURF_FLESH, 0 },
01350 {"nosteps", 0, SURF_NOSTEPS, 0 },
01351
01352
01353 {"nodraw", 0, SURF_NODRAW, 0 },
01354 {"pointlight", 0, SURF_POINTLIGHT, 0 },
01355 {"nolightmap", 0, SURF_NOLIGHTMAP,0 },
01356 {"nodlight", 0, SURF_NODLIGHT, 0 },
01357 {"dust", 0, SURF_DUST, 0}
01358 };
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368 static void ParseSurfaceParm( char **text ) {
01369 char *token;
01370 int numInfoParms = sizeof(infoParms) / sizeof(infoParms[0]);
01371 int i;
01372
01373 token = COM_ParseExt( text, qfalse );
01374 for ( i = 0 ; i < numInfoParms ; i++ ) {
01375 if ( !Q_stricmp( token, infoParms[i].name ) ) {
01376 shader.surfaceFlags |= infoParms[i].surfaceFlags;
01377 shader.contentFlags |= infoParms[i].contents;
01378 #if 0
01379 if ( infoParms[i].clearSolid ) {
01380 si->contents &= ~CONTENTS_SOLID;
01381 }
01382 #endif
01383 break;
01384 }
01385 }
01386 }
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397 static qboolean ParseShader( char **text )
01398 {
01399 char *token;
01400 int s;
01401
01402 s = 0;
01403
01404 token = COM_ParseExt( text, qtrue );
01405 if ( token[0] != '{' )
01406 {
01407 ri.Printf( PRINT_WARNING, "WARNING: expecting '{', found '%s' instead in shader '%s'\n", token, shader.name );
01408 return qfalse;
01409 }
01410
01411 while ( 1 )
01412 {
01413 token = COM_ParseExt( text, qtrue );
01414 if ( !token[0] )
01415 {
01416 ri.Printf( PRINT_WARNING, "WARNING: no concluding '}' in shader %s\n", shader.name );
01417 return qfalse;
01418 }
01419
01420
01421 if ( token[0] == '}' )
01422 {
01423 break;
01424 }
01425
01426 else if ( token[0] == '{' )
01427 {
01428 if ( !ParseStage( &stages[s], text ) )
01429 {
01430 return qfalse;
01431 }
01432 stages[s].active = qtrue;
01433 s++;
01434 continue;
01435 }
01436
01437 else if ( !Q_stricmpn( token, "qer", 3 ) ) {
01438 SkipRestOfLine( text );
01439 continue;
01440 }
01441
01442 else if ( !Q_stricmp( token, "q3map_sun" ) ) {
01443 float a, b;
01444
01445 token = COM_ParseExt( text, qfalse );
01446 tr.sunLight[0] = atof( token );
01447 token = COM_ParseExt( text, qfalse );
01448 tr.sunLight[1] = atof( token );
01449 token = COM_ParseExt( text, qfalse );
01450 tr.sunLight[2] = atof( token );
01451
01452 VectorNormalize( tr.sunLight );
01453
01454 token = COM_ParseExt( text, qfalse );
01455 a = atof( token );
01456 VectorScale( tr.sunLight, a, tr.sunLight);
01457
01458 token = COM_ParseExt( text, qfalse );
01459 a = atof( token );
01460 a = a / 180 * M_PI;
01461
01462 token = COM_ParseExt( text, qfalse );
01463 b = atof( token );
01464 b = b / 180 * M_PI;
01465
01466 tr.sunDirection[0] = cos( a ) * cos( b );
01467 tr.sunDirection[1] = sin( a ) * cos( b );
01468 tr.sunDirection[2] = sin( b );
01469 }
01470 else if ( !Q_stricmp( token, "deformVertexes" ) ) {
01471 ParseDeform( text );
01472 continue;
01473 }
01474 else if ( !Q_stricmp( token, "tesssize" ) ) {
01475 SkipRestOfLine( text );
01476 continue;
01477 }
01478 else if ( !Q_stricmp( token, "clampTime" ) ) {
01479 token = COM_ParseExt( text, qfalse );
01480 if (token[0]) {
01481 shader.clampTime = atof(token);
01482 }
01483 }
01484
01485 else if ( !Q_stricmpn( token, "q3map", 5 ) ) {
01486 SkipRestOfLine( text );
01487 continue;
01488 }
01489
01490 else if ( !Q_stricmp( token, "surfaceParm" ) ) {
01491 ParseSurfaceParm( text );
01492 continue;
01493 }
01494
01495 else if ( !Q_stricmp( token, "nomipmaps" ) )
01496 {
01497 shader.noMipMaps = qtrue;
01498 shader.noPicMip = qtrue;
01499 continue;
01500 }
01501
01502 else if ( !Q_stricmp( token, "nopicmip" ) )
01503 {
01504 shader.noPicMip = qtrue;
01505 continue;
01506 }
01507
01508 else if ( !Q_stricmp( token, "polygonOffset" ) )
01509 {
01510 shader.polygonOffset = qtrue;
01511 continue;
01512 }
01513
01514
01515
01516
01517 else if ( !Q_stricmp( token, "entityMergable" ) )
01518 {
01519 shader.entityMergable = qtrue;
01520 continue;
01521 }
01522
01523 else if ( !Q_stricmp( token, "fogParms" ) )
01524 {
01525 if ( !ParseVector( text, 3, shader.fogParms.color ) ) {
01526 return qfalse;
01527 }
01528
01529 token = COM_ParseExt( text, qfalse );
01530 if ( !token[0] )
01531 {
01532 ri.Printf( PRINT_WARNING, "WARNING: missing parm for 'fogParms' keyword in shader '%s'\n", shader.name );
01533 continue;
01534 }
01535 shader.fogParms.depthForOpaque = atof( token );
01536
01537
01538 SkipRestOfLine( text );
01539 continue;
01540 }
01541
01542 else if ( !Q_stricmp(token, "portal") )
01543 {
01544 shader.sort = SS_PORTAL;
01545 continue;
01546 }
01547
01548 else if ( !Q_stricmp( token, "skyparms" ) )
01549 {
01550 ParseSkyParms( text );
01551 continue;
01552 }
01553
01554 else if ( !Q_stricmp(token, "light") )
01555 {
01556 token = COM_ParseExt( text, qfalse );
01557 continue;
01558 }
01559
01560 else if ( !Q_stricmp( token, "cull") )
01561 {
01562 token = COM_ParseExt( text, qfalse );
01563 if ( token[0] == 0 )
01564 {
01565 ri.Printf( PRINT_WARNING, "WARNING: missing cull parms in shader '%s'\n", shader.name );
01566 continue;
01567 }
01568
01569 if ( !Q_stricmp( token, "none" ) || !Q_stricmp( token, "twosided" ) || !Q_stricmp( token, "disable" ) )
01570 {
01571 shader.cullType = CT_TWO_SIDED;
01572 }
01573 else if ( !Q_stricmp( token, "back" ) || !Q_stricmp( token, "backside" ) || !Q_stricmp( token, "backsided" ) )
01574 {
01575 shader.cullType = CT_BACK_SIDED;
01576 }
01577 else
01578 {
01579 ri.Printf( PRINT_WARNING, "WARNING: invalid cull parm '%s' in shader '%s'\n", token, shader.name );
01580 }
01581 continue;
01582 }
01583
01584 else if ( !Q_stricmp( token, "sort" ) )
01585 {
01586 ParseSort( text );
01587 continue;
01588 }
01589 else
01590 {
01591 ri.Printf( PRINT_WARNING, "WARNING: unknown general shader parameter '%s' in '%s'\n", token, shader.name );
01592 return qfalse;
01593 }
01594 }
01595
01596
01597
01598
01599 if ( s == 0 && !shader.isSky && !(shader.contentFlags & CONTENTS_FOG ) ) {
01600 return qfalse;
01601 }
01602
01603 shader.explicitlyDefined = qtrue;
01604
01605 return qtrue;
01606 }
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624 static void ComputeStageIteratorFunc( void )
01625 {
01626 shader.optimalStageIteratorFunc = RB_StageIteratorGeneric;
01627
01628
01629
01630
01631 if ( shader.isSky )
01632 {
01633 shader.optimalStageIteratorFunc = RB_StageIteratorSky;
01634 goto done;
01635 }
01636
01637 if ( r_ignoreFastPath->integer )
01638 {
01639 return;
01640 }
01641
01642
01643
01644
01645 if ( shader.numUnfoggedPasses == 1 )
01646 {
01647 if ( stages[0].rgbGen == CGEN_LIGHTING_DIFFUSE )
01648 {
01649 if ( stages[0].alphaGen == AGEN_IDENTITY )
01650 {
01651 if ( stages[0].bundle[0].tcGen == TCGEN_TEXTURE )
01652 {
01653 if ( !shader.polygonOffset )
01654 {
01655 if ( !shader.multitextureEnv )
01656 {
01657 if ( !shader.numDeforms )
01658 {
01659 shader.optimalStageIteratorFunc = RB_StageIteratorVertexLitTexture;
01660 goto done;
01661 }
01662 }
01663 }
01664 }
01665 }
01666 }
01667 }
01668
01669
01670
01671
01672 if ( shader.numUnfoggedPasses == 1 )
01673 {
01674 if ( ( stages[0].rgbGen == CGEN_IDENTITY ) && ( stages[0].alphaGen == AGEN_IDENTITY ) )
01675 {
01676 if ( stages[0].bundle[0].tcGen == TCGEN_TEXTURE &&
01677 stages[0].bundle[1].tcGen == TCGEN_LIGHTMAP )
01678 {
01679 if ( !shader.polygonOffset )
01680 {
01681 if ( !shader.numDeforms )
01682 {
01683 if ( shader.multitextureEnv )
01684 {
01685 shader.optimalStageIteratorFunc = RB_StageIteratorLightmappedMultitexture;
01686 goto done;
01687 }
01688 }
01689 }
01690 }
01691 }
01692 }
01693
01694 done:
01695 return;
01696 }
01697
01698 typedef struct {
01699 int blendA;
01700 int blendB;
01701
01702 int multitextureEnv;
01703 int multitextureBlend;
01704 } collapse_t;
01705
01706 static collapse_t collapse[] = {
01707 { 0, GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO,
01708 GL_MODULATE, 0 },
01709
01710 { 0, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR,
01711 GL_MODULATE, 0 },
01712
01713 { GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR,
01714 GL_MODULATE, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR },
01715
01716 { GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR,
01717 GL_MODULATE, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR },
01718
01719 { GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR, GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO,
01720 GL_MODULATE, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR },
01721
01722 { GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO, GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO,
01723 GL_MODULATE, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR },
01724
01725 { 0, GLS_DSTBLEND_ONE | GLS_SRCBLEND_ONE,
01726 GL_ADD, 0 },
01727
01728 { GLS_DSTBLEND_ONE | GLS_SRCBLEND_ONE, GLS_DSTBLEND_ONE | GLS_SRCBLEND_ONE,
01729 GL_ADD, GLS_DSTBLEND_ONE | GLS_SRCBLEND_ONE },
01730 #if 0
01731 { 0, GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_SRCBLEND_SRC_ALPHA,
01732 GL_DECAL, 0 },
01733 #endif
01734 { -1 }
01735 };
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745 static qboolean CollapseMultitexture( void ) {
01746 int abits, bbits;
01747 int i;
01748 textureBundle_t tmpBundle;
01749
01750 if ( !qglActiveTextureARB ) {
01751 return qfalse;
01752 }
01753
01754
01755 if ( !stages[0].active || !stages[1].active ) {
01756 return qfalse;
01757 }
01758
01759
01760 if ( glConfig.driverType == GLDRV_VOODOO ) {
01761 if ( stages[0].bundle[0].image[0]->TMU ==
01762 stages[1].bundle[0].image[0]->TMU ) {
01763 return qfalse;
01764 }
01765 }
01766
01767 abits = stages[0].stateBits;
01768 bbits = stages[1].stateBits;
01769
01770
01771 if ( ( abits & ~( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS | GLS_DEPTHMASK_TRUE ) ) !=
01772 ( bbits & ~( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS | GLS_DEPTHMASK_TRUE ) ) ) {
01773 return qfalse;
01774 }
01775
01776 abits &= ( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS );
01777 bbits &= ( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS );
01778
01779
01780 for ( i = 0; collapse[i].blendA != -1 ; i++ ) {
01781 if ( abits == collapse[i].blendA
01782 && bbits == collapse[i].blendB ) {
01783 break;
01784 }
01785 }
01786
01787
01788 if ( collapse[i].blendA == -1 ) {
01789 return qfalse;
01790 }
01791
01792
01793 if ( collapse[i].multitextureEnv == GL_ADD && !glConfig.textureEnvAddAvailable ) {
01794 return qfalse;
01795 }
01796
01797
01798 if ( ( stages[0].rgbGen != stages[1].rgbGen ) ||
01799 ( stages[0].alphaGen != stages[1].alphaGen ) ) {
01800 return qfalse;
01801 }
01802
01803
01804 if ( collapse[i].multitextureEnv == GL_ADD && stages[0].rgbGen != CGEN_IDENTITY ) {
01805 return qfalse;
01806 }
01807
01808 if ( stages[0].rgbGen == CGEN_WAVEFORM )
01809 {
01810 if ( memcmp( &stages[0].rgbWave,
01811 &stages[1].rgbWave,
01812 sizeof( stages[0].rgbWave ) ) )
01813 {
01814 return qfalse;
01815 }
01816 }
01817 if ( stages[0].alphaGen == CGEN_WAVEFORM )
01818 {
01819 if ( memcmp( &stages[0].alphaWave,
01820 &stages[1].alphaWave,
01821 sizeof( stages[0].alphaWave ) ) )
01822 {
01823 return qfalse;
01824 }
01825 }
01826
01827
01828
01829 if ( stages[0].bundle[0].isLightmap )
01830 {
01831 tmpBundle = stages[0].bundle[0];
01832 stages[0].bundle[0] = stages[1].bundle[0];
01833 stages[0].bundle[1] = tmpBundle;
01834 }
01835 else
01836 {
01837 stages[0].bundle[1] = stages[1].bundle[0];
01838 }
01839
01840
01841 shader.multitextureEnv = collapse[i].multitextureEnv;
01842 stages[0].stateBits &= ~( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS );
01843 stages[0].stateBits |= collapse[i].multitextureBlend;
01844
01845
01846
01847
01848 memmove( &stages[1], &stages[2], sizeof( stages[0] ) * ( MAX_SHADER_STAGES - 2 ) );
01849 Com_Memset( &stages[MAX_SHADER_STAGES-1], 0, sizeof( stages[0] ) );
01850
01851 return qtrue;
01852 }
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865 static void FixRenderCommandList( int newShader ) {
01866 renderCommandList_t *cmdList = &backEndData[tr.smpFrame]->commands;
01867
01868 if( cmdList ) {
01869 const void *curCmd = cmdList->cmds;
01870
01871 while ( 1 ) {
01872 switch ( *(const int *)curCmd ) {
01873 case RC_SET_COLOR:
01874 {
01875 const setColorCommand_t *sc_cmd = (const setColorCommand_t *)curCmd;
01876 curCmd = (const void *)(sc_cmd + 1);
01877 break;
01878 }
01879 case RC_STRETCH_PIC:
01880 {
01881 const stretchPicCommand_t *sp_cmd = (const stretchPicCommand_t *)curCmd;
01882 curCmd = (const void *)(sp_cmd + 1);
01883 break;
01884 }
01885 case RC_DRAW_SURFS:
01886 {
01887 int i;
01888 drawSurf_t *drawSurf;
01889 shader_t *shader;
01890 int fogNum;
01891 int entityNum;
01892 int dlightMap;
01893 int sortedIndex;
01894 const drawSurfsCommand_t *ds_cmd = (const drawSurfsCommand_t *)curCmd;
01895
01896 for( i = 0, drawSurf = ds_cmd->drawSurfs; i < ds_cmd->numDrawSurfs; i++, drawSurf++ ) {
01897 R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlightMap );
01898 sortedIndex = (( drawSurf->sort >> QSORT_SHADERNUM_SHIFT ) & (MAX_SHADERS-1));
01899 if( sortedIndex >= newShader ) {
01900 sortedIndex++;
01901 drawSurf->sort = (sortedIndex << QSORT_SHADERNUM_SHIFT) | entityNum | ( fogNum << QSORT_FOGNUM_SHIFT ) | (int)dlightMap;
01902 }
01903 }
01904 curCmd = (const void *)(ds_cmd + 1);
01905 break;
01906 }
01907 case RC_DRAW_BUFFER:
01908 {
01909 const drawBufferCommand_t *db_cmd = (const drawBufferCommand_t *)curCmd;
01910 curCmd = (const void *)(db_cmd + 1);
01911 break;
01912 }
01913 case RC_SWAP_BUFFERS:
01914 {
01915 const swapBuffersCommand_t *sb_cmd = (const swapBuffersCommand_t *)curCmd;
01916 curCmd = (const void *)(sb_cmd + 1);
01917 break;
01918 }
01919 case RC_END_OF_LIST:
01920 default:
01921 return;
01922 }
01923 }
01924 }
01925 }
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938 static void SortNewShader( void ) {
01939 int i;
01940 float sort;
01941 shader_t *newShader;
01942
01943 newShader = tr.shaders[ tr.numShaders - 1 ];
01944 sort = newShader->sort;
01945
01946 for ( i = tr.numShaders - 2 ; i >= 0 ; i-- ) {
01947 if ( tr.sortedShaders[ i ]->sort <= sort ) {
01948 break;
01949 }
01950 tr.sortedShaders[i+1] = tr.sortedShaders[i];
01951 tr.sortedShaders[i+1]->sortedIndex++;
01952 }
01953
01954
01955
01956 FixRenderCommandList( i+1 );
01957
01958 newShader->sortedIndex = i+1;
01959 tr.sortedShaders[i+1] = newShader;
01960 }
01961
01962
01963
01964
01965
01966
01967
01968 static shader_t *GeneratePermanentShader( void ) {
01969 shader_t *newShader;
01970 int i, b;
01971 int size, hash;
01972
01973 if ( tr.numShaders == MAX_SHADERS ) {
01974 ri.Printf( PRINT_WARNING, "WARNING: GeneratePermanentShader - MAX_SHADERS hit\n");
01975 return tr.defaultShader;
01976 }
01977
01978 newShader = ri.Hunk_Alloc( sizeof( shader_t ), h_low );
01979
01980 *newShader = shader;
01981
01982 if ( shader.sort <= SS_OPAQUE ) {
01983 newShader->fogPass = FP_EQUAL;
01984 } else if ( shader.contentFlags & CONTENTS_FOG ) {
01985 newShader->fogPass = FP_LE;
01986 }
01987
01988 tr.shaders[ tr.numShaders ] = newShader;
01989 newShader->index = tr.numShaders;
01990
01991 tr.sortedShaders[ tr.numShaders ] = newShader;
01992 newShader->sortedIndex = tr.numShaders;
01993
01994 tr.numShaders++;
01995
01996 for ( i = 0 ; i < newShader->numUnfoggedPasses ; i++ ) {
01997 if ( !stages[i].active ) {
01998 break;
01999 }
02000 newShader->stages[i] = ri.Hunk_Alloc( sizeof( stages[i] ), h_low );
02001 *newShader->stages[i] = stages[i];
02002
02003 for ( b = 0 ; b < NUM_TEXTURE_BUNDLES ; b++ ) {
02004 size = newShader->stages[i]->bundle[b].numTexMods * sizeof( texModInfo_t );
02005 newShader->stages[i]->bundle[b].texMods = ri.Hunk_Alloc( size, h_low );
02006 Com_Memcpy( newShader->stages[i]->bundle[b].texMods, stages[i].bundle[b].texMods, size );
02007 }
02008 }
02009
02010 SortNewShader();
02011
02012 hash = generateHashValue(newShader->name, FILE_HASH_SIZE);
02013 newShader->next = hashTable[hash];
02014 hashTable[hash] = newShader;
02015
02016 return newShader;
02017 }
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027
02028 static void VertexLightingCollapse( void ) {
02029 int stage;
02030 shaderStage_t *bestStage;
02031 int bestImageRank;
02032 int rank;
02033
02034
02035 if ( shader.sort == SS_OPAQUE ) {
02036
02037
02038 bestStage = &stages[0];
02039 bestImageRank = -999999;
02040
02041 for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ ) {
02042 shaderStage_t *pStage = &stages[stage];
02043
02044 if ( !pStage->active ) {
02045 break;
02046 }
02047 rank = 0;
02048
02049 if ( pStage->bundle[0].isLightmap ) {
02050 rank -= 100;
02051 }
02052 if ( pStage->bundle[0].tcGen != TCGEN_TEXTURE ) {
02053 rank -= 5;
02054 }
02055 if ( pStage->bundle[0].numTexMods ) {
02056 rank -= 5;
02057 }
02058 if ( pStage->rgbGen != CGEN_IDENTITY && pStage->rgbGen != CGEN_IDENTITY_LIGHTING ) {
02059 rank -= 3;
02060 }
02061
02062 if ( rank > bestImageRank ) {
02063 bestImageRank = rank;
02064 bestStage = pStage;
02065 }
02066 }
02067
02068 stages[0].bundle[0] = bestStage->bundle[0];
02069 stages[0].stateBits &= ~( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS );
02070 stages[0].stateBits |= GLS_DEPTHMASK_TRUE;
02071 if ( shader.lightmapIndex == LIGHTMAP_NONE ) {
02072 stages[0].rgbGen = CGEN_LIGHTING_DIFFUSE;
02073 } else {
02074 stages[0].rgbGen = CGEN_EXACT_VERTEX;
02075 }
02076 stages[0].alphaGen = AGEN_SKIP;
02077 } else {
02078
02079 if ( stages[0].bundle[0].isLightmap ) {
02080 stages[0] = stages[1];
02081 }
02082
02083
02084 if ( stages[0].rgbGen == CGEN_ONE_MINUS_ENTITY || stages[1].rgbGen == CGEN_ONE_MINUS_ENTITY ) {
02085 stages[0].rgbGen = CGEN_IDENTITY_LIGHTING;
02086 }
02087 if ( ( stages[0].rgbGen == CGEN_WAVEFORM && stages[0].rgbWave.func == GF_SAWTOOTH )
02088 && ( stages[1].rgbGen == CGEN_WAVEFORM && stages[1].rgbWave.func == GF_INVERSE_SAWTOOTH ) ) {
02089 stages[0].rgbGen = CGEN_IDENTITY_LIGHTING;
02090 }
02091 if ( ( stages[0].rgbGen == CGEN_WAVEFORM && stages[0].rgbWave.func == GF_INVERSE_SAWTOOTH )
02092 && ( stages[1].rgbGen == CGEN_WAVEFORM && stages[1].rgbWave.func == GF_SAWTOOTH ) ) {
02093 stages[0].rgbGen = CGEN_IDENTITY_LIGHTING;
02094 }
02095 }
02096
02097 for ( stage = 1; stage < MAX_SHADER_STAGES; stage++ ) {
02098 shaderStage_t *pStage = &stages[stage];
02099
02100 if ( !pStage->active ) {
02101 break;
02102 }
02103
02104 Com_Memset( pStage, 0, sizeof( *pStage ) );
02105 }
02106 }
02107
02108
02109
02110
02111
02112
02113
02114
02115
02116 static shader_t *FinishShader( void ) {
02117 int stage;
02118 qboolean hasLightmapStage;
02119 qboolean vertexLightmap;
02120
02121 hasLightmapStage = qfalse;
02122 vertexLightmap = qfalse;
02123
02124
02125
02126
02127 if ( shader.isSky ) {
02128 shader.sort = SS_ENVIRONMENT;
02129 }
02130
02131
02132
02133
02134 if ( shader.polygonOffset && !shader.sort ) {
02135 shader.sort = SS_DECAL;
02136 }
02137
02138
02139
02140
02141 for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ ) {
02142 shaderStage_t *pStage = &stages[stage];
02143
02144 if ( !pStage->active ) {
02145 break;
02146 }
02147
02148
02149 if ( !pStage->bundle[0].image[0] ) {
02150 ri.Printf( PRINT_WARNING, "Shader %s has a stage with no image\n", shader.name );
02151 pStage->active = qfalse;
02152 continue;
02153 }
02154
02155
02156
02157
02158 if ( pStage->isDetail && !r_detailTextures->integer ) {
02159 if ( stage < ( MAX_SHADER_STAGES - 1 ) ) {
02160 memmove( pStage, pStage + 1, sizeof( *pStage ) * ( MAX_SHADER_STAGES - stage - 1 ) );
02161 Com_Memset( pStage + 1, 0, sizeof( *pStage ) );
02162 }
02163 continue;
02164 }
02165
02166
02167
02168
02169 if ( pStage->bundle[0].isLightmap ) {
02170 if ( pStage->bundle[0].tcGen == TCGEN_BAD ) {
02171 pStage->bundle[0].tcGen = TCGEN_LIGHTMAP;
02172 }
02173 hasLightmapStage = qtrue;
02174 } else {
02175 if ( pStage->bundle[0].tcGen == TCGEN_BAD ) {
02176 pStage->bundle[0].tcGen = TCGEN_TEXTURE;
02177 }
02178 }
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192 if ( ( pStage->stateBits & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) ) &&
02193 ( stages[0].stateBits & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) ) ) {
02194 int blendSrcBits = pStage->stateBits & GLS_SRCBLEND_BITS;
02195 int blendDstBits = pStage->stateBits & GLS_DSTBLEND_BITS;
02196
02197
02198
02199
02200
02201
02202
02203
02204 if ( ( ( blendSrcBits == GLS_SRCBLEND_ONE ) && ( blendDstBits == GLS_DSTBLEND_ONE ) ) ||
02205 ( ( blendSrcBits == GLS_SRCBLEND_ZERO ) && ( blendDstBits == GLS_DSTBLEND_ONE_MINUS_SRC_COLOR ) ) ) {
02206 pStage->adjustColorsForFog = ACFF_MODULATE_RGB;
02207 }
02208
02209 else if ( ( blendSrcBits == GLS_SRCBLEND_SRC_ALPHA ) && ( blendDstBits == GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ) )
02210 {
02211 pStage->adjustColorsForFog = ACFF_MODULATE_ALPHA;
02212 }
02213
02214 else if ( ( blendSrcBits == GLS_SRCBLEND_ONE ) && ( blendDstBits == GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ) )
02215 {
02216 pStage->adjustColorsForFog = ACFF_MODULATE_RGBA;
02217 } else {
02218
02219 }
02220
02221
02222 if ( !shader.sort ) {
02223
02224 if ( pStage->stateBits & GLS_DEPTHMASK_TRUE ) {
02225 shader.sort = SS_SEE_THROUGH;
02226 } else {
02227 shader.sort = SS_BLEND0;
02228 }
02229 }
02230 }
02231 }
02232
02233
02234
02235 if ( !shader.sort ) {
02236 shader.sort = SS_OPAQUE;
02237 }
02238
02239
02240
02241
02242 if ( stage > 1 && ( (r_vertexLight->integer && !r_uiFullScreen->integer) || glConfig.hardwareType == GLHW_PERMEDIA2 ) ) {
02243 VertexLightingCollapse();
02244 stage = 1;
02245 hasLightmapStage = qfalse;
02246 }
02247
02248
02249
02250
02251 if ( stage > 1 && CollapseMultitexture() ) {
02252 stage--;
02253 }
02254
02255 if ( shader.lightmapIndex >= 0 && !hasLightmapStage ) {
02256 if (vertexLightmap) {
02257 ri.Printf( PRINT_DEVELOPER, "WARNING: shader '%s' has VERTEX forced lightmap!\n", shader.name );
02258 } else {
02259 ri.Printf( PRINT_DEVELOPER, "WARNING: shader '%s' has lightmap but no lightmap stage!\n", shader.name );
02260 shader.lightmapIndex = LIGHTMAP_NONE;
02261 }
02262 }
02263
02264
02265
02266
02267
02268 shader.numUnfoggedPasses = stage;
02269
02270
02271 if ( stage == 0 ) {
02272 shader.sort = SS_FOG;
02273 }
02274
02275
02276 ComputeStageIteratorFunc();
02277
02278 return GeneratePermanentShader();
02279 }
02280
02281
02282
02283
02284
02285
02286
02287
02288
02289
02290
02291
02292
02293
02294
02295 static char *FindShaderInShaderText( const char *shadername ) {
02296
02297 char *token, *p;
02298
02299 int i, hash;
02300
02301 hash = generateHashValue(shadername, MAX_SHADERTEXT_HASH);
02302
02303 for (i = 0; shaderTextHashTable[hash][i]; i++) {
02304 p = shaderTextHashTable[hash][i];
02305 token = COM_ParseExt(&p, qtrue);
02306 if ( !Q_stricmp( token, shadername ) ) {
02307 return p;
02308 }
02309 }
02310
02311 p = s_shaderText;
02312
02313 if ( !p ) {
02314 return NULL;
02315 }
02316
02317
02318 while ( 1 ) {
02319 token = COM_ParseExt( &p, qtrue );
02320 if ( token[0] == 0 ) {
02321 break;
02322 }
02323
02324 if ( !Q_stricmp( token, shadername ) ) {
02325 return p;
02326 }
02327 else {
02328
02329 SkipBracedSection( &p );
02330 }
02331 }
02332
02333 return NULL;
02334 }
02335
02336
02337
02338
02339
02340
02341
02342
02343
02344
02345 shader_t *R_FindShaderByName( const char *name ) {
02346 char strippedName[MAX_QPATH];
02347 int hash;
02348 shader_t *sh;
02349
02350 if ( (name==NULL) || (name[0] == 0) ) {
02351 return tr.defaultShader;
02352 }
02353
02354 COM_StripExtension( name, strippedName );
02355
02356 hash = generateHashValue(strippedName, FILE_HASH_SIZE);
02357
02358
02359
02360
02361 for (sh=hashTable[hash]; sh; sh=sh->next) {
02362
02363
02364
02365
02366 if (Q_stricmp(sh->name, strippedName) == 0) {
02367
02368 return sh;
02369 }
02370 }
02371
02372 return tr.defaultShader;
02373 }
02374
02375
02376
02377
02378
02379
02380
02381
02382
02383
02384
02385
02386
02387
02388
02389
02390
02391
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403
02404 shader_t *R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImage ) {
02405 char strippedName[MAX_QPATH];
02406 char fileName[MAX_QPATH];
02407 int i, hash;
02408 char *shaderText;
02409 image_t *image;
02410 shader_t *sh;
02411
02412 if ( name[0] == 0 ) {
02413 return tr.defaultShader;
02414 }
02415
02416
02417
02418 if ( lightmapIndex >= 0 && lightmapIndex >= tr.numLightmaps ) {
02419 lightmapIndex = LIGHTMAP_BY_VERTEX;
02420 }
02421
02422 COM_StripExtension( name, strippedName );
02423
02424 hash = generateHashValue(strippedName, FILE_HASH_SIZE);
02425
02426
02427
02428
02429 for (sh = hashTable[hash]; sh; sh = sh->next) {
02430
02431
02432
02433
02434 if ( (sh->lightmapIndex == lightmapIndex || sh->defaultShader) &&
02435 !Q_stricmp(sh->name, strippedName)) {
02436
02437 return sh;
02438 }
02439 }
02440
02441
02442
02443 if (r_smp->integer) {
02444 R_SyncRenderThread();
02445 }
02446
02447
02448 Com_Memset( &shader, 0, sizeof( shader ) );
02449 Com_Memset( &stages, 0, sizeof( stages ) );
02450 Q_strncpyz(shader.name, strippedName, sizeof(shader.name));
02451 shader.lightmapIndex = lightmapIndex;
02452 for ( i = 0 ; i < MAX_SHADER_STAGES ; i++ ) {
02453 stages[i].bundle[0].texMods = texMods[i];
02454 }
02455
02456
02457 shader.needsNormal = qtrue;
02458 shader.needsST1 = qtrue;
02459 shader.needsST2 = qtrue;
02460 shader.needsColor = qtrue;
02461
02462
02463
02464
02465 shaderText = FindShaderInShaderText( strippedName );
02466 if ( shaderText ) {
02467
02468
02469 if ( r_printShaders->integer ) {
02470 ri.Printf( PRINT_ALL, "*SHADER* %s\n", name );
02471 }
02472
02473 if ( !ParseShader( &shaderText ) ) {
02474
02475 shader.defaultShader = qtrue;
02476 }
02477 sh = FinishShader();
02478 return sh;
02479 }
02480
02481
02482
02483
02484
02485
02486 Q_strncpyz( fileName, name, sizeof( fileName ) );
02487 COM_DefaultExtension( fileName, sizeof( fileName ), ".tga" );
02488 image = R_FindImageFile( fileName, mipRawImage, mipRawImage, mipRawImage ? GL_REPEAT : GL_CLAMP );
02489 if ( !image ) {
02490 ri.Printf( PRINT_DEVELOPER, "Couldn't find image for shader %s\n", name );
02491 shader.defaultShader = qtrue;
02492 return FinishShader();
02493 }
02494
02495
02496
02497
02498 if ( shader.lightmapIndex == LIGHTMAP_NONE ) {
02499
02500 stages[0].bundle[0].image[0] = image;
02501 stages[0].active = qtrue;
02502 stages[0].rgbGen = CGEN_LIGHTING_DIFFUSE;
02503 stages[0].stateBits = GLS_DEFAULT;
02504 } else if ( shader.lightmapIndex == LIGHTMAP_BY_VERTEX ) {
02505
02506 stages[0].bundle[0].image[0] = image;
02507 stages[0].active = qtrue;
02508 stages[0].rgbGen = CGEN_EXACT_VERTEX;
02509 stages[0].alphaGen = AGEN_SKIP;
02510 stages[0].stateBits = GLS_DEFAULT;
02511 } else if ( shader.lightmapIndex == LIGHTMAP_2D ) {
02512
02513 stages[0].bundle[0].image[0] = image;
02514 stages[0].active = qtrue;
02515 stages[0].rgbGen = CGEN_VERTEX;
02516 stages[0].alphaGen = AGEN_VERTEX;
02517 stages[0].stateBits = GLS_DEPTHTEST_DISABLE |
02518 GLS_SRCBLEND_SRC_ALPHA |
02519 GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA;
02520 } else if ( shader.lightmapIndex == LIGHTMAP_WHITEIMAGE ) {
02521
02522 stages[0].bundle[0].image[0] = tr.whiteImage;
02523 stages[0].active = qtrue;
02524 stages[0].rgbGen = CGEN_IDENTITY_LIGHTING;
02525 stages[0].stateBits = GLS_DEFAULT;
02526
02527 stages[1].bundle[0].image[0] = image;
02528 stages[1].active = qtrue;
02529 stages[1].rgbGen = CGEN_IDENTITY;
02530 stages[1].stateBits |= GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO;
02531 } else {
02532
02533 stages[0].bundle[0].image[0] = tr.lightmaps[shader.lightmapIndex];
02534 stages[0].bundle[0].isLightmap = qtrue;
02535 stages[0].active = qtrue;
02536 stages[0].rgbGen = CGEN_IDENTITY;
02537
02538 stages[0].stateBits = GLS_DEFAULT;
02539
02540 stages[1].bundle[0].image[0] = image;
02541 stages[1].active = qtrue;
02542 stages[1].rgbGen = CGEN_IDENTITY;
02543 stages[1].stateBits |= GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO;
02544 }
02545
02546 return FinishShader();
02547 }
02548
02549
02550 qhandle_t RE_RegisterShaderFromImage(const char *name, int lightmapIndex, image_t *image, qboolean mipRawImage) {
02551 int i, hash;
02552 shader_t *sh;
02553
02554 hash = generateHashValue(name, FILE_HASH_SIZE);
02555
02556
02557
02558
02559 for (sh=hashTable[hash]; sh; sh=sh->next) {
02560
02561
02562
02563
02564 if ( (sh->lightmapIndex == lightmapIndex || sh->defaultShader) &&
02565
02566 !Q_stricmp(sh->name, name)) {
02567
02568 return sh->index;
02569 }
02570 }
02571
02572
02573
02574 if (r_smp->integer) {
02575 R_SyncRenderThread();
02576 }
02577
02578
02579 Com_Memset( &shader, 0, sizeof( shader ) );
02580 Com_Memset( &stages, 0, sizeof( stages ) );
02581 Q_strncpyz(shader.name, name, sizeof(shader.name));
02582 shader.lightmapIndex = lightmapIndex;
02583 for ( i = 0 ; i < MAX_SHADER_STAGES ; i++ ) {
02584 stages[i].bundle[0].texMods = texMods[i];
02585 }
02586
02587
02588 shader.needsNormal = qtrue;
02589 shader.needsST1 = qtrue;
02590 shader.needsST2 = qtrue;
02591 shader.needsColor = qtrue;
02592
02593
02594
02595
02596 if ( shader.lightmapIndex == LIGHTMAP_NONE ) {
02597
02598 stages[0].bundle[0].image[0] = image;
02599 stages[0].active = qtrue;
02600 stages[0].rgbGen = CGEN_LIGHTING_DIFFUSE;
02601 stages[0].stateBits = GLS_DEFAULT;
02602 } else if ( shader.lightmapIndex == LIGHTMAP_BY_VERTEX ) {
02603
02604 stages[0].bundle[0].image[0] = image;
02605 stages[0].active = qtrue;
02606 stages[0].rgbGen = CGEN_EXACT_VERTEX;
02607 stages[0].alphaGen = AGEN_SKIP;
02608 stages[0].stateBits = GLS_DEFAULT;
02609 } else if ( shader.lightmapIndex == LIGHTMAP_2D ) {
02610
02611 stages[0].bundle[0].image[0] = image;
02612 stages[0].active = qtrue;
02613 stages[0].rgbGen = CGEN_VERTEX;
02614 stages[0].alphaGen = AGEN_VERTEX;
02615 stages[0].stateBits = GLS_DEPTHTEST_DISABLE |
02616 GLS_SRCBLEND_SRC_ALPHA |
02617 GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA;
02618 } else if ( shader.lightmapIndex == LIGHTMAP_WHITEIMAGE ) {
02619
02620 stages[0].bundle[0].image[0] = tr.whiteImage;
02621 stages[0].active = qtrue;
02622 stages[0].rgbGen = CGEN_IDENTITY_LIGHTING;
02623 stages[0].stateBits = GLS_DEFAULT;
02624
02625 stages[1].bundle[0].image[0] = image;
02626 stages[1].active = qtrue;
02627 stages[1].rgbGen = CGEN_IDENTITY;
02628 stages[1].stateBits |= GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO;
02629 } else {
02630
02631 stages[0].bundle[0].image[0] = tr.lightmaps[shader.lightmapIndex];
02632 stages[0].bundle[0].isLightmap = qtrue;
02633 stages[0].active = qtrue;
02634 stages[0].rgbGen = CGEN_IDENTITY;
02635
02636 stages[0].stateBits = GLS_DEFAULT;
02637
02638 stages[1].bundle[0].image[0] = image;
02639 stages[1].active = qtrue;
02640 stages[1].rgbGen = CGEN_IDENTITY;
02641 stages[1].stateBits |= GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO;
02642 }
02643
02644 sh = FinishShader();
02645 return sh->index;
02646 }
02647
02648
02649
02650
02651
02652
02653
02654
02655
02656
02657
02658
02659
02660 qhandle_t RE_RegisterShaderLightMap( const char *name, int lightmapIndex ) {
02661 shader_t *sh;
02662
02663 if ( strlen( name ) >= MAX_QPATH ) {
02664 Com_Printf( "Shader name exceeds MAX_QPATH\n" );
02665 return 0;
02666 }
02667
02668 sh = R_FindShader( name, lightmapIndex, qtrue );
02669
02670
02671
02672
02673
02674
02675 if ( sh->defaultShader ) {
02676 return 0;
02677 }
02678
02679 return sh->index;
02680 }
02681
02682
02683
02684
02685
02686
02687
02688
02689
02690
02691
02692
02693
02694 qhandle_t RE_RegisterShader( const char *name ) {
02695 shader_t *sh;
02696
02697 if ( strlen( name ) >= MAX_QPATH ) {
02698 Com_Printf( "Shader name exceeds MAX_QPATH\n" );
02699 return 0;
02700 }
02701
02702 sh = R_FindShader( name, LIGHTMAP_2D, qtrue );
02703
02704
02705
02706
02707
02708
02709 if ( sh->defaultShader ) {
02710 return 0;
02711 }
02712
02713 return sh->index;
02714 }
02715
02716
02717
02718
02719
02720
02721
02722
02723
02724 qhandle_t RE_RegisterShaderNoMip( const char *name ) {
02725 shader_t *sh;
02726
02727 if ( strlen( name ) >= MAX_QPATH ) {
02728 Com_Printf( "Shader name exceeds MAX_QPATH\n" );
02729 return 0;
02730 }
02731
02732 sh = R_FindShader( name, LIGHTMAP_2D, qfalse );
02733
02734
02735
02736
02737
02738
02739 if ( sh->defaultShader ) {
02740 return 0;
02741 }
02742
02743 return sh->index;
02744 }
02745
02746
02747
02748
02749
02750
02751
02752
02753
02754
02755 shader_t *R_GetShaderByHandle( qhandle_t hShader ) {
02756 if ( hShader < 0 ) {
02757 ri.Printf( PRINT_WARNING, "R_GetShaderByHandle: out of range hShader '%d'\n", hShader );
02758 return tr.defaultShader;
02759 }
02760 if ( hShader >= tr.numShaders ) {
02761 ri.Printf( PRINT_WARNING, "R_GetShaderByHandle: out of range hShader '%d'\n", hShader );
02762 return tr.defaultShader;
02763 }
02764 return tr.shaders[hShader];
02765 }
02766
02767
02768
02769
02770
02771
02772
02773
02774
02775 void R_ShaderList_f (void) {
02776 int i;
02777 int count;
02778 shader_t *shader;
02779
02780 ri.Printf (PRINT_ALL, "-----------------------\n");
02781
02782 count = 0;
02783 for ( i = 0 ; i < tr.numShaders ; i++ ) {
02784 if ( ri.Cmd_Argc() > 1 ) {
02785 shader = tr.sortedShaders[i];
02786 } else {
02787 shader = tr.shaders[i];
02788 }
02789
02790 ri.Printf( PRINT_ALL, "%i ", shader->numUnfoggedPasses );
02791
02792 if (shader->lightmapIndex >= 0 ) {
02793 ri.Printf (PRINT_ALL, "L ");
02794 } else {
02795 ri.Printf (PRINT_ALL, " ");
02796 }
02797 if ( shader->multitextureEnv == GL_ADD ) {
02798 ri.Printf( PRINT_ALL, "MT(a) " );
02799 } else if ( shader->multitextureEnv == GL_MODULATE ) {
02800 ri.Printf( PRINT_ALL, "MT(m) " );
02801 } else if ( shader->multitextureEnv == GL_DECAL ) {
02802 ri.Printf( PRINT_ALL, "MT(d) " );
02803 } else {
02804 ri.Printf( PRINT_ALL, " " );
02805 }
02806 if ( shader->explicitlyDefined ) {
02807 ri.Printf( PRINT_ALL, "E " );
02808 } else {
02809 ri.Printf( PRINT_ALL, " " );
02810 }
02811
02812 if ( shader->optimalStageIteratorFunc == RB_StageIteratorGeneric ) {
02813 ri.Printf( PRINT_ALL, "gen " );
02814 } else if ( shader->optimalStageIteratorFunc == RB_StageIteratorSky ) {
02815 ri.Printf( PRINT_ALL, "sky " );
02816 } else if ( shader->optimalStageIteratorFunc == RB_StageIteratorLightmappedMultitexture ) {
02817 ri.Printf( PRINT_ALL, "lmmt" );
02818 } else if ( shader->optimalStageIteratorFunc == RB_StageIteratorVertexLitTexture ) {
02819 ri.Printf( PRINT_ALL, "vlt " );
02820 } else {
02821 ri.Printf( PRINT_ALL, " " );
02822 }
02823
02824 if ( shader->defaultShader ) {
02825 ri.Printf (PRINT_ALL, ": %s (DEFAULTED)\n", shader->name);
02826 } else {
02827 ri.Printf (PRINT_ALL, ": %s\n", shader->name);
02828 }
02829 count++;
02830 }
02831 ri.Printf (PRINT_ALL, "%i total shaders\n", count);
02832 ri.Printf (PRINT_ALL, "------------------\n");
02833 }
02834
02835
02836
02837
02838
02839
02840
02841
02842
02843
02844 #define MAX_SHADER_FILES 4096
02845 static void ScanAndLoadShaderFiles( void )
02846 {
02847 char **shaderFiles;
02848 char *buffers[MAX_SHADER_FILES];
02849 char *p;
02850 int numShaders;
02851 int i;
02852 char *oldp, *token, *hashMem;
02853 int shaderTextHashTableSizes[MAX_SHADERTEXT_HASH], hash, size;
02854
02855 long sum = 0;
02856
02857 shaderFiles = ri.FS_ListFiles( "scripts", ".shader", &numShaders );
02858
02859 if ( !shaderFiles || !numShaders )
02860 {
02861 ri.Printf( PRINT_WARNING, "WARNING: no shader files found\n" );
02862 return;
02863 }
02864
02865 if ( numShaders > MAX_SHADER_FILES ) {
02866 numShaders = MAX_SHADER_FILES;
02867 }
02868
02869
02870 for ( i = 0; i < numShaders; i++ )
02871 {
02872 char filename[MAX_QPATH];
02873
02874 Com_sprintf( filename, sizeof( filename ), "scripts/%s", shaderFiles[i] );
02875 ri.Printf( PRINT_ALL, "...loading '%s'\n", filename );
02876 sum += ri.FS_ReadFile( filename, (void **)&buffers[i] );
02877 if ( !buffers[i] ) {
02878 ri.Error( ERR_DROP, "Couldn't load %s", filename );
02879 }
02880 }
02881
02882
02883 s_shaderText = ri.Hunk_Alloc( sum + numShaders*2, h_low );
02884
02885
02886 for ( i = numShaders - 1; i >= 0 ; i-- ) {
02887 strcat( s_shaderText, "\n" );
02888 p = &s_shaderText[strlen(s_shaderText)];
02889 strcat( s_shaderText, buffers[i] );
02890 ri.FS_FreeFile( buffers[i] );
02891 buffers[i] = p;
02892 COM_Compress(p);
02893 }
02894
02895
02896 ri.FS_FreeFileList( shaderFiles );
02897
02898 Com_Memset(shaderTextHashTableSizes, 0, sizeof(shaderTextHashTableSizes));
02899 size = 0;
02900
02901 for ( i = 0; i < numShaders; i++ ) {
02902
02903 p = buffers[i];
02904
02905 while ( 1 ) {
02906 token = COM_ParseExt( &p, qtrue );
02907 if ( token[0] == 0 ) {
02908 break;
02909 }
02910
02911 hash = generateHashValue(token, MAX_SHADERTEXT_HASH);
02912 shaderTextHashTableSizes[hash]++;
02913 size++;
02914 SkipBracedSection(&p);
02915
02916 if ( i < numShaders - 1 ) {
02917 if ( p > buffers[i+1] ) {
02918 break;
02919 }
02920 }
02921 }
02922 }
02923
02924 size += MAX_SHADERTEXT_HASH;
02925
02926 hashMem = ri.Hunk_Alloc( size * sizeof(char *), h_low );
02927
02928 for (i = 0; i < MAX_SHADERTEXT_HASH; i++) {
02929 shaderTextHashTable[i] = (char **) hashMem;
02930 hashMem = ((char *) hashMem) + ((shaderTextHashTableSizes[i] + 1) * sizeof(char *));
02931 }
02932
02933 Com_Memset(shaderTextHashTableSizes, 0, sizeof(shaderTextHashTableSizes));
02934
02935 for ( i = 0; i < numShaders; i++ ) {
02936
02937 p = buffers[i];
02938
02939 while ( 1 ) {
02940 oldp = p;
02941 token = COM_ParseExt( &p, qtrue );
02942 if ( token[0] == 0 ) {
02943 break;
02944 }
02945
02946 hash = generateHashValue(token, MAX_SHADERTEXT_HASH);
02947 shaderTextHashTable[hash][shaderTextHashTableSizes[hash]++] = oldp;
02948
02949 SkipBracedSection(&p);
02950
02951 if ( i < numShaders - 1 ) {
02952 if ( p > buffers[i+1] ) {
02953 break;
02954 }
02955 }
02956 }
02957 }
02958
02959 return;
02960
02961 }
02962
02963
02964
02965
02966
02967
02968
02969 static void CreateInternalShaders( void ) {
02970 tr.numShaders = 0;
02971
02972
02973 Com_Memset( &shader, 0, sizeof( shader ) );
02974 Com_Memset( &stages, 0, sizeof( stages ) );
02975
02976 Q_strncpyz( shader.name, "<default>", sizeof( shader.name ) );
02977
02978 shader.lightmapIndex = LIGHTMAP_NONE;
02979 stages[0].bundle[0].image[0] = tr.defaultImage;
02980 stages[0].active = qtrue;
02981 stages[0].stateBits = GLS_DEFAULT;
02982 tr.defaultShader = FinishShader();
02983
02984
02985 Q_strncpyz( shader.name, "<stencil shadow>", sizeof( shader.name ) );
02986 shader.sort = SS_STENCIL_SHADOW;
02987 tr.shadowShader = FinishShader();
02988 }
02989
02990 static void CreateExternalShaders( void ) {
02991 tr.projectionShadowShader = R_FindShader( "projectionShadow", LIGHTMAP_NONE, qtrue );
02992 tr.flareShader = R_FindShader( "flareShader", LIGHTMAP_NONE, qtrue );
02993 tr.sunShader = R_FindShader( "sun", LIGHTMAP_NONE, qtrue );
02994 }
02995
02996
02997
02998
02999
03000
03001 void R_InitShaders( void ) {
03002 ri.Printf( PRINT_ALL, "Initializing Shaders\n" );
03003
03004 Com_Memset(hashTable, 0, sizeof(hashTable));
03005
03006 deferLoad = qfalse;
03007
03008 CreateInternalShaders();
03009
03010 ScanAndLoadShaderFiles();
03011
03012 CreateExternalShaders();
03013 }