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->