1 /*
2 ===========================================================================
3
4 Return to Castle Wolfenstein single player GPL Source Code
5 Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
6
7 This file is part of the Return to Castle Wolfenstein single player GPL Source Code (RTCW SP Source Code).
8
9 RTCW SP Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 RTCW SP Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
21
22 In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
23
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25
26 ===========================================================================
27 */
28
29 #include "tr_local.h"
30
31 // tr_shader.c -- this file deals with the parsing and definition of shaders
32
33 static char *s_shaderText;
34
35 // the shader is parsed into these global variables, then copied into
36 // dynamically allocated memory if it is valid.
37 static shaderStage_t stages[MAX_SHADER_STAGES];
38 static shader_t shader;
39 static texModInfo_t texMods[MAX_SHADER_STAGES][TR_MAX_TEXMODS];
40
41 #define FILE_HASH_SIZE 4096
42
43 static shader_t* hashTable[FILE_HASH_SIZE];
44
45 // Ridah
46 // Table containing string indexes for each shader found in the scripts, referenced by their checksum
47 // values.
48 typedef struct shaderStringPointer_s
49 {
50 char *pStr;
51 struct shaderStringPointer_s *next;
52 } shaderStringPointer_t;
53 //
54 shaderStringPointer_t shaderChecksumLookup[FILE_HASH_SIZE];
55 // done.
56
57 /*
58 ================
59 return a hash value for the filename
60 ================
61 */
62 #ifdef __GNUCC__
63 #warning TODO: check if long is ok here
64 #endif
generateHashValue(const char * fname)65 static long generateHashValue( const char *fname ) {
66 int i;
67 long hash;
68 char letter;
69
70 hash = 0;
71 i = 0;
72 while ( fname[i] != '\0' ) {
73 letter = tolower( fname[i] );
74 if ( letter == '.' ) {
75 break; // don't include extension
76 }
77 if ( letter == '\\' ) {
78 letter = '/'; // damn path names
79 }
80 if ( letter == PATH_SEP ) {
81 letter = '/'; // damn path names
82 }
83 hash += (long)( letter ) * ( i + 119 );
84 i++;
85 }
86 hash &= ( FILE_HASH_SIZE - 1 );
87 return hash;
88 }
89
R_RemapShader(const char * shaderName,const char * newShaderName,const char * timeOffset)90 void R_RemapShader( const char *shaderName, const char *newShaderName, const char *timeOffset ) {
91 char strippedName[MAX_QPATH];
92 int hash;
93 shader_t *sh, *sh2;
94 qhandle_t h;
95
96 sh = R_FindShaderByName( shaderName );
97 if ( sh == NULL || sh == tr.defaultShader ) {
98 h = RE_RegisterShaderLightMap( shaderName, 0 );
99 sh = R_GetShaderByHandle( h );
100 }
101 if ( sh == NULL || sh == tr.defaultShader ) {
102 ri.Printf( PRINT_WARNING, "WARNING: R_RemapShader: shader %s not found\n", shaderName );
103 return;
104 }
105
106 sh2 = R_FindShaderByName( newShaderName );
107 if ( sh2 == NULL || sh2 == tr.defaultShader ) {
108 h = RE_RegisterShaderLightMap( newShaderName, 0 );
109 sh2 = R_GetShaderByHandle( h );
110 }
111
112 if ( sh2 == NULL || sh2 == tr.defaultShader ) {
113 ri.Printf( PRINT_WARNING, "WARNING: R_RemapShader: new shader %s not found\n", newShaderName );
114 return;
115 }
116
117 // remap all the shaders with the given name
118 // even tho they might have different lightmaps
119 COM_StripExtension( shaderName, strippedName, sizeof( strippedName ) );
120 hash = generateHashValue( strippedName );
121 for ( sh = hashTable[hash]; sh; sh = sh->next ) {
122 if ( Q_stricmp( sh->name, strippedName ) == 0 ) {
123 if ( sh != sh2 ) {
124 sh->remappedShader = sh2;
125 } else {
126 sh->remappedShader = NULL;
127 }
128 }
129 }
130 if ( timeOffset ) {
131 sh2->timeOffset = atof( timeOffset );
132 }
133 }
134
135 /*
136 ===============
137 ParseVector
138 ===============
139 */
ParseVector(char ** text,int count,float * v)140 static qboolean ParseVector( char **text, int count, float *v ) {
141 char *token;
142 int i;
143
144 // FIXME: spaces are currently required after parens, should change parseext...
145 token = COM_ParseExt( text, qfalse );
146 if ( strcmp( token, "(" ) ) {
147 ri.Printf( PRINT_WARNING, "WARNING: missing parenthesis in shader '%s'\n", shader.name );
148 return qfalse;
149 }
150
151 for ( i = 0 ; i < count ; i++ ) {
152 token = COM_ParseExt( text, qfalse );
153 if ( !token[0] ) {
154 ri.Printf( PRINT_WARNING, "WARNING: missing vector element in shader '%s'\n", shader.name );
155 return qfalse;
156 }
157 v[i] = atof( token );
158 }
159
160 token = COM_ParseExt( text, qfalse );
161 if ( strcmp( token, ")" ) ) {
162 ri.Printf( PRINT_WARNING, "WARNING: missing parenthesis in shader '%s'\n", shader.name );
163 return qfalse;
164 }
165
166 return qtrue;
167 }
168
169
170 /*
171 ===============
172 NameToAFunc
173 ===============
174 */
NameToAFunc(const char * funcname)175 static unsigned NameToAFunc( const char *funcname ) {
176 if ( !Q_stricmp( funcname, "GT0" ) ) {
177 return GLS_ATEST_GT_0;
178 } else if ( !Q_stricmp( funcname, "LT128" ) ) {
179 return GLS_ATEST_LT_80;
180 } else if ( !Q_stricmp( funcname, "GE128" ) ) {
181 return GLS_ATEST_GE_80;
182 }
183
184 ri.Printf( PRINT_WARNING, "WARNING: invalid alphaFunc name '%s' in shader '%s'\n", funcname, shader.name );
185 return 0;
186 }
187
188
189 /*
190 ===============
191 NameToSrcBlendMode
192 ===============
193 */
NameToSrcBlendMode(const char * name)194 static int NameToSrcBlendMode( const char *name ) {
195 if ( !Q_stricmp( name, "GL_ONE" ) ) {
196 return GLS_SRCBLEND_ONE;
197 } else if ( !Q_stricmp( name, "GL_ZERO" ) ) {
198 return GLS_SRCBLEND_ZERO;
199 } else if ( !Q_stricmp( name, "GL_DST_COLOR" ) ) {
200 return GLS_SRCBLEND_DST_COLOR;
201 } else if ( !Q_stricmp( name, "GL_ONE_MINUS_DST_COLOR" ) ) {
202 return GLS_SRCBLEND_ONE_MINUS_DST_COLOR;
203 } else if ( !Q_stricmp( name, "GL_SRC_ALPHA" ) ) {
204 return GLS_SRCBLEND_SRC_ALPHA;
205 } else if ( !Q_stricmp( name, "GL_ONE_MINUS_SRC_ALPHA" ) ) {
206 return GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA;
207 } else if ( !Q_stricmp( name, "GL_DST_ALPHA" ) ) {
208 if (r_ignoreDstAlpha->integer)
209 return GLS_SRCBLEND_ONE;
210 return GLS_SRCBLEND_DST_ALPHA;
211 } else if ( !Q_stricmp( name, "GL_ONE_MINUS_DST_ALPHA" ) ) {
212 if (r_ignoreDstAlpha->integer)
213 return GLS_SRCBLEND_ZERO;
214 return GLS_SRCBLEND_ONE_MINUS_DST_ALPHA;
215 } else if ( !Q_stricmp( name, "GL_SRC_ALPHA_SATURATE" ) ) {
216 return GLS_SRCBLEND_ALPHA_SATURATE;
217 }
218
219 ri.Printf( PRINT_WARNING, "WARNING: unknown blend mode '%s' in shader '%s', substituting GL_ONE\n", name, shader.name );
220 return GLS_SRCBLEND_ONE;
221 }
222
223 /*
224 ===============
225 NameToDstBlendMode
226 ===============
227 */
NameToDstBlendMode(const char * name)228 static int NameToDstBlendMode( const char *name ) {
229 if ( !Q_stricmp( name, "GL_ONE" ) ) {
230 return GLS_DSTBLEND_ONE;
231 } else if ( !Q_stricmp( name, "GL_ZERO" ) ) {
232 return GLS_DSTBLEND_ZERO;
233 } else if ( !Q_stricmp( name, "GL_SRC_ALPHA" ) ) {
234 return GLS_DSTBLEND_SRC_ALPHA;
235 } else if ( !Q_stricmp( name, "GL_ONE_MINUS_SRC_ALPHA" ) ) {
236 return GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA;
237 } else if ( !Q_stricmp( name, "GL_DST_ALPHA" ) ) {
238 if (r_ignoreDstAlpha->integer)
239 return GLS_DSTBLEND_ONE;
240 return GLS_DSTBLEND_DST_ALPHA;
241 } else if ( !Q_stricmp( name, "GL_ONE_MINUS_DST_ALPHA" ) ) {
242 if (r_ignoreDstAlpha->integer)
243 return GLS_DSTBLEND_ZERO;
244 return GLS_DSTBLEND_ONE_MINUS_DST_ALPHA;
245 } else if ( !Q_stricmp( name, "GL_SRC_COLOR" ) ) {
246 return GLS_DSTBLEND_SRC_COLOR;
247 } else if ( !Q_stricmp( name, "GL_ONE_MINUS_SRC_COLOR" ) ) {
248 return GLS_DSTBLEND_ONE_MINUS_SRC_COLOR;
249 }
250
251 ri.Printf( PRINT_WARNING, "WARNING: unknown blend mode '%s' in shader '%s', substituting GL_ONE\n", name, shader.name );
252 return GLS_DSTBLEND_ONE;
253 }
254
255 /*
256 ===============
257 NameToGenFunc
258 ===============
259 */
NameToGenFunc(const char * funcname)260 static genFunc_t NameToGenFunc( const char *funcname ) {
261 if ( !Q_stricmp( funcname, "sin" ) ) {
262 return GF_SIN;
263 } else if ( !Q_stricmp( funcname, "square" ) ) {
264 return GF_SQUARE;
265 } else if ( !Q_stricmp( funcname, "triangle" ) ) {
266 return GF_TRIANGLE;
267 } else if ( !Q_stricmp( funcname, "sawtooth" ) ) {
268 return GF_SAWTOOTH;
269 } else if ( !Q_stricmp( funcname, "inversesawtooth" ) ) {
270 return GF_INVERSE_SAWTOOTH;
271 } else if ( !Q_stricmp( funcname, "noise" ) ) {
272 return GF_NOISE;
273 }
274
275 ri.Printf( PRINT_WARNING, "WARNING: invalid genfunc name '%s' in shader '%s'\n", funcname, shader.name );
276 return GF_SIN;
277 }
278
279
280 /*
281 ===================
282 ParseWaveForm
283 ===================
284 */
ParseWaveForm(char ** text,waveForm_t * wave)285 static void ParseWaveForm( char **text, waveForm_t *wave ) {
286 char *token;
287
288 token = COM_ParseExt( text, qfalse );
289 if ( token[0] == 0 ) {
290 ri.Printf( PRINT_WARNING, "WARNING: missing waveform parm in shader '%s'\n", shader.name );
291 return;
292 }
293 wave->func = NameToGenFunc( token );
294
295 // BASE, AMP, PHASE, FREQ
296 token = COM_ParseExt( text, qfalse );
297 if ( token[0] == 0 ) {
298 ri.Printf( PRINT_WARNING, "WARNING: missing waveform parm in shader '%s'\n", shader.name );
299 return;
300 }
301 wave->base = atof( token );
302
303 token = COM_ParseExt( text, qfalse );
304 if ( token[0] == 0 ) {
305 ri.Printf( PRINT_WARNING, "WARNING: missing waveform parm in shader '%s'\n", shader.name );
306 return;
307 }
308 wave->amplitude = atof( token );
309
310 token = COM_ParseExt( text, qfalse );
311 if ( token[0] == 0 ) {
312 ri.Printf( PRINT_WARNING, "WARNING: missing waveform parm in shader '%s'\n", shader.name );
313 return;
314 }
315 wave->phase = atof( token );
316
317 token = COM_ParseExt( text, qfalse );
318 if ( token[0] == 0 ) {
319 ri.Printf( PRINT_WARNING, "WARNING: missing waveform parm in shader '%s'\n", shader.name );
320 return;
321 }
322 wave->frequency = atof( token );
323 }
324
325
326 /*
327 ===================
328 ParseTexMod
329 ===================
330 */
ParseTexMod(char * _text,shaderStage_t * stage)331 static void ParseTexMod( char *_text, shaderStage_t *stage ) {
332 const char *token;
333 char **text = &_text;
334 texModInfo_t *tmi;
335
336 if ( stage->bundle[0].numTexMods == TR_MAX_TEXMODS ) {
337 ri.Error( ERR_DROP, "ERROR: too many tcMod stages in shader '%s'", shader.name );
338 return;
339 }
340
341 tmi = &stage->bundle[0].texMods[stage->bundle[0].numTexMods];
342 stage->bundle[0].numTexMods++;
343
344 token = COM_ParseExt( text, qfalse );
345
346 //
347 // swap
348 //
349 if ( !Q_stricmp( token, "swap" ) ) { // swap S/T coords (rotate 90d)
350 tmi->type = TMOD_SWAP;
351 }
352 //
353 // turb
354 //
355 // (SA) added 'else' so it wouldn't claim 'swap' was unknown.
356 else if ( !Q_stricmp( token, "turb" ) ) {
357 token = COM_ParseExt( text, qfalse );
358 if ( token[0] == 0 ) {
359 ri.Printf( PRINT_WARNING, "WARNING: missing tcMod turb parms in shader '%s'\n", shader.name );
360 return;
361 }
362 tmi->wave.base = atof( token );
363 token = COM_ParseExt( text, qfalse );
364 if ( token[0] == 0 ) {
365 ri.Printf( PRINT_WARNING, "WARNING: missing tcMod turb in shader '%s'\n", shader.name );
366 return;
367 }
368 tmi->wave.amplitude = atof( token );
369 token = COM_ParseExt( text, qfalse );
370 if ( token[0] == 0 ) {
371 ri.Printf( PRINT_WARNING, "WARNING: missing tcMod turb in shader '%s'\n", shader.name );
372 return;
373 }
374 tmi->wave.phase = atof( token );
375 token = COM_ParseExt( text, qfalse );
376 if ( token[0] == 0 ) {
377 ri.Printf( PRINT_WARNING, "WARNING: missing tcMod turb in shader '%s'\n", shader.name );
378 return;
379 }
380 tmi->wave.frequency = atof( token );
381
382 tmi->type = TMOD_TURBULENT;
383 }
384 //
385 // scale
386 //
387 else if ( !Q_stricmp( token, "scale" ) ) {
388 token = COM_ParseExt( text, qfalse );
389 if ( token[0] == 0 ) {
390 ri.Printf( PRINT_WARNING, "WARNING: missing scale parms in shader '%s'\n", shader.name );
391 return;
392 }
393 tmi->scale[0] = atof( token );
394
395 token = COM_ParseExt( text, qfalse );
396 if ( token[0] == 0 ) {
397 ri.Printf( PRINT_WARNING, "WARNING: missing scale parms in shader '%s'\n", shader.name );
398 return;
399 }
400 tmi->scale[1] = atof( token );
401 tmi->type = TMOD_SCALE;
402 }
403 //
404 // scroll
405 //
406 else if ( !Q_stricmp( token, "scroll" ) ) {
407 token = COM_ParseExt( text, qfalse );
408 if ( token[0] == 0 ) {
409 ri.Printf( PRINT_WARNING, "WARNING: missing scale scroll parms in shader '%s'\n", shader.name );
410 return;
411 }
412 tmi->scroll[0] = atof( token );
413 token = COM_ParseExt( text, qfalse );
414 if ( token[0] == 0 ) {
415 ri.Printf( PRINT_WARNING, "WARNING: missing scale scroll parms in shader '%s'\n", shader.name );
416 return;
417 }
418 tmi->scroll[1] = atof( token );
419 tmi->type = TMOD_SCROLL;
420 }
421 //
422 // stretch
423 //
424 else if ( !Q_stricmp( token, "stretch" ) ) {
425 token = COM_ParseExt( text, qfalse );
426 if ( token[0] == 0 ) {
427 ri.Printf( PRINT_WARNING, "WARNING: missing stretch parms in shader '%s'\n", shader.name );
428 return;
429 }
430 tmi->wave.func = NameToGenFunc( token );
431
432 token = COM_ParseExt( text, qfalse );
433 if ( token[0] == 0 ) {
434 ri.Printf( PRINT_WARNING, "WARNING: missing stretch parms in shader '%s'\n", shader.name );
435 return;
436 }
437 tmi->wave.base = atof( token );
438
439 token = COM_ParseExt( text, qfalse );
440 if ( token[0] == 0 ) {
441 ri.Printf( PRINT_WARNING, "WARNING: missing stretch parms in shader '%s'\n", shader.name );
442 return;
443 }
444 tmi->wave.amplitude = atof( token );
445
446 token = COM_ParseExt( text, qfalse );
447 if ( token[0] == 0 ) {
448 ri.Printf( PRINT_WARNING, "WARNING: missing stretch parms in shader '%s'\n", shader.name );
449 return;
450 }
451 tmi->wave.phase = atof( token );
452
453 token = COM_ParseExt( text, qfalse );
454 if ( token[0] == 0 ) {
455 ri.Printf( PRINT_WARNING, "WARNING: missing stretch parms in shader '%s'\n", shader.name );
456 return;
457 }
458 tmi->wave.frequency = atof( token );
459
460 tmi->type = TMOD_STRETCH;
461 }
462 //
463 // transform
464 //
465 else if ( !Q_stricmp( token, "transform" ) ) {
466 token = COM_ParseExt( text, qfalse );
467 if ( token[0] == 0 ) {
468 ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name );
469 return;
470 }
471 tmi->matrix[0][0] = atof( token );
472
473 token = COM_ParseExt( text, qfalse );
474 if ( token[0] == 0 ) {
475 ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name );
476 return;
477 }
478 tmi->matrix[0][1] = atof( token );
479
480 token = COM_ParseExt( text, qfalse );
481 if ( token[0] == 0 ) {
482 ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name );
483 return;
484 }
485 tmi->matrix[1][0] = atof( token );
486
487 token = COM_ParseExt( text, qfalse );
488 if ( token[0] == 0 ) {
489 ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name );
490 return;
491 }
492 tmi->matrix[1][1] = atof( token );
493
494 token = COM_ParseExt( text, qfalse );
495 if ( token[0] == 0 ) {
496 ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name );
497 return;
498 }
499 tmi->translate[0] = atof( token );
500
501 token = COM_ParseExt( text, qfalse );
502 if ( token[0] == 0 ) {
503 ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name );
504 return;
505 }
506 tmi->translate[1] = atof( token );
507
508 tmi->type = TMOD_TRANSFORM;
509 }
510 //
511 // rotate
512 //
513 else if ( !Q_stricmp( token, "rotate" ) ) {
514 token = COM_ParseExt( text, qfalse );
515 if ( token[0] == 0 ) {
516 ri.Printf( PRINT_WARNING, "WARNING: missing tcMod rotate parms in shader '%s'\n", shader.name );
517 return;
518 }
519 tmi->rotateSpeed = atof( token );
520 tmi->type = TMOD_ROTATE;
521 }
522 //
523 // entityTranslate
524 //
525 else if ( !Q_stricmp( token, "entityTranslate" ) ) {
526 tmi->type = TMOD_ENTITY_TRANSLATE;
527 } else
528 {
529 ri.Printf( PRINT_WARNING, "WARNING: unknown tcMod '%s' in shader '%s'\n", token, shader.name );
530 }
531 }
532
533
534 /*
535 ===================
536 ParseStage
537 ===================
538 */
ParseStage(shaderStage_t * stage,char ** text)539 static qboolean ParseStage( shaderStage_t *stage, char **text ) {
540 char *token;
541 int depthMaskBits = GLS_DEPTHMASK_TRUE, blendSrcBits = 0, blendDstBits = 0, atestBits = 0, depthFuncBits = 0;
542 qboolean depthMaskExplicit = qfalse;
543
544 stage->active = qtrue;
545
546 while ( 1 )
547 {
548 token = COM_ParseExt( text, qtrue );
549 if ( !token[0] ) {
550 ri.Printf( PRINT_WARNING, "WARNING: no matching '}' found\n" );
551 return qfalse;
552 }
553
554 if ( token[0] == '}' ) {
555 break;
556 }
557 //
558 // check special case for map16/map32/mapcomp/mapnocomp (compression enabled)
559 if ( !Q_stricmp( token, "map16" ) ) { // only use this texture if 16 bit color depth
560 if ( glConfig.colorBits <= 16 ) {
561 token = "map"; // use this map
562 } else {
563 COM_ParseExt( text, qfalse ); // ignore the map
564 continue;
565 }
566 } else if ( !Q_stricmp( token, "map32" ) ) { // only use this texture if 16 bit color depth
567 if ( glConfig.colorBits > 16 ) {
568 token = "map"; // use this map
569 } else {
570 COM_ParseExt( text, qfalse ); // ignore the map
571 continue;
572 }
573 } else if ( !Q_stricmp( token, "mapcomp" ) ) { // only use this texture if compression is enabled
574 if ( glConfig.textureCompression && r_ext_compressed_textures->integer ) {
575 token = "map"; // use this map
576 } else {
577 COM_ParseExt( text, qfalse ); // ignore the map
578 continue;
579 }
580 } else if ( !Q_stricmp( token, "mapnocomp" ) ) { // only use this texture if compression is not available or disabled
581 if ( !glConfig.textureCompression ) {
582 token = "map"; // use this map
583 } else {
584 COM_ParseExt( text, qfalse ); // ignore the map
585 continue;
586 }
587 } else if ( !Q_stricmp( token, "animmapcomp" ) ) { // only use this texture if compression is enabled
588 if ( glConfig.textureCompression && r_ext_compressed_textures->integer ) {
589 token = "animmap"; // use this map
590 } else {
591 while ( token[0] )
592 COM_ParseExt( text, qfalse ); // ignore the map
593 continue;
594 }
595 } else if ( !Q_stricmp( token, "animmapnocomp" ) ) { // only use this texture if compression is not available or disabled
596 if ( !glConfig.textureCompression ) {
597 token = "animmap"; // use this map
598 } else {
599 while ( token[0] )
600 COM_ParseExt( text, qfalse ); // ignore the map
601 continue;
602 }
603 }
604 //
605 // map <name>
606 //
607 if ( !Q_stricmp( token, "map" ) ) {
608 token = COM_ParseExt( text, qfalse );
609 if ( !token[0] ) {
610 ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'map' keyword in shader '%s'\n", shader.name );
611 return qfalse;
612 }
613
614 //----(SA) fixes startup error and allows polygon shadows to work again
615 if ( !Q_stricmp( token, "$whiteimage" ) || !Q_stricmp( token, "*white" ) ) {
616 //----(SA) end
617 stage->bundle[0].image[0] = tr.whiteImage;
618 continue;
619 }
620 //----(SA) added
621 else if ( !Q_stricmp( token, "$dlight" ) ) {
622 stage->bundle[0].image[0] = tr.dlightImage;
623 continue;
624 }
625 //----(SA) end
626 else if ( !Q_stricmp( token, "$lightmap" ) ) {
627 stage->bundle[0].isLightmap = qtrue;
628 if ( shader.lightmapIndex < 0 || !tr.lightmaps ) {
629 stage->bundle[0].image[0] = tr.whiteImage;
630 } else {
631 stage->bundle[0].image[0] = tr.lightmaps[shader.lightmapIndex];
632 }
633 continue;
634 }
635 else if ( !Q_stricmp( token, "$deluxemap" ) )
636 {
637 if (!tr.worldDeluxeMapping)
638 {
639 ri.Printf( PRINT_WARNING, "WARNING: shader '%s' wants a deluxe map in a map compiled without them\n", shader.name );
640 return qfalse;
641 }
642
643 stage->bundle[0].isLightmap = qtrue;
644 if ( shader.lightmapIndex < 0 ) {
645 stage->bundle[0].image[0] = tr.whiteImage;
646 } else {
647 stage->bundle[0].image[0] = tr.deluxemaps[shader.lightmapIndex];
648 }
649 continue;
650 }
651 else
652 {
653 imgType_t type = IMGTYPE_COLORALPHA;
654 imgFlags_t flags = IMGFLAG_NONE;
655
656 if (!shader.noMipMaps)
657 flags |= IMGFLAG_MIPMAP;
658
659 if (!shader.noPicMip)
660 flags |= IMGFLAG_PICMIP;
661
662 if (stage->type == ST_NORMALMAP || stage->type == ST_NORMALPARALLAXMAP)
663 {
664 type = IMGTYPE_NORMAL;
665 flags |= IMGFLAG_NOLIGHTSCALE;
666
667 if (stage->type == ST_NORMALPARALLAXMAP)
668 type = IMGTYPE_NORMALHEIGHT;
669 }
670 else
671 {
672 if (r_genNormalMaps->integer)
673 flags |= IMGFLAG_GENNORMALMAP;
674 }
675
676 stage->bundle[0].image[0] = R_FindImageFileExt( token, type, flags, shader.characterMip );
677 if ( !stage->bundle[0].image[0] ) {
678 ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFileExt could not find '%s' in shader '%s'\n", token, shader.name );
679 return qfalse;
680 }
681 }
682 }
683 //
684 // clampmap <name>
685 //
686 else if ( !Q_stricmp( token, "clampmap" ) ) {
687 imgType_t type = IMGTYPE_COLORALPHA;
688 imgFlags_t flags = IMGFLAG_CLAMPTOEDGE;
689
690 token = COM_ParseExt( text, qfalse );
691 if ( !token[0] ) {
692 ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'clampmap' keyword in shader '%s'\n", shader.name );
693 return qfalse;
694 }
695
696 if (!shader.noMipMaps)
697 flags |= IMGFLAG_MIPMAP;
698
699 if (!shader.noPicMip)
700 flags |= IMGFLAG_PICMIP;
701
702 if (stage->type == ST_NORMALMAP || stage->type == ST_NORMALPARALLAXMAP)
703 {
704 type = IMGTYPE_NORMAL;
705 flags |= IMGFLAG_NOLIGHTSCALE;
706
707 if (stage->type == ST_NORMALPARALLAXMAP)
708 type = IMGTYPE_NORMALHEIGHT;
709 }
710 else
711 {
712 if (r_genNormalMaps->integer)
713 flags |= IMGFLAG_GENNORMALMAP;
714 }
715
716 stage->bundle[0].image[0] = R_FindImageFileExt( token, type, flags, shader.characterMip );
717 if ( !stage->bundle[0].image[0] ) {
718 ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFileExt could not find '%s' in shader '%s'\n", token, shader.name );
719 return qfalse;
720 }
721 }
722 //
723 // animMap <frequency> <image1> .... <imageN>
724 //
725 else if ( !Q_stricmp( token, "animMap" ) ) {
726 int totalImages = 0;
727
728 token = COM_ParseExt( text, qfalse );
729 if ( !token[0] ) {
730 ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'animMap' keyword in shader '%s'\n", shader.name );
731 return qfalse;
732 }
733 stage->bundle[0].imageAnimationSpeed = atof( token );
734
735 // parse up to MAX_IMAGE_ANIMATIONS animations
736 while ( 1 ) {
737 int num;
738
739 token = COM_ParseExt( text, qfalse );
740 if ( !token[0] ) {
741 break;
742 }
743 num = stage->bundle[0].numImageAnimations;
744 if ( num < MAX_IMAGE_ANIMATIONS ) {
745 imgFlags_t flags = IMGFLAG_NONE;
746
747 if (!shader.noMipMaps)
748 flags |= IMGFLAG_MIPMAP;
749
750 if (!shader.noPicMip)
751 flags |= IMGFLAG_PICMIP;
752
753 stage->bundle[0].image[num] = R_FindImageFileExt( token, IMGTYPE_COLORALPHA, flags, shader.characterMip );
754 if ( !stage->bundle[0].image[num] ) {
755 ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFileExt could not find '%s' in shader '%s'\n", token, shader.name );
756 return qfalse;
757 }
758 stage->bundle[0].numImageAnimations++;
759 }
760 totalImages++;
761 }
762
763 if ( totalImages > MAX_IMAGE_ANIMATIONS ) {
764 ri.Printf( PRINT_WARNING, "WARNING: ignoring excess images for 'animMap' (found %d, max is %d) in shader '%s'\n",
765 totalImages, MAX_IMAGE_ANIMATIONS, shader.name );
766 }
767 } else if ( !Q_stricmp( token, "videoMap" ) ) {
768 token = COM_ParseExt( text, qfalse );
769 if ( !token[0] ) {
770 ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'videoMap' keyword in shader '%s'\n", shader.name );
771 return qfalse;
772 }
773 stage->bundle[0].videoMapHandle = ri.CIN_PlayCinematic( token, 0, 0, 256, 256, ( CIN_loop | CIN_silent | CIN_shader ) );
774 if ( stage->bundle[0].videoMapHandle != -1 ) {
775 stage->bundle[0].isVideoMap = qtrue;
776 stage->bundle[0].image[0] = tr.scratchImage[stage->bundle[0].videoMapHandle];
777 } else {
778 ri.Printf( PRINT_WARNING, "WARNING: could not load '%s' for 'videoMap' keyword in shader '%s'\n", token, shader.name );
779 }
780 }
781 //
782 // alphafunc <func>
783 //
784 else if ( !Q_stricmp( token, "alphaFunc" ) ) {
785 token = COM_ParseExt( text, qfalse );
786 if ( !token[0] ) {
787 ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'alphaFunc' keyword in shader '%s'\n", shader.name );
788 return qfalse;
789 }
790
791 atestBits = NameToAFunc( token );
792 }
793 //
794 // depthFunc <func>
795 //
796 else if ( !Q_stricmp( token, "depthfunc" ) ) {
797 token = COM_ParseExt( text, qfalse );
798
799 if ( !token[0] ) {
800 ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'depthfunc' keyword in shader '%s'\n", shader.name );
801 return qfalse;
802 }
803
804 if ( !Q_stricmp( token, "lequal" ) ) {
805 depthFuncBits = 0;
806 } else if ( !Q_stricmp( token, "equal" ) ) {
807 depthFuncBits = GLS_DEPTHFUNC_EQUAL;
808 } else
809 {
810 ri.Printf( PRINT_WARNING, "WARNING: unknown depthfunc '%s' in shader '%s'\n", token, shader.name );
811 continue;
812 }
813 }
814 //
815 // detail
816 //
817 else if ( !Q_stricmp( token, "detail" ) ) {
818 stage->isDetail = qtrue;
819 }
820 //
821 // fog
822 //
823 else if ( !Q_stricmp( token, "fog" ) ) {
824 token = COM_ParseExt( text, qfalse );
825 if ( token[0] == 0 ) {
826 ri.Printf( PRINT_WARNING, "WARNING: missing parm for fog in shader '%s'\n", shader.name );
827 continue;
828 }
829 if ( !Q_stricmp( token, "on" ) ) {
830 stage->isFogged = qtrue;
831 } else {
832 stage->isFogged = qfalse;
833 }
834 }
835 //
836 // blendfunc <srcFactor> <dstFactor>
837 // or blendfunc <add|filter|blend>
838 //
839 else if ( !Q_stricmp( token, "blendfunc" ) ) {
840 token = COM_ParseExt( text, qfalse );
841 if ( token[0] == 0 ) {
842 ri.Printf( PRINT_WARNING, "WARNING: missing parm for blendFunc in shader '%s'\n", shader.name );
843 continue;
844 }
845 // check for "simple" blends first
846 if ( !Q_stricmp( token, "add" ) ) {
847 blendSrcBits = GLS_SRCBLEND_ONE;
848 blendDstBits = GLS_DSTBLEND_ONE;
849 } else if ( !Q_stricmp( token, "filter" ) ) {
850 blendSrcBits = GLS_SRCBLEND_DST_COLOR;
851 blendDstBits = GLS_DSTBLEND_ZERO;
852 } else if ( !Q_stricmp( token, "blend" ) ) {
853 blendSrcBits = GLS_SRCBLEND_SRC_ALPHA;
854 blendDstBits = GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA;
855 } else {
856 // complex double blends
857 blendSrcBits = NameToSrcBlendMode( token );
858
859 token = COM_ParseExt( text, qfalse );
860 if ( token[0] == 0 ) {
861 ri.Printf( PRINT_WARNING, "WARNING: missing parm for blendFunc in shader '%s'\n", shader.name );
862 continue;
863 }
864 blendDstBits = NameToDstBlendMode( token );
865 }
866
867 // clear depth mask for blended surfaces
868 if ( !depthMaskExplicit ) {
869 depthMaskBits = 0;
870 }
871 }
872 //
873 // stage <type>
874 //
875 else if(!Q_stricmp(token, "stage"))
876 {
877 token = COM_ParseExt(text, qfalse);
878 if(token[0] == 0)
879 {
880 ri.Printf(PRINT_WARNING, "WARNING: missing parameters for stage in shader '%s'\n", shader.name);
881 continue;
882 }
883
884 if(!Q_stricmp(token, "diffuseMap"))
885 {
886 stage->type = ST_DIFFUSEMAP;
887 }
888 else if(!Q_stricmp(token, "normalMap") || !Q_stricmp(token, "bumpMap"))
889 {
890 stage->type = ST_NORMALMAP;
891 VectorSet4(stage->normalScale, r_baseNormalX->value, r_baseNormalY->value, 1.0f, r_baseParallax->value);
892 }
893 else if(!Q_stricmp(token, "normalParallaxMap") || !Q_stricmp(token, "bumpParallaxMap"))
894 {
895 if (r_parallaxMapping->integer)
896 stage->type = ST_NORMALPARALLAXMAP;
897 else
898 stage->type = ST_NORMALMAP;
899 VectorSet4(stage->normalScale, r_baseNormalX->value, r_baseNormalY->value, 1.0f, r_baseParallax->value);
900 }
901 else if(!Q_stricmp(token, "specularMap"))
902 {
903 stage->type = ST_SPECULARMAP;
904 VectorSet4(stage->specularScale, 1.0f, 1.0f, 1.0f, 1.0f);
905 }
906 else
907 {
908 ri.Printf(PRINT_WARNING, "WARNING: unknown stage parameter '%s' in shader '%s'\n", token, shader.name);
909 continue;
910 }
911 }
912 //
913 // specularReflectance <value>
914 //
915 else if (!Q_stricmp(token, "specularreflectance"))
916 {
917 token = COM_ParseExt(text, qfalse);
918 if ( token[0] == 0 )
919 {
920 ri.Printf( PRINT_WARNING, "WARNING: missing parameter for specular reflectance in shader '%s'\n", shader.name );
921 continue;
922 }
923
924 if (r_pbr->integer)
925 {
926 // interpret specularReflectance < 0.5 as nonmetal
927 stage->specularScale[1] = (atof(token) < 0.5f) ? 0.0f : 1.0f;
928 }
929 else
930 {
931 stage->specularScale[0] =
932 stage->specularScale[1] =
933 stage->specularScale[2] = atof( token );
934 }
935 }
936 //
937 // specularExponent <value>
938 //
939 else if (!Q_stricmp(token, "specularexponent"))
940 {
941 float exponent;
942
943 token = COM_ParseExt(text, qfalse);
944 if ( token[0] == 0 )
945 {
946 ri.Printf( PRINT_WARNING, "WARNING: missing parameter for specular exponent in shader '%s'\n", shader.name );
947 continue;
948 }
949
950 exponent = atof( token );
951
952 if (r_pbr->integer)
953 stage->specularScale[0] = 1.0f - powf(2.0f / (exponent + 2.0), 0.25);
954 else
955 {
956 // Change shininess to gloss
957 // Assumes max exponent of 8190 and min of 0, must change here if altered in lightall_fp.glsl
958 exponent = CLAMP(exponent, 0.0f, 8190.0f);
959 stage->specularScale[3] = (log2f(exponent + 2.0f) - 1.0f) / 12.0f;
960 }
961 }
962 //
963 // gloss <value>
964 //
965 else if (!Q_stricmp(token, "gloss"))
966 {
967 float gloss;
968
969 token = COM_ParseExt(text, qfalse);
970 if ( token[0] == 0 )
971 {
972 ri.Printf( PRINT_WARNING, "WARNING: missing parameter for gloss in shader '%s'\n", shader.name );
973 continue;
974 }
975
976 gloss = atof(token);
977
978 if (r_pbr->integer)
979 stage->specularScale[0] = 1.0f - exp2f(-3.0f * gloss);
980 else
981 stage->specularScale[3] = gloss;
982 }
983 //
984 // roughness <value>
985 //
986 else if (!Q_stricmp(token, "roughness"))
987 {
988 float roughness;
989
990 token = COM_ParseExt(text, qfalse);
991 if (token[0] == 0)
992 {
993 ri.Printf(PRINT_WARNING, "WARNING: missing parameter for roughness in shader '%s'\n", shader.name);
994 continue;
995 }
996
997 roughness = atof(token);
998
999 if (r_pbr->integer)
1000 stage->specularScale[0] = 1.0 - roughness;
1001 else
1002 {
1003 if (roughness >= 0.125)
1004 stage->specularScale[3] = log2f(1.0f / roughness) / 3.0f;
1005 else
1006 stage->specularScale[3] = 1.0f;
1007 }
1008 }
1009 //
1010 // parallaxDepth <value>
1011 //
1012 else if (!Q_stricmp(token, "parallaxdepth"))
1013 {
1014 token = COM_ParseExt(text, qfalse);
1015 if ( token[0] == 0 )
1016 {
1017 ri.Printf( PRINT_WARNING, "WARNING: missing parameter for parallaxDepth in shader '%s'\n", shader.name );
1018 continue;
1019 }
1020
1021 stage->normalScale[3] = atof( token );
1022 }
1023 //
1024 // normalScale <xy>
1025 // or normalScale <x> <y>
1026 // or normalScale <x> <y> <height>
1027 //
1028 else if (!Q_stricmp(token, "normalscale"))
1029 {
1030 token = COM_ParseExt(text, qfalse);
1031 if ( token[0] == 0 )
1032 {
1033 ri.Printf( PRINT_WARNING, "WARNING: missing parameter for normalScale in shader '%s'\n", shader.name );
1034 continue;
1035 }
1036
1037 stage->normalScale[0] = atof( token );
1038
1039 token = COM_ParseExt(text, qfalse);
1040 if ( token[0] == 0 )
1041 {
1042 // one value, applies to X/Y
1043 stage->normalScale[1] = stage->normalScale[0];
1044 continue;
1045 }
1046
1047 stage->normalScale[1] = atof( token );
1048
1049 token = COM_ParseExt(text, qfalse);
1050 if ( token[0] == 0 )
1051 {
1052 // two values, no height
1053 continue;
1054 }
1055
1056 stage->normalScale[3] = atof( token );
1057 }
1058 //
1059 // specularScale <rgb> <gloss>
1060 // or specularScale <metallic> <smoothness> with r_pbr 1
1061 // or specularScale <r> <g> <b>
1062 // or specularScale <r> <g> <b> <gloss>
1063 //
1064 else if (!Q_stricmp(token, "specularscale"))
1065 {
1066 token = COM_ParseExt(text, qfalse);
1067 if ( token[0] == 0 )
1068 {
1069 ri.Printf( PRINT_WARNING, "WARNING: missing parameter for specularScale in shader '%s'\n", shader.name );
1070 continue;
1071 }
1072
1073 stage->specularScale[0] = atof( token );
1074
1075 token = COM_ParseExt(text, qfalse);
1076 if ( token[0] == 0 )
1077 {
1078 ri.Printf( PRINT_WARNING, "WARNING: missing parameter for specularScale in shader '%s'\n", shader.name );
1079 continue;
1080 }
1081
1082 stage->specularScale[1] = atof( token );
1083
1084 token = COM_ParseExt(text, qfalse);
1085 if ( token[0] == 0 )
1086 {
1087 if (r_pbr->integer)
1088 {
1089 // two values, metallic then smoothness
1090 float smoothness = stage->specularScale[1];
1091 stage->specularScale[1] = (stage->specularScale[0] < 0.5f) ? 0.0f : 1.0f;
1092 stage->specularScale[0] = smoothness;
1093 }
1094 else
1095 {
1096 // two values, rgb then gloss
1097 stage->specularScale[3] = stage->specularScale[1];
1098 stage->specularScale[1] =
1099 stage->specularScale[2] = stage->specularScale[0];
1100 }
1101 continue;
1102 }
1103
1104 stage->specularScale[2] = atof( token );
1105
1106 token = COM_ParseExt(text, qfalse);
1107 if ( token[0] == 0 )
1108 {
1109 // three values, rgb
1110 continue;
1111 }
1112
1113 stage->specularScale[3] = atof( token );
1114
1115 }
1116 //
1117 // rgbGen
1118 //
1119 else if ( !Q_stricmp( token, "rgbGen" ) ) {
1120 token = COM_ParseExt( text, qfalse );
1121 if ( token[0] == 0 ) {
1122 ri.Printf( PRINT_WARNING, "WARNING: missing parameters for rgbGen in shader '%s'\n", shader.name );
1123 continue;
1124 }
1125
1126 if ( !Q_stricmp( token, "wave" ) ) {
1127 ParseWaveForm( text, &stage->rgbWave );
1128 stage->rgbGen = CGEN_WAVEFORM;
1129 } else if ( !Q_stricmp( token, "const" ) ) {
1130 vec3_t color;
1131
1132 VectorClear( color );
1133
1134 ParseVector( text, 3, color );
1135 stage->constantColor[0] = 255 * color[0];
1136 stage->constantColor[1] = 255 * color[1];
1137 stage->constantColor[2] = 255 * color[2];
1138
1139 stage->rgbGen = CGEN_CONST;
1140 } else if ( !Q_stricmp( token, "identity" ) ) {
1141 stage->rgbGen = CGEN_IDENTITY;
1142 } else if ( !Q_stricmp( token, "identityLighting" ) ) {
1143 stage->rgbGen = CGEN_IDENTITY_LIGHTING;
1144 } else if ( !Q_stricmp( token, "entity" ) ) {
1145 stage->rgbGen = CGEN_ENTITY;
1146 } else if ( !Q_stricmp( token, "oneMinusEntity" ) ) {
1147 stage->rgbGen = CGEN_ONE_MINUS_ENTITY;
1148 } else if ( !Q_stricmp( token, "vertex" ) ) {
1149 stage->rgbGen = CGEN_VERTEX;
1150 if ( stage->alphaGen == 0 ) {
1151 stage->alphaGen = AGEN_VERTEX;
1152 }
1153 } else if ( !Q_stricmp( token, "exactVertex" ) ) {
1154 stage->rgbGen = CGEN_EXACT_VERTEX;
1155 } else if ( !Q_stricmp( token, "vertexLit" ) ) {
1156 stage->rgbGen = CGEN_VERTEX_LIT;
1157 if ( stage->alphaGen == 0 ) {
1158 stage->alphaGen = AGEN_VERTEX;
1159 }
1160 } else if ( !Q_stricmp( token, "exactVertexLit" ) ) {
1161 stage->rgbGen = CGEN_EXACT_VERTEX_LIT;
1162 } else if ( !Q_stricmp( token, "lightingDiffuse" ) ) {
1163 stage->rgbGen = CGEN_LIGHTING_DIFFUSE;
1164 } else if ( !Q_stricmp( token, "oneMinusVertex" ) ) {
1165 stage->rgbGen = CGEN_ONE_MINUS_VERTEX;
1166 } else
1167 {
1168 ri.Printf( PRINT_WARNING, "WARNING: unknown rgbGen parameter '%s' in shader '%s'\n", token, shader.name );
1169 continue;
1170 }
1171 }
1172 //
1173 // alphaGen
1174 //
1175 else if ( !Q_stricmp( token, "alphaGen" ) ) {
1176 token = COM_ParseExt( text, qfalse );
1177 if ( token[0] == 0 ) {
1178 ri.Printf( PRINT_WARNING, "WARNING: missing parameters for alphaGen in shader '%s'\n", shader.name );
1179 continue;
1180 }
1181
1182 if ( !Q_stricmp( token, "wave" ) ) {
1183 ParseWaveForm( text, &stage->alphaWave );
1184 stage->alphaGen = AGEN_WAVEFORM;
1185 } else if ( !Q_stricmp( token, "const" ) ) {
1186 token = COM_ParseExt( text, qfalse );
1187 stage->constantColor[3] = 255 * atof( token );
1188 stage->alphaGen = AGEN_CONST;
1189 } else if ( !Q_stricmp( token, "identity" ) ) {
1190 stage->alphaGen = AGEN_IDENTITY;
1191 } else if ( !Q_stricmp( token, "entity" ) ) {
1192 stage->alphaGen = AGEN_ENTITY;
1193 } else if ( !Q_stricmp( token, "oneMinusEntity" ) ) {
1194 stage->alphaGen = AGEN_ONE_MINUS_ENTITY;
1195 }
1196 // Ridah
1197 else if ( !Q_stricmp( token, "normalzfade" ) ) {
1198 stage->alphaGen = AGEN_NORMALZFADE;
1199 token = COM_ParseExt( text, qfalse );
1200 if ( token[0] ) {
1201 stage->constantColor[3] = 255 * atof( token );
1202 } else {
1203 stage->constantColor[3] = 255;
1204 }
1205
1206 token = COM_ParseExt( text, qfalse );
1207 if ( token[0] ) {
1208 stage->zFadeBounds[0] = atof( token ); // lower range
1209 token = COM_ParseExt( text, qfalse );
1210 stage->zFadeBounds[1] = atof( token ); // upper range
1211 } else {
1212 stage->zFadeBounds[0] = -1.0; // lower range
1213 stage->zFadeBounds[1] = 1.0; // upper range
1214 }
1215
1216 }
1217 // done.
1218 else if ( !Q_stricmp( token, "vertex" ) ) {
1219 stage->alphaGen = AGEN_VERTEX;
1220 } else if ( !Q_stricmp( token, "lightingSpecular" ) ) {
1221 stage->alphaGen = AGEN_LIGHTING_SPECULAR;
1222 } else if ( !Q_stricmp( token, "oneMinusVertex" ) ) {
1223 stage->alphaGen = AGEN_ONE_MINUS_VERTEX;
1224 } else if ( !Q_stricmp( token, "portal" ) ) {
1225 stage->alphaGen = AGEN_PORTAL;
1226 token = COM_ParseExt( text, qfalse );
1227 if ( token[0] == 0 ) {
1228 shader.portalRange = 256;
1229 ri.Printf( PRINT_WARNING, "WARNING: missing range parameter for alphaGen portal in shader '%s', defaulting to 256\n", shader.name );
1230 }
1231 else
1232 {
1233 shader.portalRange = atof( token );
1234 }
1235 }
1236 else
1237 {
1238 ri.Printf( PRINT_WARNING, "WARNING: unknown alphaGen parameter '%s' in shader '%s'\n", token, shader.name );
1239 continue;
1240 }
1241 }
1242 //
1243 // tcGen <function>
1244 //
1245 else if ( !Q_stricmp( token, "texgen" ) || !Q_stricmp( token, "tcGen" ) ) {
1246 token = COM_ParseExt( text, qfalse );
1247 if ( token[0] == 0 ) {
1248 ri.Printf( PRINT_WARNING, "WARNING: missing texgen parm in shader '%s'\n", shader.name );
1249 continue;
1250 }
1251
1252 if ( !Q_stricmp( token, "environment" ) ) {
1253 stage->bundle[0].tcGen = TCGEN_ENVIRONMENT_MAPPED;
1254 } else if ( !Q_stricmp( token, "firerisenv" ) ) {
1255 stage->bundle[0].tcGen = TCGEN_FIRERISEENV_MAPPED;
1256 } else if ( !Q_stricmp( token, "lightmap" ) ) {
1257 stage->bundle[0].tcGen = TCGEN_LIGHTMAP;
1258 } else if ( !Q_stricmp( token, "texture" ) || !Q_stricmp( token, "base" ) ) {
1259 stage->bundle[0].tcGen = TCGEN_TEXTURE;
1260 } else if ( !Q_stricmp( token, "vector" ) ) {
1261 ParseVector( text, 3, stage->bundle[0].tcGenVectors[0] );
1262 ParseVector( text, 3, stage->bundle[0].tcGenVectors[1] );
1263
1264 stage->bundle[0].tcGen = TCGEN_VECTOR;
1265 } else
1266 {
1267 ri.Printf( PRINT_WARNING, "WARNING: unknown texgen parm in shader '%s'\n", shader.name );
1268 }
1269 }
1270 //
1271 // tcMod <type> <...>
1272 //
1273 else if ( !Q_stricmp( token, "tcMod" ) ) {
1274 char buffer[1024] = "";
1275
1276 while ( 1 )
1277 {
1278 token = COM_ParseExt( text, qfalse );
1279 if ( token[0] == 0 ) {
1280 break;
1281 }
1282 Q_strcat( buffer, sizeof (buffer), token );
1283 Q_strcat( buffer, sizeof (buffer), " " );
1284 }
1285
1286 ParseTexMod( buffer, stage );
1287
1288 continue;
1289 }
1290 //
1291 // depthmask
1292 //
1293 else if ( !Q_stricmp( token, "depthwrite" ) ) {
1294 depthMaskBits = GLS_DEPTHMASK_TRUE;
1295 depthMaskExplicit = qtrue;
1296
1297 continue;
1298 } else
1299 {
1300 ri.Printf( PRINT_WARNING, "WARNING: unknown parameter '%s' in shader '%s'\n", token, shader.name );
1301 return qfalse;
1302 }
1303 }
1304
1305 //
1306 // if cgen isn't explicitly specified, use either identity or identitylighting
1307 //
1308 if ( stage->rgbGen == CGEN_BAD ) {
1309 if ( blendSrcBits == 0 ||
1310 blendSrcBits == GLS_SRCBLEND_ONE ||
1311 blendSrcBits == GLS_SRCBLEND_SRC_ALPHA ) {
1312 stage->rgbGen = CGEN_IDENTITY_LIGHTING;
1313 } else {
1314 stage->rgbGen = CGEN_IDENTITY;
1315 }
1316 }
1317
1318
1319 //
1320 // implicitly assume that a GL_ONE GL_ZERO blend mask disables blending
1321 //
1322 if ( ( blendSrcBits == GLS_SRCBLEND_ONE ) &&
1323 ( blendDstBits == GLS_DSTBLEND_ZERO ) ) {
1324 blendDstBits = blendSrcBits = 0;
1325 depthMaskBits = GLS_DEPTHMASK_TRUE;
1326 }
1327
1328 // decide which agens we can skip
1329 if ( stage->alphaGen == AGEN_IDENTITY ) {
1330 if ( stage->rgbGen == CGEN_IDENTITY
1331 || stage->rgbGen == CGEN_LIGHTING_DIFFUSE ) {
1332 stage->alphaGen = AGEN_SKIP;
1333 }
1334 }
1335
1336 //
1337 // compute state bits
1338 //
1339 stage->stateBits = depthMaskBits |
1340 blendSrcBits | blendDstBits |
1341 atestBits |
1342 depthFuncBits;
1343
1344 return qtrue;
1345 }
1346
1347 /*
1348 ===============
1349 ParseDeform
1350
1351 deformVertexes wave <spread> <waveform> <base> <amplitude> <phase> <frequency>
1352 deformVertexes normal <frequency> <amplitude>
1353 deformVertexes move <vector> <waveform> <base> <amplitude> <phase> <frequency>
1354 deformVertexes bulge <bulgeWidth> <bulgeHeight> <bulgeSpeed>
1355 deformVertexes projectionShadow
1356 deformVertexes autoSprite
1357 deformVertexes autoSprite2
1358 deformVertexes text[0-7]
1359 ===============
1360 */
ParseDeform(char ** text)1361 static void ParseDeform( char **text ) {
1362 char *token;
1363 deformStage_t *ds;
1364
1365 token = COM_ParseExt( text, qfalse );
1366 if ( token[0] == 0 ) {
1367 ri.Printf( PRINT_WARNING, "WARNING: missing deform parm in shader '%s'\n", shader.name );
1368 return;
1369 }
1370
1371 if ( shader.numDeforms == MAX_SHADER_DEFORMS ) {
1372 ri.Printf( PRINT_WARNING, "WARNING: MAX_SHADER_DEFORMS in '%s'\n", shader.name );
1373 return;
1374 }
1375
1376 ds = &shader.deforms[ shader.numDeforms ];
1377 shader.numDeforms++;
1378
1379 if ( !Q_stricmp( token, "projectionShadow" ) ) {
1380 ds->deformation = DEFORM_PROJECTION_SHADOW;
1381 return;
1382 }
1383
1384 if ( !Q_stricmp( token, "autosprite" ) ) {
1385 ds->deformation = DEFORM_AUTOSPRITE;
1386 return;
1387 }
1388
1389 if ( !Q_stricmp( token, "autosprite2" ) ) {
1390 ds->deformation = DEFORM_AUTOSPRITE2;
1391 return;
1392 }
1393
1394 if ( !Q_stricmpn( token, "text", 4 ) ) {
1395 int n;
1396
1397 n = token[4] - '0';
1398 if ( n < 0 || n > 7 ) {
1399 n = 0;
1400 }
1401 ds->deformation = DEFORM_TEXT0 + n;
1402 return;
1403 }
1404
1405 if ( !Q_stricmp( token, "bulge" ) ) {
1406 token = COM_ParseExt( text, qfalse );
1407 if ( token[0] == 0 ) {
1408 ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes bulge parm in shader '%s'\n", shader.name );
1409 return;
1410 }
1411 ds->bulgeWidth = atof( token );
1412
1413 token = COM_ParseExt( text, qfalse );
1414 if ( token[0] == 0 ) {
1415 ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes bulge parm in shader '%s'\n", shader.name );
1416 return;
1417 }
1418 ds->bulgeHeight = atof( token );
1419
1420 token = COM_ParseExt( text, qfalse );
1421 if ( token[0] == 0 ) {
1422 ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes bulge parm in shader '%s'\n", shader.name );
1423 return;
1424 }
1425 ds->bulgeSpeed = atof( token );
1426
1427 ds->deformation = DEFORM_BULGE;
1428 return;
1429 }
1430
1431 if ( !Q_stricmp( token, "wave" ) ) {
1432 token = COM_ParseExt( text, qfalse );
1433 if ( token[0] == 0 ) {
1434 ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes parm in shader '%s'\n", shader.name );
1435 return;
1436 }
1437
1438 if ( atof( token ) != 0 ) {
1439 ds->deformationSpread = 1.0f / atof( token );
1440 } else
1441 {
1442 ds->deformationSpread = 100.0f;
1443 ri.Printf( PRINT_WARNING, "WARNING: illegal div value of 0 in deformVertexes command for shader '%s'\n", shader.name );
1444 }
1445
1446 ParseWaveForm( text, &ds->deformationWave );
1447 ds->deformation = DEFORM_WAVE;
1448 return;
1449 }
1450
1451 if ( !Q_stricmp( token, "normal" ) ) {
1452 token = COM_ParseExt( text, qfalse );
1453 if ( token[0] == 0 ) {
1454 ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes parm in shader '%s'\n", shader.name );
1455 return;
1456 }
1457 ds->deformationWave.amplitude = atof( token );
1458
1459 token = COM_ParseExt( text, qfalse );
1460 if ( token[0] == 0 ) {
1461 ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes parm in shader '%s'\n", shader.name );
1462 return;
1463 }
1464 ds->deformationWave.frequency = atof( token );
1465
1466 ds->deformation = DEFORM_NORMALS;
1467 return;
1468 }
1469
1470 if ( !Q_stricmp( token, "move" ) ) {
1471 int i;
1472
1473 for ( i = 0 ; i < 3 ; i++ ) {
1474 token = COM_ParseExt( text, qfalse );
1475 if ( token[0] == 0 ) {
1476 ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes parm in shader '%s'\n", shader.name );
1477 return;
1478 }
1479 ds->moveVector[i] = atof( token );
1480 }
1481
1482 ParseWaveForm( text, &ds->deformationWave );
1483 ds->deformation = DEFORM_MOVE;
1484 return;
1485 }
1486
1487 ri.Printf( PRINT_WARNING, "WARNING: unknown deformVertexes subtype '%s' found in shader '%s'\n", token, shader.name );
1488 }
1489
1490
1491 /*
1492 ===============
1493 ParseSkyParms
1494
1495 skyParms <outerbox> <cloudheight> <innerbox>
1496 ===============
1497 */
ParseSkyParms(char ** text)1498 static void ParseSkyParms( char **text ) {
1499 char *token;
1500 static char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
1501 char pathname[MAX_QPATH];
1502 int i;
1503 imgFlags_t imgFlags = IMGFLAG_MIPMAP | IMGFLAG_PICMIP;
1504
1505 // outerbox
1506 token = COM_ParseExt( text, qfalse );
1507 if ( token[0] == 0 ) {
1508 ri.Printf( PRINT_WARNING, "WARNING: 'skyParms' missing parameter in shader '%s'\n", shader.name );
1509 return;
1510 }
1511 if ( strcmp( token, "-" ) ) {
1512 for ( i = 0 ; i < 6 ; i++ ) {
1513 Com_sprintf( pathname, sizeof( pathname ), "%s_%s.tga"
1514 , token, suf[i] );
1515 shader.sky.outerbox[i] = R_FindImageFile( ( char * ) pathname, IMGTYPE_COLORALPHA, imgFlags | IMGFLAG_CLAMPTOEDGE );
1516 if ( !shader.sky.outerbox[i] ) {
1517 shader.sky.outerbox[i] = tr.defaultImage;
1518 }
1519 }
1520 }
1521
1522 // cloudheight
1523 token = COM_ParseExt( text, qfalse );
1524 if ( token[0] == 0 ) {
1525 ri.Printf( PRINT_WARNING, "WARNING: 'skyParms' missing parameter in shader '%s'\n", shader.name );
1526 return;
1527 }
1528 shader.sky.cloudHeight = atof( token );
1529 if ( !shader.sky.cloudHeight ) {
1530 shader.sky.cloudHeight = 512;
1531 }
1532 R_InitSkyTexCoords( shader.sky.cloudHeight );
1533
1534
1535 // innerbox
1536 token = COM_ParseExt( text, qfalse );
1537 if ( token[0] == 0 ) {
1538 ri.Printf( PRINT_WARNING, "WARNING: 'skyParms' missing parameter in shader '%s'\n", shader.name );
1539 return;
1540 }
1541 if ( strcmp( token, "-" ) ) {
1542 for ( i = 0 ; i < 6 ; i++ ) {
1543 Com_sprintf( pathname, sizeof( pathname ), "%s_%s.tga"
1544 , token, suf[i] );
1545 shader.sky.innerbox[i] = R_FindImageFile( ( char * ) pathname, IMGTYPE_COLORALPHA, imgFlags );
1546 if ( !shader.sky.innerbox[i] ) {
1547 shader.sky.innerbox[i] = tr.defaultImage;
1548 }
1549 }
1550 }
1551
1552 shader.isSky = qtrue;
1553 }
1554
1555
1556 /*
1557 =================
1558 ParseSort
1559 =================
1560 */
ParseSort(char ** text)1561 void ParseSort( char **text ) {
1562 char *token;
1563
1564 token = COM_ParseExt( text, qfalse );
1565 if ( token[0] == 0 ) {
1566 ri.Printf( PRINT_WARNING, "WARNING: missing sort parameter in shader '%s'\n", shader.name );
1567 return;
1568 }
1569
1570 if ( !Q_stricmp( token, "portal" ) ) {
1571 shader.sort = SS_PORTAL;
1572 } else if ( !Q_stricmp( token, "sky" ) ) {
1573 shader.sort = SS_ENVIRONMENT;
1574 } else if ( !Q_stricmp( token, "opaque" ) ) {
1575 shader.sort = SS_OPAQUE;
1576 } else if ( !Q_stricmp( token, "decal" ) ) {
1577 shader.sort = SS_DECAL;
1578 } else if ( !Q_stricmp( token, "seeThrough" ) ) {
1579 shader.sort = SS_SEE_THROUGH;
1580 } else if ( !Q_stricmp( token, "banner" ) ) {
1581 shader.sort = SS_BANNER;
1582 } else if ( !Q_stricmp( token, "additive" ) ) {
1583 shader.sort = SS_BLEND1;
1584 } else if ( !Q_stricmp( token, "nearest" ) ) {
1585 shader.sort = SS_NEAREST;
1586 } else if ( !Q_stricmp( token, "underwater" ) ) {
1587 shader.sort = SS_UNDERWATER;
1588 } else {
1589 shader.sort = atof( token );
1590 }
1591 }
1592
1593
1594
1595 // this table is also present in q3map
1596
1597 typedef struct {
1598 char *name;
1599 int clearSolid, surfaceFlags, contents;
1600 } infoParm_t;
1601
1602 infoParm_t infoParms[] = {
1603 // server relevant contents
1604
1605 //----(SA) modified
1606 {"clipmissile", 1, 0, CONTENTS_MISSILECLIP}, // impact only specific weapons (rl, gl)
1607 //----(SA) end
1608
1609 // RF, AI sight
1610 {"ai_nosight", 1, 0, CONTENTS_AI_NOSIGHT},
1611 {"clipshot", 1, 0, CONTENTS_CLIPSHOT}, // stops bullets
1612 // RF, end
1613
1614 {"water", 1, 0, CONTENTS_WATER },
1615 {"slag", 1, 0, CONTENTS_SLIME }, // uses the CONTENTS_SLIME flag, but the shader reference is changed to 'slag'
1616 // to idendify that this doesn't work the same as 'slime' did.
1617 // (slime hurts instantly, slag doesn't)
1618 // {"slime", 1, 0, CONTENTS_SLIME }, // mildly damaging
1619 {"lava", 1, 0, CONTENTS_LAVA }, // very damaging
1620 {"playerclip", 1, 0, CONTENTS_PLAYERCLIP },
1621 {"monsterclip", 1, 0, CONTENTS_MONSTERCLIP },
1622 {"nodrop", 1, 0, CONTENTS_NODROP }, // don't drop items or leave bodies (death fog, lava, etc)
1623 {"nonsolid", 1, SURF_NONSOLID, 0}, // clears the solid flag
1624
1625 // utility relevant attributes
1626 {"origin", 1, 0, CONTENTS_ORIGIN }, // center of rotating brushes
1627 {"trans", 0, 0, CONTENTS_TRANSLUCENT }, // don't eat contained surfaces
1628 {"detail", 0, 0, CONTENTS_DETAIL }, // don't include in structural bsp
1629 {"structural", 0, 0, CONTENTS_STRUCTURAL }, // force into structural bsp even if trnas
1630 {"areaportal", 1, 0, CONTENTS_AREAPORTAL }, // divides areas
1631 {"clusterportal", 1,0, CONTENTS_CLUSTERPORTAL }, // for bots
1632 {"donotenter", 1, 0, CONTENTS_DONOTENTER }, // for bots
1633
1634 // Rafael - nopass
1635 {"donotenterlarge", 1, 0, CONTENTS_DONOTENTER_LARGE }, // for larger bots
1636
1637 {"fog", 1, 0, CONTENTS_FOG}, // carves surfaces entering
1638 {"sky", 0, SURF_SKY, 0 }, // emit light from an environment map
1639 {"lightfilter", 0, SURF_LIGHTFILTER, 0 }, // filter light going through it
1640 {"alphashadow", 0, SURF_ALPHASHADOW, 0 }, // test light on a per-pixel basis
1641 {"hint", 0, SURF_HINT, 0 }, // use as a primary splitter
1642
1643 // server attributes
1644 {"slick", 0, SURF_SLICK, 0 },
1645 {"noimpact", 0, SURF_NOIMPACT, 0 }, // don't make impact explosions or marks
1646 {"nomarks", 0, SURF_NOMARKS, 0 }, // don't make impact marks, but still explode
1647 {"ladder", 0, SURF_LADDER, 0 },
1648 {"nodamage", 0, SURF_NODAMAGE, 0 },
1649
1650 {"monsterslick", 0, SURF_MONSTERSLICK, 0}, // surf only slick for monsters
1651
1652 // {"flesh", 0, SURF_FLESH, 0 },
1653 {"glass", 0, SURF_GLASS, 0 }, //----(SA) added
1654 {"ceramic", 0, SURF_CERAMIC, 0 }, //----(SA) added
1655
1656 // steps
1657 {"metal", 0, SURF_METAL, 0 },
1658 {"metalsteps", 0, SURF_METAL, 0 }, // retain bw compatibility with Q3A metal shaders... (SA)
1659 {"nosteps", 0, SURF_NOSTEPS, 0 },
1660 {"woodsteps", 0, SURF_WOOD, 0 },
1661 {"grasssteps", 0, SURF_GRASS, 0 },
1662 {"gravelsteps", 0, SURF_GRAVEL, 0 },
1663 {"carpetsteps", 0, SURF_CARPET, 0 },
1664 {"snowsteps", 0, SURF_SNOW, 0 },
1665 {"roofsteps", 0, SURF_ROOF, 0 }, // tile roof
1666
1667 {"rubble", 0, SURF_RUBBLE, 0 },
1668
1669 // drawsurf attributes
1670 {"nodraw", 0, SURF_NODRAW, 0 }, // don't generate a drawsurface (or a lightmap)
1671 {"pointlight", 0, SURF_POINTLIGHT, 0 }, // sample lighting at vertexes
1672 {"nolightmap", 0, SURF_NOLIGHTMAP,0 }, // don't generate a lightmap
1673 {"nodlight", 0, SURF_NODLIGHT, 0 }, // don't ever add dynamic lights
1674
1675 {"monsterslicknorth", 0, SURF_MONSLICK_N,0},
1676 {"monsterslickeast", 0, SURF_MONSLICK_E,0},
1677 {"monsterslicksouth", 0, SURF_MONSLICK_S,0},
1678 {"monsterslickwest", 0, SURF_MONSLICK_W,0}
1679
1680 };
1681
1682
1683 /*
1684 ===============
1685 ParseSurfaceParm
1686
1687 surfaceparm <name>
1688 ===============
1689 */
ParseSurfaceParm(char ** text)1690 static void ParseSurfaceParm( char **text ) {
1691 char *token;
1692 int numInfoParms = ARRAY_LEN( infoParms );
1693 int i;
1694
1695 token = COM_ParseExt( text, qfalse );
1696 for ( i = 0 ; i < numInfoParms ; i++ ) {
1697 if ( !Q_stricmp( token, infoParms[i].name ) ) {
1698 shader.surfaceFlags |= infoParms[i].surfaceFlags;
1699 shader.contentFlags |= infoParms[i].contents;
1700 #if 0
1701 if ( infoParms[i].clearSolid ) {
1702 si->contents &= ~CONTENTS_SOLID;
1703 }
1704 #endif
1705 break;
1706 }
1707 }
1708 }
1709
1710 /*
1711 =================
1712 ParseShader
1713
1714 The current text pointer is at the explicit text definition of the
1715 shader. Parse it into the global shader variable. Later functions
1716 will optimize it.
1717 =================
1718 */
ParseShader(char ** text)1719 static qboolean ParseShader( char **text ) {
1720 char *token;
1721 int s;
1722
1723 s = 0;
1724
1725 token = COM_ParseExt( text, qtrue );
1726 if ( token[0] != '{' ) {
1727 ri.Printf( PRINT_WARNING, "WARNING: expecting '{', found '%s' instead in shader '%s'\n", token, shader.name );
1728 return qfalse;
1729 }
1730
1731 while ( 1 )
1732 {
1733 token = COM_ParseExt( text, qtrue );
1734 if ( !token[0] ) {
1735 ri.Printf( PRINT_WARNING, "WARNING: no concluding '}' in shader %s\n", shader.name );
1736 return qfalse;
1737 }
1738
1739 // end of shader definition
1740 if ( token[0] == '}' ) {
1741 break;
1742 }
1743 // stage definition
1744 else if ( token[0] == '{' ) {
1745 if ( s >= MAX_SHADER_STAGES ) {
1746 ri.Printf( PRINT_WARNING, "WARNING: too many stages in shader %s (max is %i)\n", shader.name, MAX_SHADER_STAGES );
1747 return qfalse;
1748 }
1749
1750 if ( !ParseStage( &stages[s], text ) ) {
1751 return qfalse;
1752 }
1753 stages[s].active = qtrue;
1754 s++;
1755 continue;
1756 }
1757 // skip stuff that only the QuakeEdRadient needs
1758 else if ( !Q_stricmpn( token, "qer", 3 ) ) {
1759 SkipRestOfLine( text );
1760 continue;
1761 }
1762 // sun parms
1763 else if ( !Q_stricmp( token, "q3map_sun" ) || !Q_stricmp( token, "q3map_sunExt" ) || !Q_stricmp( token, "q3gl2_sun" ) ) {
1764 float a, b;
1765 qboolean isGL2Sun = qfalse;
1766
1767 if (!Q_stricmp( token, "q3gl2_sun" ) && r_sunShadows->integer )
1768 {
1769 isGL2Sun = qtrue;
1770 tr.sunShadows = qtrue;
1771 }
1772
1773 token = COM_ParseExt( text, qfalse );
1774 tr.sunLight[0] = atof( token );
1775 token = COM_ParseExt( text, qfalse );
1776 tr.sunLight[1] = atof( token );
1777 token = COM_ParseExt( text, qfalse );
1778 tr.sunLight[2] = atof( token );
1779
1780 VectorNormalize( tr.sunLight );
1781
1782 token = COM_ParseExt( text, qfalse );
1783 a = atof( token );
1784 VectorScale( tr.sunLight, a, tr.sunLight );
1785
1786 token = COM_ParseExt( text, qfalse );
1787 a = atof( token );
1788 a = a / 180 * M_PI;
1789
1790 token = COM_ParseExt( text, qfalse );
1791 b = atof( token );
1792 b = b / 180 * M_PI;
1793
1794 tr.sunDirection[0] = cos( a ) * cos( b );
1795 tr.sunDirection[1] = sin( a ) * cos( b );
1796 tr.sunDirection[2] = sin( b );
1797
1798 if (isGL2Sun)
1799 {
1800 token = COM_ParseExt( text, qfalse );
1801 tr.sunShadowScale = atof(token);
1802
1803 // parse twice, since older shaders may include mapLightScale before sunShadowScale
1804 token = COM_ParseExt( text, qfalse );
1805 if (token[0])
1806 tr.sunShadowScale = atof(token);
1807 }
1808
1809 SkipRestOfLine( text );
1810 continue;
1811 }
1812 // tonemap parms
1813 else if ( !Q_stricmp( token, "q3gl2_tonemap" ) ) {
1814 token = COM_ParseExt( text, qfalse );
1815 tr.toneMinAvgMaxLevel[0] = atof( token );
1816 token = COM_ParseExt( text, qfalse );
1817 tr.toneMinAvgMaxLevel[1] = atof( token );
1818 token = COM_ParseExt( text, qfalse );
1819 tr.toneMinAvgMaxLevel[2] = atof( token );
1820
1821 token = COM_ParseExt( text, qfalse );
1822 tr.autoExposureMinMax[0] = atof( token );
1823 token = COM_ParseExt( text, qfalse );
1824 tr.autoExposureMinMax[1] = atof( token );
1825
1826 SkipRestOfLine( text );
1827 continue;
1828 } else if ( !Q_stricmp( token, "deformVertexes" ) ) {
1829 ParseDeform( text );
1830 continue;
1831 } else if ( !Q_stricmp( token, "tesssize" ) ) {
1832 SkipRestOfLine( text );
1833 continue;
1834 } else if ( !Q_stricmp( token, "clampTime" ) ) {
1835 token = COM_ParseExt( text, qfalse );
1836 if ( token[0] ) {
1837 shader.clampTime = atof( token );
1838 }
1839 }
1840 // skip stuff that only the q3map needs
1841 else if ( !Q_stricmpn( token, "q3map", 5 ) ) {
1842 SkipRestOfLine( text );
1843 continue;
1844 }
1845 // skip stuff that only q3map or the server needs
1846 else if ( !Q_stricmp( token, "surfaceParm" ) ) {
1847 ParseSurfaceParm( text );
1848 continue;
1849 }
1850 // no mip maps
1851 else if ( !Q_stricmp( token, "nomipmaps" ) ) {
1852 shader.noMipMaps = qtrue;
1853 shader.noPicMip = qtrue;
1854 continue;
1855 }
1856 // no picmip adjustment
1857 else if ( !Q_stricmp( token, "nopicmip" ) ) {
1858 shader.noPicMip = qtrue;
1859 continue;
1860 }
1861 // character picmip adjustment
1862 else if ( !Q_stricmp( token, "picmip2" ) ) {
1863 shader.characterMip = qtrue;
1864 continue;
1865 }
1866 // polygonOffset
1867 else if ( !Q_stricmp( token, "polygonOffset" ) ) {
1868 shader.polygonOffset = qtrue;
1869 continue;
1870 }
1871 // entityMergable, allowing sprite surfaces from multiple entities
1872 // to be merged into one batch. This is a savings for smoke
1873 // puffs and blood, but can't be used for anything where the
1874 // shader calcs (not the surface function) reference the entity color or scroll
1875 else if ( !Q_stricmp( token, "entityMergable" ) ) {
1876 shader.entityMergable = qtrue;
1877 continue;
1878 }
1879 // fogParms
1880 else if ( !Q_stricmp( token, "fogParms" ) ) {
1881 if ( !ParseVector( text, 3, shader.fogParms.color ) ) {
1882 return qfalse;
1883 }
1884
1885 if ( r_greyscale->integer )
1886 {
1887 float luminance;
1888
1889 luminance = LUMA( shader.fogParms.color[0], shader.fogParms.color[1], shader.fogParms.color[2] );
1890 VectorSet( shader.fogParms.color, luminance, luminance, luminance );
1891 }
1892 else if ( r_greyscale->value )
1893 {
1894 float luminance;
1895
1896 luminance = LUMA( shader.fogParms.color[0], shader.fogParms.color[1], shader.fogParms.color[2] );
1897 shader.fogParms.color[0] = LERP( shader.fogParms.color[0], luminance, r_greyscale->value );
1898 shader.fogParms.color[1] = LERP( shader.fogParms.color[1], luminance, r_greyscale->value );
1899 shader.fogParms.color[2] = LERP( shader.fogParms.color[2], luminance, r_greyscale->value );
1900 }
1901
1902 token = COM_ParseExt( text, qfalse );
1903 if ( !token[0] ) {
1904 ri.Printf( PRINT_WARNING, "WARNING: missing parm for 'fogParms' keyword in shader '%s'\n", shader.name );
1905 continue;
1906 }
1907 shader.fogParms.depthForOpaque = atof( token );
1908
1909 // skip any old gradient directions
1910 SkipRestOfLine( text );
1911 continue;
1912 }
1913 // portal
1914 else if ( !Q_stricmp( token, "portal" ) ) {
1915 shader.sort = SS_PORTAL;
1916 shader.isPortal = qtrue;
1917 continue;
1918 }
1919 // skyparms <cloudheight> <outerbox> <innerbox>
1920 else if ( !Q_stricmp( token, "skyparms" ) ) {
1921 ParseSkyParms( text );
1922 continue;
1923 }
1924 // This is fixed fog for the skybox/clouds determined solely by the shader
1925 // it will not change in a level and will not be necessary
1926 // to force clients to use a sky fog the server says to.
1927 // skyfogvars <(r,g,b)> <dist>
1928 else if ( !Q_stricmp( token, "skyfogvars" ) ) {
1929 vec3_t fogColor;
1930
1931 if ( !ParseVector( text, 3, fogColor ) ) {
1932 return qfalse;
1933 }
1934 token = COM_ParseExt( text, qfalse );
1935
1936 if ( !token[0] ) {
1937 ri.Printf( PRINT_WARNING, "WARNING: missing density value for sky fog\n" );
1938 continue;
1939 }
1940
1941 if ( atof( token ) > 1 ) {
1942 ri.Printf( PRINT_WARNING, "WARNING: last value for skyfogvars is 'density' which needs to be 0.0-1.0\n" );
1943 continue;
1944 }
1945
1946 R_SetFog( FOG_SKY, 0, 5, fogColor[0], fogColor[1], fogColor[2], atof( token ) );
1947 continue;
1948 } else if ( !Q_stricmp( token, "sunshader" ) ) {
1949 token = COM_ParseExt( text, qfalse );
1950 if ( !token[0] ) {
1951 ri.Printf( PRINT_WARNING, "WARNING: missing shader name for 'sunshader'\n" );
1952 continue;
1953 }
1954 // tr.sunShaderName = CopyString( token );
1955 tr.sunShaderName = "sun";
1956 }
1957 //----(SA) added
1958 else if ( !Q_stricmp( token, "lightgridmulamb" ) ) { // ambient multiplier for lightgrid
1959 token = COM_ParseExt( text, qfalse );
1960 if ( !token[0] ) {
1961 ri.Printf( PRINT_WARNING, "WARNING: missing value for 'lightgrid ambient multiplier'\n" );
1962 continue;
1963 }
1964 if ( atof( token ) > 0 ) {
1965 tr.lightGridMulAmbient = atof( token );
1966 }
1967 } else if ( !Q_stricmp( token, "lightgridmuldir" ) ) { // directional multiplier for lightgrid
1968 token = COM_ParseExt( text, qfalse );
1969 if ( !token[0] ) {
1970 ri.Printf( PRINT_WARNING, "WARNING: missing value for 'lightgrid directional multiplier'\n" );
1971 continue;
1972 }
1973 if ( atof( token ) > 0 ) {
1974 tr.lightGridMulDirected = atof( token );
1975 }
1976 }
1977 //----(SA) end
1978 else if ( !Q_stricmp( token, "waterfogvars" ) ) {
1979 vec3_t watercolor;
1980 float fogvar;
1981 char fogString[64];
1982
1983 if ( !ParseVector( text, 3, watercolor ) ) {
1984 return qfalse;
1985 }
1986 token = COM_ParseExt( text, qfalse );
1987
1988 if ( !token[0] ) {
1989 ri.Printf( PRINT_WARNING, "WARNING: missing density/distance value for water fog\n" );
1990 continue;
1991 }
1992
1993 fogvar = atof( token );
1994
1995 //----(SA) right now allow one water color per map. I'm sure this will need
1996 // to change at some point, but I'm not sure how to track fog parameters
1997 // on a "per-water volume" basis yet.
1998
1999 if ( fogvar == 0 ) { // '0' specifies "use the map values for everything except the fog color
2000 // TODO
2001 } else if ( fogvar > 1 ) { // distance "linear" fog
2002 Com_sprintf( fogString, sizeof( fogString ), "0 %d 1.1 %f %f %f 200", (int)fogvar, watercolor[0], watercolor[1], watercolor[2] );
2003 // R_SetFog(FOG_WATER, 0, fogvar, watercolor[0], watercolor[1], watercolor[2], 1.1);
2004 } else { // density "exp" fog
2005 Com_sprintf( fogString, sizeof( fogString ), "0 5 %f %f %f %f 200", fogvar, watercolor[0], watercolor[1], watercolor[2] );
2006 // R_SetFog(FOG_WATER, 0, 5, watercolor[0], watercolor[1], watercolor[2], fogvar);
2007 }
2008
2009 // near
2010 // far
2011 // density
2012 // r,g,b
2013 // time to complete
2014 ri.Cvar_Set( "r_waterFogColor", fogString );
2015
2016 continue;
2017 }
2018 // fogvars
2019 else if ( !Q_stricmp( token, "fogvars" ) ) {
2020 vec3_t fogColor;
2021 float fogDensity;
2022 int fogFar;
2023
2024 if ( !ParseVector( text, 3, fogColor ) ) {
2025 return qfalse;
2026 }
2027
2028 token = COM_ParseExt( text, qfalse );
2029 if ( !token[0] ) {
2030 ri.Printf( PRINT_WARNING, "WARNING: missing density value for the fog\n" );
2031 continue;
2032 }
2033
2034
2035 //----(SA) NOTE: fogFar > 1 means the shader is setting the farclip, < 1 means setting
2036 // density (so old maps or maps that just need softening fog don't have to care about farclip)
2037
2038 fogDensity = atof( token );
2039 if ( fogDensity >= 1 ) { // linear
2040 fogFar = fogDensity;
2041 } else {
2042 fogFar = 5;
2043 }
2044
2045 // R_SetFog(FOG_MAP, 0, fogFar, fogColor[0], fogColor[1], fogColor[2], fogDensity);
2046 ri.Cvar_Set( "r_mapFogColor", va( "0 %d %f %f %f %f 0", fogFar, fogDensity, fogColor[0], fogColor[1], fogColor[2] ) );
2047 // R_SetFog(FOG_CMD_SWITCHFOG, FOG_MAP, 50, 0, 0, 0, 0);
2048
2049 continue;
2050 }
2051 // done.
2052 // Ridah, allow disable fog for some shaders
2053 else if ( !Q_stricmp( token, "nofog" ) ) {
2054 shader.noFog = qtrue;
2055 continue;
2056 }
2057 // done.
2058 // RF, allow each shader to permit compression if available
2059 else if ( !Q_stricmp( token, "allowcompress" ) ) {
2060 tr.allowCompress = qtrue;
2061 continue;
2062 } else if ( !Q_stricmp( token, "nocompress" ) ) {
2063 tr.allowCompress = -1;
2064 continue;
2065 }
2066 // done.
2067 // light <value> determines flaring in q3map, not needed here
2068 else if ( !Q_stricmp( token, "light" ) ) {
2069 COM_ParseExt( text, qfalse );
2070 continue;
2071 }
2072 // cull <face>
2073 else if ( !Q_stricmp( token, "cull" ) ) {
2074 token = COM_ParseExt( text, qfalse );
2075 if ( token[0] == 0 ) {
2076 ri.Printf( PRINT_WARNING, "WARNING: missing cull parms in shader '%s'\n", shader.name );
2077 continue;
2078 }
2079
2080 if ( !Q_stricmp( token, "none" ) || !Q_stricmp( token, "twosided" ) || !Q_stricmp( token, "disable" ) ) {
2081 shader.cullType = CT_TWO_SIDED;
2082 } else if ( !Q_stricmp( token, "back" ) || !Q_stricmp( token, "backside" ) || !Q_stricmp( token, "backsided" ) ) {
2083 shader.cullType = CT_BACK_SIDED;
2084 } else
2085 {
2086 ri.Printf( PRINT_WARNING, "WARNING: invalid cull parm '%s' in shader '%s'\n", token, shader.name );
2087 }
2088 continue;
2089 }
2090 // sort
2091 else if ( !Q_stricmp( token, "sort" ) ) {
2092 ParseSort( text );
2093 continue;
2094 } else
2095 {
2096 ri.Printf( PRINT_WARNING, "WARNING: unknown general shader parameter '%s' in '%s'\n", token, shader.name );
2097 return qfalse;
2098 }
2099 }
2100
2101 //
2102 // ignore shaders that don't have any stages, unless it is a sky or fog
2103 //
2104 if ( s == 0 && !shader.isSky && !( shader.contentFlags & CONTENTS_FOG ) ) {
2105 return qfalse;
2106 }
2107
2108 shader.explicitlyDefined = qtrue;
2109
2110 return qtrue;
2111 }
2112
2113 /*
2114 ========================================================================================
2115
2116 SHADER OPTIMIZATION AND FOGGING
2117
2118 ========================================================================================
2119 */
2120
2121 /*
2122 ===================
2123 ComputeStageIteratorFunc
2124
2125 See if we can use on of the simple fastpath stage functions,
2126 otherwise set to the generic stage function
2127 ===================
2128 */
ComputeStageIteratorFunc(void)2129 static void ComputeStageIteratorFunc( void )
2130 {
2131 shader.optimalStageIteratorFunc = RB_StageIteratorGeneric;
2132
2133 //
2134 // see if this should go into the sky path
2135 //
2136 if ( shader.isSky )
2137 {
2138 shader.optimalStageIteratorFunc = RB_StageIteratorSky;
2139 return;
2140 }
2141 }
2142
2143 /*
2144 ===================
2145 ComputeVertexAttribs
2146
2147 Check which vertex attributes we only need, so we
2148 don't need to submit/copy all of them.
2149 ===================
2150 */
ComputeVertexAttribs(void)2151 static void ComputeVertexAttribs(void)
2152 {
2153 int i, stage;
2154
2155 // dlights always need ATTR_NORMAL
2156 shader.vertexAttribs = ATTR_POSITION | ATTR_NORMAL;
2157
2158 // portals always need normals, for SurfIsOffscreen()
2159 if (shader.isPortal)
2160 {
2161 shader.vertexAttribs |= ATTR_NORMAL;
2162 }
2163
2164 if (shader.defaultShader)
2165 {
2166 shader.vertexAttribs |= ATTR_TEXCOORD;
2167 return;
2168 }
2169
2170 if(shader.numDeforms)
2171 {
2172 for ( i = 0; i < shader.numDeforms; i++)
2173 {
2174 deformStage_t *ds = &shader.deforms[i];
2175
2176 switch (ds->deformation)
2177 {
2178 case DEFORM_BULGE:
2179 shader.vertexAttribs |= ATTR_NORMAL | ATTR_TEXCOORD;
2180 break;
2181
2182 case DEFORM_AUTOSPRITE:
2183 shader.vertexAttribs |= ATTR_NORMAL | ATTR_COLOR;
2184 break;
2185
2186 case DEFORM_WAVE:
2187 case DEFORM_NORMALS:
2188 case DEFORM_TEXT0:
2189 case DEFORM_TEXT1:
2190 case DEFORM_TEXT2:
2191 case DEFORM_TEXT3:
2192 case DEFORM_TEXT4:
2193 case DEFORM_TEXT5:
2194 case DEFORM_TEXT6:
2195 case DEFORM_TEXT7:
2196 shader.vertexAttribs |= ATTR_NORMAL;
2197 break;
2198
2199 default:
2200 case DEFORM_NONE:
2201 case DEFORM_MOVE:
2202 case DEFORM_PROJECTION_SHADOW:
2203 case DEFORM_AUTOSPRITE2:
2204 break;
2205 }
2206 }
2207 }
2208
2209 for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ )
2210 {
2211 shaderStage_t *pStage = &stages[stage];
2212
2213 if ( !pStage->active )
2214 {
2215 break;
2216 }
2217
2218 if (pStage->glslShaderGroup == tr.lightallShader)
2219 {
2220 shader.vertexAttribs |= ATTR_NORMAL;
2221
2222 if ((pStage->glslShaderIndex & LIGHTDEF_LIGHTTYPE_MASK) && !(r_normalMapping->integer == 0 && r_specularMapping->integer == 0))
2223 {
2224 shader.vertexAttribs |= ATTR_TANGENT;
2225 }
2226
2227 switch (pStage->glslShaderIndex & LIGHTDEF_LIGHTTYPE_MASK)
2228 {
2229 case LIGHTDEF_USE_LIGHTMAP:
2230 case LIGHTDEF_USE_LIGHT_VERTEX:
2231 shader.vertexAttribs |= ATTR_LIGHTDIRECTION;
2232 break;
2233 default:
2234 break;
2235 }
2236 }
2237
2238 for (i = 0; i < NUM_TEXTURE_BUNDLES; i++)
2239 {
2240 if ( pStage->bundle[i].image[0] == 0 )
2241 {
2242 continue;
2243 }
2244
2245 switch(pStage->bundle[i].tcGen)
2246 {
2247 case TCGEN_TEXTURE:
2248 shader.vertexAttribs |= ATTR_TEXCOORD;
2249 break;
2250 case TCGEN_LIGHTMAP:
2251 shader.vertexAttribs |= ATTR_LIGHTCOORD;
2252 break;
2253 case TCGEN_ENVIRONMENT_MAPPED:
2254 shader.vertexAttribs |= ATTR_NORMAL;
2255 break;
2256
2257 default:
2258 break;
2259 }
2260 }
2261
2262 switch(pStage->rgbGen)
2263 {
2264 case CGEN_EXACT_VERTEX:
2265 case CGEN_VERTEX:
2266 case CGEN_EXACT_VERTEX_LIT:
2267 case CGEN_VERTEX_LIT:
2268 case CGEN_ONE_MINUS_VERTEX:
2269 shader.vertexAttribs |= ATTR_COLOR;
2270 break;
2271
2272 case CGEN_LIGHTING_DIFFUSE:
2273 shader.vertexAttribs |= ATTR_NORMAL;
2274 break;
2275
2276 default:
2277 break;
2278 }
2279
2280 switch(pStage->alphaGen)
2281 {
2282 case AGEN_LIGHTING_SPECULAR:
2283 shader.vertexAttribs |= ATTR_NORMAL;
2284 break;
2285
2286 case AGEN_NORMALZFADE:
2287 break;
2288 case AGEN_VERTEX:
2289 case AGEN_ONE_MINUS_VERTEX:
2290 shader.vertexAttribs |= ATTR_COLOR;
2291 break;
2292
2293 default:
2294 break;
2295 }
2296 }
2297 }
2298
2299
CollapseStagesToLightall(shaderStage_t * diffuse,shaderStage_t * normal,shaderStage_t * specular,shaderStage_t * lightmap,qboolean useLightVector,qboolean useLightVertex,qboolean parallax,qboolean tcgen)2300 static void CollapseStagesToLightall(shaderStage_t *diffuse,
2301 shaderStage_t *normal, shaderStage_t *specular, shaderStage_t *lightmap,
2302 qboolean useLightVector, qboolean useLightVertex, qboolean parallax, qboolean tcgen)
2303 {
2304 int defs = 0;
2305
2306 //ri.Printf(PRINT_ALL, "shader %s has diffuse %s", shader.name, diffuse->bundle[0].image[0]->imgName);
2307
2308 // reuse diffuse, mark others inactive
2309 diffuse->type = ST_GLSL;
2310
2311 if (lightmap)
2312 {
2313 //ri.Printf(PRINT_ALL, ", lightmap");
2314 diffuse->bundle[TB_LIGHTMAP] = lightmap->bundle[0];
2315 defs |= LIGHTDEF_USE_LIGHTMAP;
2316 }
2317 else if (useLightVector)
2318 {
2319 defs |= LIGHTDEF_USE_LIGHT_VECTOR;
2320 }
2321 else if (useLightVertex)
2322 {
2323 defs |= LIGHTDEF_USE_LIGHT_VERTEX;
2324 }
2325
2326 if (r_deluxeMapping->integer && tr.worldDeluxeMapping && lightmap && shader.lightmapIndex >= 0)
2327 {
2328 //ri.Printf(PRINT_ALL, ", deluxemap");
2329 diffuse->bundle[TB_DELUXEMAP] = lightmap->bundle[0];
2330 diffuse->bundle[TB_DELUXEMAP].image[0] = tr.deluxemaps[shader.lightmapIndex];
2331 }
2332
2333 if (r_normalMapping->integer)
2334 {
2335 image_t *diffuseImg;
2336 if (normal)
2337 {
2338 //ri.Printf(PRINT_ALL, ", normalmap %s", normal->bundle[0].image[0]->imgName);
2339 diffuse->bundle[TB_NORMALMAP] = normal->bundle[0];
2340 if (parallax && r_parallaxMapping->integer)
2341 defs |= LIGHTDEF_USE_PARALLAXMAP;
2342
2343 VectorCopy4(normal->normalScale, diffuse->normalScale);
2344 }
2345 else if ((lightmap || useLightVector || useLightVertex) && (diffuseImg = diffuse->bundle[TB_DIFFUSEMAP].image[0]))
2346 {
2347 char normalName[MAX_QPATH];
2348 image_t *normalImg;
2349 imgFlags_t normalFlags = (diffuseImg->flags & ~IMGFLAG_GENNORMALMAP) | IMGFLAG_NOLIGHTSCALE;
2350
2351 // try a normalheight image first
2352 COM_StripExtension(diffuseImg->imgName, normalName, MAX_QPATH);
2353 Q_strcat(normalName, MAX_QPATH, "_nh");
2354
2355 normalImg = R_FindImageFile(normalName, IMGTYPE_NORMALHEIGHT, normalFlags);
2356
2357 if (normalImg)
2358 {
2359 parallax = qtrue;
2360 }
2361 else
2362 {
2363 // try a normal image ("_n" suffix)
2364 normalName[strlen(normalName) - 1] = '\0';
2365 normalImg = R_FindImageFile(normalName, IMGTYPE_NORMAL, normalFlags);
2366 }
2367
2368 if (normalImg)
2369 {
2370 diffuse->bundle[TB_NORMALMAP] = diffuse->bundle[0];
2371 diffuse->bundle[TB_NORMALMAP].numImageAnimations = 0;
2372 diffuse->bundle[TB_NORMALMAP].image[0] = normalImg;
2373
2374 if (parallax && r_parallaxMapping->integer)
2375 defs |= LIGHTDEF_USE_PARALLAXMAP;
2376
2377 VectorSet4(diffuse->normalScale, r_baseNormalX->value, r_baseNormalY->value, 1.0f, r_baseParallax->value);
2378 }
2379 }
2380 }
2381
2382 if (r_specularMapping->integer)
2383 {
2384 image_t *diffuseImg;
2385 if (specular)
2386 {
2387 //ri.Printf(PRINT_ALL, ", specularmap %s", specular->bundle[0].image[0]->imgName);
2388 diffuse->bundle[TB_SPECULARMAP] = specular->bundle[0];
2389 VectorCopy4(specular->specularScale, diffuse->specularScale);
2390 }
2391 else if ((lightmap || useLightVector || useLightVertex) && (diffuseImg = diffuse->bundle[TB_DIFFUSEMAP].image[0]))
2392 {
2393 char specularName[MAX_QPATH];
2394 image_t *specularImg;
2395 imgFlags_t specularFlags = (diffuseImg->flags & ~IMGFLAG_GENNORMALMAP) | IMGFLAG_NOLIGHTSCALE;
2396
2397 COM_StripExtension(diffuseImg->imgName, specularName, MAX_QPATH);
2398 Q_strcat(specularName, MAX_QPATH, "_s");
2399
2400 specularImg = R_FindImageFile(specularName, IMGTYPE_COLORALPHA, specularFlags);
2401
2402 if (specularImg)
2403 {
2404 diffuse->bundle[TB_SPECULARMAP] = diffuse->bundle[0];
2405 diffuse->bundle[TB_SPECULARMAP].numImageAnimations = 0;
2406 diffuse->bundle[TB_SPECULARMAP].image[0] = specularImg;
2407
2408 VectorSet4(diffuse->specularScale, 1.0f, 1.0f, 1.0f, 1.0f);
2409 }
2410 }
2411 }
2412
2413 if (tcgen || diffuse->bundle[0].numTexMods)
2414 {
2415 defs |= LIGHTDEF_USE_TCGEN_AND_TCMOD;
2416 }
2417
2418 //ri.Printf(PRINT_ALL, ".\n");
2419
2420 diffuse->glslShaderGroup = tr.lightallShader;
2421 diffuse->glslShaderIndex = defs;
2422 }
2423
2424
CollapseStagesToGLSL(void)2425 static int CollapseStagesToGLSL(void)
2426 {
2427 int i, j, numStages;
2428 qboolean skip = qfalse;
2429
2430 // skip shaders with deforms
2431 if (shader.numDeforms != 0)
2432 {
2433 skip = qtrue;
2434 }
2435
2436 if (!skip)
2437 {
2438 // if 2+ stages and first stage is lightmap, switch them
2439 // this makes it easier for the later bits to process
2440 if (stages[0].active && stages[0].bundle[0].tcGen == TCGEN_LIGHTMAP && stages[1].active)
2441 {
2442 int blendBits = stages[1].stateBits & ( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS );
2443
2444 if (blendBits == (GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO)
2445 || blendBits == (GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR))
2446 {
2447 int stateBits0 = stages[0].stateBits;
2448 int stateBits1 = stages[1].stateBits;
2449 shaderStage_t swapStage;
2450
2451 swapStage = stages[0];
2452 stages[0] = stages[1];
2453 stages[1] = swapStage;
2454
2455 stages[0].stateBits = stateBits0;
2456 stages[1].stateBits = stateBits1;
2457 }
2458 }
2459 }
2460
2461 if (!skip)
2462 {
2463 // scan for shaders that aren't supported
2464 for (i = 0; i < MAX_SHADER_STAGES; i++)
2465 {
2466 shaderStage_t *pStage = &stages[i];
2467
2468 if (!pStage->active)
2469 continue;
2470
2471 if (pStage->adjustColorsForFog)
2472 {
2473 skip = qtrue;
2474 break;
2475 }
2476
2477 if (pStage->bundle[0].tcGen == TCGEN_LIGHTMAP)
2478 {
2479 int blendBits = pStage->stateBits & ( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS );
2480
2481 if (blendBits != (GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO)
2482 && blendBits != (GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR))
2483 {
2484 skip = qtrue;
2485 break;
2486 }
2487 }
2488
2489 switch(pStage->bundle[0].tcGen)
2490 {
2491 case TCGEN_TEXTURE:
2492 case TCGEN_LIGHTMAP:
2493 case TCGEN_ENVIRONMENT_MAPPED:
2494 case TCGEN_VECTOR:
2495 break;
2496 default:
2497 skip = qtrue;
2498 break;
2499 }
2500
2501 switch(pStage->alphaGen)
2502 {
2503 case AGEN_LIGHTING_SPECULAR:
2504 case AGEN_PORTAL:
2505 case AGEN_NORMALZFADE:
2506 skip = qtrue;
2507 break;
2508 default:
2509 break;
2510 }
2511 }
2512 }
2513
2514 if (!skip)
2515 {
2516 qboolean usedLightmap = qfalse;
2517
2518 for (i = 0; i < MAX_SHADER_STAGES; i++)
2519 {
2520 shaderStage_t *pStage = &stages[i];
2521 shaderStage_t *diffuse, *normal, *specular, *lightmap;
2522 qboolean parallax, tcgen, diffuselit, vertexlit;
2523
2524 if (!pStage->active)
2525 continue;
2526
2527 // skip normal and specular maps
2528 if (pStage->type != ST_COLORMAP)
2529 continue;
2530
2531 // skip lightmaps
2532 if (pStage->bundle[0].tcGen == TCGEN_LIGHTMAP)
2533 continue;
2534
2535 diffuse = pStage;
2536 normal = NULL;
2537 parallax = qfalse;
2538 specular = NULL;
2539 lightmap = NULL;
2540
2541 // we have a diffuse map, find matching normal, specular, and lightmap
2542 for (j = i + 1; j < MAX_SHADER_STAGES; j++)
2543 {
2544 shaderStage_t *pStage2 = &stages[j];
2545
2546 if (!pStage2->active)
2547 continue;
2548
2549 switch(pStage2->type)
2550 {
2551 case ST_NORMALMAP:
2552 if (!normal)
2553 {
2554 normal = pStage2;
2555 }
2556 break;
2557
2558 case ST_NORMALPARALLAXMAP:
2559 if (!normal)
2560 {
2561 normal = pStage2;
2562 parallax = qtrue;
2563 }
2564 break;
2565
2566 case ST_SPECULARMAP:
2567 if (!specular)
2568 {
2569 specular = pStage2;
2570 }
2571 break;
2572
2573 case ST_COLORMAP:
2574 if (pStage2->bundle[0].tcGen == TCGEN_LIGHTMAP)
2575 {
2576 int blendBits = pStage->stateBits & ( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS );
2577
2578 // Only add lightmap to blendfunc filter stage if it's the first time lightmap is used
2579 // otherwise it will cause the shader to be darkened by the lightmap multiple times.
2580 if (!usedLightmap || (blendBits != (GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO)
2581 && blendBits != (GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR)))
2582 {
2583 lightmap = pStage2;
2584 usedLightmap = qtrue;
2585 }
2586 }
2587 break;
2588
2589 default:
2590 break;
2591 }
2592 }
2593
2594 tcgen = qfalse;
2595 if (diffuse->bundle[0].tcGen == TCGEN_ENVIRONMENT_MAPPED
2596 || diffuse->bundle[0].tcGen == TCGEN_LIGHTMAP
2597 || diffuse->bundle[0].tcGen == TCGEN_VECTOR)
2598 {
2599 tcgen = qtrue;
2600 }
2601
2602 diffuselit = qfalse;
2603 if (diffuse->rgbGen == CGEN_LIGHTING_DIFFUSE)
2604 {
2605 diffuselit = qtrue;
2606 }
2607
2608 vertexlit = qfalse;
2609 if (diffuse->rgbGen == CGEN_VERTEX_LIT || diffuse->rgbGen == CGEN_EXACT_VERTEX_LIT)
2610 {
2611 vertexlit = qtrue;
2612 }
2613
2614 CollapseStagesToLightall(diffuse, normal, specular, lightmap, diffuselit, vertexlit, parallax, tcgen);
2615 }
2616
2617 // deactivate lightmap stages
2618 for (i = 0; i < MAX_SHADER_STAGES; i++)
2619 {
2620 shaderStage_t *pStage = &stages[i];
2621
2622 if (!pStage->active)
2623 continue;
2624
2625 if (pStage->bundle[0].tcGen == TCGEN_LIGHTMAP)
2626 {
2627 pStage->active = qfalse;
2628 }
2629 }
2630 }
2631
2632 // deactivate normal and specular stages
2633 for (i = 0; i < MAX_SHADER_STAGES; i++)
2634 {
2635 shaderStage_t *pStage = &stages[i];
2636
2637 if (!pStage->active)
2638 continue;
2639
2640 if (pStage->type == ST_NORMALMAP)
2641 {
2642 pStage->active = qfalse;
2643 }
2644
2645 if (pStage->type == ST_NORMALPARALLAXMAP)
2646 {
2647 pStage->active = qfalse;
2648 }
2649
2650 if (pStage->type == ST_SPECULARMAP)
2651 {
2652 pStage->active = qfalse;
2653 }
2654 }
2655
2656 // remove inactive stages
2657 numStages = 0;
2658 for (i = 0; i < MAX_SHADER_STAGES; i++)
2659 {
2660 if (!stages[i].active)
2661 continue;
2662
2663 if (i == numStages)
2664 {
2665 numStages++;
2666 continue;
2667 }
2668
2669 stages[numStages] = stages[i];
2670 stages[i].active = qfalse;
2671 numStages++;
2672 }
2673
2674 // convert any remaining lightmap stages to a lighting pass with a white texture
2675 // only do this with r_sunlightMode non-zero, as it's only for correct shadows.
2676 if (r_sunlightMode->integer && shader.numDeforms == 0)
2677 {
2678 for (i = 0; i < MAX_SHADER_STAGES; i++)
2679 {
2680 shaderStage_t *pStage = &stages[i];
2681
2682 if (!pStage->active)
2683 continue;
2684
2685 if (pStage->adjustColorsForFog)
2686 continue;
2687
2688 if (pStage->bundle[TB_DIFFUSEMAP].tcGen == TCGEN_LIGHTMAP)
2689 {
2690 pStage->glslShaderGroup = tr.lightallShader;
2691 pStage->glslShaderIndex = LIGHTDEF_USE_LIGHTMAP;
2692 pStage->bundle[TB_LIGHTMAP] = pStage->bundle[TB_DIFFUSEMAP];
2693 pStage->bundle[TB_DIFFUSEMAP].image[0] = tr.whiteImage;
2694 pStage->bundle[TB_DIFFUSEMAP].isLightmap = qfalse;
2695 pStage->bundle[TB_DIFFUSEMAP].tcGen = TCGEN_TEXTURE;
2696 }
2697 }
2698 }
2699
2700 // convert any remaining lightingdiffuse stages to a lighting pass
2701 if (shader.numDeforms == 0)
2702 {
2703 for (i = 0; i < MAX_SHADER_STAGES; i++)
2704 {
2705 shaderStage_t *pStage = &stages[i];
2706
2707 if (!pStage->active)
2708 continue;
2709
2710 if (pStage->adjustColorsForFog)
2711 continue;
2712
2713 if (pStage->rgbGen == CGEN_LIGHTING_DIFFUSE)
2714 {
2715 pStage->glslShaderGroup = tr.lightallShader;
2716 pStage->glslShaderIndex = LIGHTDEF_USE_LIGHT_VECTOR;
2717
2718 if (pStage->bundle[0].tcGen != TCGEN_TEXTURE || pStage->bundle[0].numTexMods != 0)
2719 pStage->glslShaderIndex |= LIGHTDEF_USE_TCGEN_AND_TCMOD;
2720 }
2721 }
2722 }
2723
2724 return numStages;
2725 }
2726
2727 /*
2728 =============
2729 FixRenderCommandList
2730
2731 Arnout: this is a nasty issue. Shaders can be registered after drawsurfaces are generated
2732 but before the frame is rendered. This will, for the duration of one frame, cause drawsurfaces
2733 to be rendered with bad shaders. To fix this, need to go through all render commands and fix
2734 sortedIndex.
2735 ==============
2736 */
FixRenderCommandList(int newShader)2737 static void FixRenderCommandList( int newShader ) {
2738 renderCommandList_t *cmdList = &backEndData->commands;
2739
2740 if ( cmdList ) {
2741 const void *curCmd = cmdList->cmds;
2742
2743 while ( 1 ) {
2744 curCmd = PADP(curCmd, sizeof(void *));
2745
2746 switch ( *(const int *)curCmd ) {
2747 case RC_SET_COLOR:
2748 {
2749 const setColorCommand_t *sc_cmd = (const setColorCommand_t *)curCmd;
2750 curCmd = (const void *)( sc_cmd + 1 );
2751 break;
2752 }
2753 case RC_STRETCH_PIC:
2754 case RC_STRETCH_PIC_GRADIENT:
2755 {
2756 const stretchPicCommand_t *sp_cmd = (const stretchPicCommand_t *)curCmd;
2757 curCmd = (const void *)( sp_cmd + 1 );
2758 break;
2759 }
2760 case RC_DRAW_SURFS:
2761 {
2762 int i;
2763 drawSurf_t *drawSurf;
2764 shader_t *shader;
2765 int fogNum;
2766 int entityNum;
2767 int dlightMap;
2768 int pshadowMap;
2769 int atiTess;
2770 int sortedIndex;
2771 const drawSurfsCommand_t *ds_cmd = (const drawSurfsCommand_t *)curCmd;
2772
2773 for ( i = 0, drawSurf = ds_cmd->drawSurfs; i < ds_cmd->numDrawSurfs; i++, drawSurf++ ) {
2774 R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlightMap, &pshadowMap, &atiTess );
2775 sortedIndex = ( ( drawSurf->sort >> QSORT_SHADERNUM_SHIFT ) & ( MAX_SHADERS - 1 ) );
2776 if ( sortedIndex >= newShader ) {
2777 sortedIndex++;
2778 drawSurf->sort = (sortedIndex << QSORT_SHADERNUM_SHIFT) | entityNum | ( fogNum << QSORT_FOGNUM_SHIFT ) | ( (int)pshadowMap << QSORT_PSHADOW_SHIFT) | (int)dlightMap;
2779 }
2780 }
2781 curCmd = (const void *)( ds_cmd + 1 );
2782 break;
2783 }
2784 case RC_DRAW_BUFFER:
2785 {
2786 const drawBufferCommand_t *db_cmd = (const drawBufferCommand_t *)curCmd;
2787 curCmd = (const void *)( db_cmd + 1 );
2788 break;
2789 }
2790 case RC_SWAP_BUFFERS:
2791 {
2792 const swapBuffersCommand_t *sb_cmd = (const swapBuffersCommand_t *)curCmd;
2793 curCmd = (const void *)( sb_cmd + 1 );
2794 break;
2795 }
2796 case RC_END_OF_LIST:
2797 default:
2798 return;
2799 }
2800 }
2801 }
2802 }
2803
2804 /*
2805 ==============
2806 SortNewShader
2807
2808 Positions the most recently created shader in the tr.sortedShaders[]
2809 array so that the shader->sort key is sorted relative to the other
2810 shaders.
2811
2812 Sets shader->sortedIndex
2813 ==============
2814 */
SortNewShader(void)2815 static void SortNewShader( void ) {
2816 int i;
2817 float sort;
2818 shader_t *newShader;
2819
2820 newShader = tr.shaders[ tr.numShaders - 1 ];
2821 sort = newShader->sort;
2822
2823 for ( i = tr.numShaders - 2 ; i >= 0 ; i-- ) {
2824 if ( tr.sortedShaders[ i ]->sort <= sort ) {
2825 break;
2826 }
2827 tr.sortedShaders[i + 1] = tr.sortedShaders[i];
2828 tr.sortedShaders[i + 1]->sortedIndex++;
2829 }
2830
2831 // Arnout: fix rendercommandlist
2832 FixRenderCommandList( i + 1 );
2833
2834 newShader->sortedIndex = i + 1;
2835 tr.sortedShaders[i + 1] = newShader;
2836 }
2837
2838
2839 /*
2840 ====================
2841 GeneratePermanentShader
2842 ====================
2843 */
GeneratePermanentShader(void)2844 static shader_t *GeneratePermanentShader( void ) {
2845 shader_t *newShader;
2846 int i, b;
2847 int size, hash;
2848
2849 if ( tr.numShaders == MAX_SHADERS ) {
2850 ri.Printf( PRINT_WARNING, "WARNING: GeneratePermanentShader - MAX_SHADERS hit\n" );
2851 return tr.defaultShader;
2852 }
2853
2854 newShader = ri.Hunk_Alloc( sizeof( shader_t ), h_low );
2855
2856 *newShader = shader;
2857
2858 if ( shader.sort <= SS_OPAQUE ) {
2859 newShader->fogPass = FP_EQUAL;
2860 } else if ( shader.contentFlags & CONTENTS_FOG ) {
2861 newShader->fogPass = FP_LE;
2862 }
2863
2864 tr.shaders[ tr.numShaders ] = newShader;
2865 newShader->index = tr.numShaders;
2866
2867 tr.sortedShaders[ tr.numShaders ] = newShader;
2868 newShader->sortedIndex = tr.numShaders;
2869
2870 tr.numShaders++;
2871
2872 for ( i = 0 ; i < newShader->numUnfoggedPasses ; i++ ) {
2873 if ( !stages[i].active ) {
2874 newShader->stages[i] = NULL; // Ridah, make sure it's null
2875 break;
2876 }
2877 newShader->stages[i] = ri.Hunk_Alloc( sizeof( stages[i] ), h_low );
2878 *newShader->stages[i] = stages[i];
2879
2880 for ( b = 0 ; b < NUM_TEXTURE_BUNDLES ; b++ ) {
2881 if ( !newShader->stages[i]->bundle[b].numTexMods ) {
2882 // make sure unalloc'd texMods aren't pointing to some random point in memory
2883 newShader->stages[i]->bundle[b].texMods = NULL;
2884 continue;
2885 }
2886 size = newShader->stages[i]->bundle[b].numTexMods * sizeof( texModInfo_t );
2887 // Ridah, caching system
2888 newShader->stages[i]->bundle[b].texMods = ri.Hunk_Alloc( size, h_low );
2889 memcpy( newShader->stages[i]->bundle[b].texMods, stages[i].bundle[b].texMods, size );
2890 }
2891 }
2892
2893 SortNewShader();
2894
2895 hash = generateHashValue( newShader->name );
2896 newShader->next = hashTable[hash];
2897 hashTable[hash] = newShader;
2898
2899 return newShader;
2900 }
2901
2902 /*
2903 =================
2904 VertexLightingCollapse
2905
2906 If vertex lighting is enabled, only render a single
2907 pass, trying to guess which is the correct one to best aproximate
2908 what it is supposed to look like.
2909 =================
2910 */
VertexLightingCollapse(void)2911 static void VertexLightingCollapse( void ) {
2912 int stage;
2913 shaderStage_t *bestStage;
2914 int bestImageRank;
2915 int rank;
2916
2917 // if we aren't opaque, just use the first pass
2918 if ( shader.sort == SS_OPAQUE ) {
2919
2920 // pick the best texture for the single pass
2921 bestStage = &stages[0];
2922 bestImageRank = -999999;
2923
2924 for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ ) {
2925 shaderStage_t *pStage = &stages[stage];
2926
2927 if ( !pStage->active ) {
2928 break;
2929 }
2930 rank = 0;
2931
2932 if ( pStage->bundle[0].isLightmap ) {
2933 rank -= 100;
2934 }
2935 if ( pStage->bundle[0].tcGen != TCGEN_TEXTURE ) {
2936 rank -= 5;
2937 }
2938 if ( pStage->bundle[0].numTexMods ) {
2939 rank -= 5;
2940 }
2941 if ( pStage->rgbGen != CGEN_IDENTITY && pStage->rgbGen != CGEN_IDENTITY_LIGHTING ) {
2942 rank -= 3;
2943 }
2944
2945 if ( rank > bestImageRank ) {
2946 bestImageRank = rank;
2947 bestStage = pStage;
2948 }
2949 }
2950
2951 stages[0].bundle[0] = bestStage->bundle[0];
2952 stages[0].stateBits &= ~( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS );
2953 stages[0].stateBits |= GLS_DEPTHMASK_TRUE;
2954 if ( shader.lightmapIndex == LIGHTMAP_NONE ) {
2955 stages[0].rgbGen = CGEN_LIGHTING_DIFFUSE;
2956 } else {
2957 stages[0].rgbGen = CGEN_EXACT_VERTEX;
2958 }
2959 stages[0].alphaGen = AGEN_SKIP;
2960 } else {
2961 // don't use a lightmap (tesla coils)
2962 if ( stages[0].bundle[0].isLightmap ) {
2963 stages[0] = stages[1];
2964 }
2965
2966 // if we were in a cross-fade cgen, hack it to normal
2967 if ( stages[0].rgbGen == CGEN_ONE_MINUS_ENTITY || stages[1].rgbGen == CGEN_ONE_MINUS_ENTITY ) {
2968 stages[0].rgbGen = CGEN_IDENTITY_LIGHTING;
2969 }
2970 if ( ( stages[0].rgbGen == CGEN_WAVEFORM && stages[0].rgbWave.func == GF_SAWTOOTH )
2971 && ( stages[1].rgbGen == CGEN_WAVEFORM && stages[1].rgbWave.func == GF_INVERSE_SAWTOOTH ) ) {
2972 stages[0].rgbGen = CGEN_IDENTITY_LIGHTING;
2973 }
2974 if ( ( stages[0].rgbGen == CGEN_WAVEFORM && stages[0].rgbWave.func == GF_INVERSE_SAWTOOTH )
2975 && ( stages[1].rgbGen == CGEN_WAVEFORM && stages[1].rgbWave.func == GF_SAWTOOTH ) ) {
2976 stages[0].rgbGen = CGEN_IDENTITY_LIGHTING;
2977 }
2978 }
2979
2980 for ( stage = 1; stage < MAX_SHADER_STAGES; stage++ ) {
2981 shaderStage_t *pStage = &stages[stage];
2982
2983 if ( !pStage->active ) {
2984 break;
2985 }
2986
2987 memset( pStage, 0, sizeof( *pStage ) );
2988 }
2989 }
2990
2991 /*
2992 ===============
2993 InitShader
2994 ===============
2995 */
InitShader(const char * name,int lightmapIndex)2996 static void InitShader( const char *name, int lightmapIndex ) {
2997 int i;
2998
2999 // clear the global shader
3000 Com_Memset( &shader, 0, sizeof( shader ) );
3001 Com_Memset( &stages, 0, sizeof( stages ) );
3002
3003 Q_strncpyz( shader.name, name, sizeof( shader.name ) );
3004 shader.lightmapIndex = lightmapIndex;
3005
3006 for ( i = 0 ; i < MAX_SHADER_STAGES ; i++ ) {
3007 stages[i].bundle[0].texMods = texMods[i];
3008
3009 // default normal/specular
3010 VectorSet4(stages[i].normalScale, 0.0f, 0.0f, 0.0f, 0.0f);
3011 if (r_pbr->integer)
3012 {
3013 stages[i].specularScale[0] = r_baseGloss->value;
3014 }
3015 else
3016 {
3017 stages[i].specularScale[0] =
3018 stages[i].specularScale[1] =
3019 stages[i].specularScale[2] = r_baseSpecular->value;
3020 stages[i].specularScale[3] = r_baseGloss->value;
3021 }
3022 }
3023 }
3024
3025 /*
3026 =========================
3027 FinishShader
3028
3029 Returns a freshly allocated shader with all the needed info
3030 from the current global working shader
3031 =========================
3032 */
FinishShader(void)3033 static shader_t *FinishShader( void ) {
3034 int stage;
3035 qboolean hasLightmapStage;
3036 qboolean vertexLightmap;
3037
3038 hasLightmapStage = qfalse;
3039 vertexLightmap = qfalse;
3040
3041 //
3042 // set sky stuff appropriate
3043 //
3044 if ( shader.isSky ) {
3045 shader.sort = SS_ENVIRONMENT;
3046 }
3047
3048 //
3049 // set polygon offset
3050 //
3051 if ( shader.polygonOffset && !shader.sort ) {
3052 shader.sort = SS_DECAL;
3053 }
3054
3055 //
3056 // set appropriate stage information
3057 //
3058 for ( stage = 0; stage < MAX_SHADER_STAGES; ) {
3059 shaderStage_t *pStage = &stages[stage];
3060
3061 if ( !pStage->active ) {
3062 break;
3063 }
3064
3065 // check for a missing texture
3066 if ( !pStage->bundle[0].image[0] ) {
3067 ri.Printf( PRINT_WARNING, "Shader %s has a stage with no image\n", shader.name );
3068 pStage->active = qfalse;
3069 stage++;
3070 continue;
3071 }
3072
3073 //
3074 // ditch this stage if it's detail and detail textures are disabled
3075 //
3076 if ( pStage->isDetail && !r_detailTextures->integer )
3077 {
3078 int index;
3079
3080 for(index = stage + 1; index < MAX_SHADER_STAGES; index++)
3081 {
3082 if(!stages[index].active)
3083 break;
3084 }
3085
3086 if(index < MAX_SHADER_STAGES)
3087 memmove(pStage, pStage + 1, sizeof(*pStage) * (index - stage));
3088 else
3089 {
3090 if(stage + 1 < MAX_SHADER_STAGES)
3091 memmove(pStage, pStage + 1, sizeof(*pStage) * (index - stage - 1));
3092
3093 Com_Memset(&stages[index - 1], 0, sizeof(*stages));
3094 }
3095 continue;
3096 }
3097
3098 //
3099 // default texture coordinate generation
3100 //
3101 if ( pStage->bundle[0].isLightmap ) {
3102 if ( pStage->bundle[0].tcGen == TCGEN_BAD ) {
3103 pStage->bundle[0].tcGen = TCGEN_LIGHTMAP;
3104 }
3105 hasLightmapStage = qtrue;
3106 } else {
3107 if ( pStage->bundle[0].tcGen == TCGEN_BAD ) {
3108 pStage->bundle[0].tcGen = TCGEN_TEXTURE;
3109 }
3110 }
3111
3112
3113 // not a true lightmap but we want to leave existing
3114 // behaviour in place and not print out a warning
3115 //if (pStage->rgbGen == CGEN_VERTEX) {
3116 // vertexLightmap = qtrue;
3117 //}
3118
3119
3120
3121 //
3122 // determine sort order and fog color adjustment
3123 //
3124 if ( ( pStage->stateBits & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) ) &&
3125 ( stages[0].stateBits & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) ) ) {
3126 int blendSrcBits = pStage->stateBits & GLS_SRCBLEND_BITS;
3127 int blendDstBits = pStage->stateBits & GLS_DSTBLEND_BITS;
3128
3129 // fog color adjustment only works for blend modes that have a contribution
3130 // that aproaches 0 as the modulate values aproach 0 --
3131 // GL_ONE, GL_ONE
3132 // GL_ZERO, GL_ONE_MINUS_SRC_COLOR
3133 // GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA
3134
3135 // modulate, additive
3136 if ( ( ( blendSrcBits == GLS_SRCBLEND_ONE ) && ( blendDstBits == GLS_DSTBLEND_ONE ) ) ||
3137 ( ( blendSrcBits == GLS_SRCBLEND_ZERO ) && ( blendDstBits == GLS_DSTBLEND_ONE_MINUS_SRC_COLOR ) ) ) {
3138 pStage->adjustColorsForFog = ACFF_MODULATE_RGB;
3139 }
3140 // strict blend
3141 else if ( ( blendSrcBits == GLS_SRCBLEND_SRC_ALPHA ) && ( blendDstBits == GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ) ) {
3142 pStage->adjustColorsForFog = ACFF_MODULATE_ALPHA;
3143 }
3144 // premultiplied alpha
3145 else if ( ( blendSrcBits == GLS_SRCBLEND_ONE ) && ( blendDstBits == GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ) ) {
3146 pStage->adjustColorsForFog = ACFF_MODULATE_RGBA;
3147 } else {
3148 // we can't adjust this one correctly, so it won't be exactly correct in fog
3149 }
3150
3151 // don't screw with sort order if this is a portal or environment
3152 if ( !shader.sort ) {
3153 // see through item, like a grill or grate
3154 if ( pStage->stateBits & GLS_DEPTHMASK_TRUE ) {
3155 shader.sort = SS_SEE_THROUGH;
3156 } else {
3157 shader.sort = SS_BLEND0;
3158 }
3159 }
3160 }
3161
3162 stage++;
3163 }
3164
3165 // there are times when you will need to manually apply a sort to
3166 // opaque alpha tested shaders that have later blend passes
3167 if ( !shader.sort ) {
3168 shader.sort = SS_OPAQUE;
3169 }
3170
3171 //
3172 // if we are in r_vertexLight mode, never use a lightmap texture
3173 //
3174 if ( 0 && ( stage > 1 && ( ( r_vertexLight->integer && !r_uiFullScreen->integer ) || glConfig.hardwareType == GLHW_PERMEDIA2 ) ) ) {
3175 VertexLightingCollapse();
3176 hasLightmapStage = qfalse;
3177 }
3178
3179 //
3180 // look for multitexture potential
3181 //
3182 stage = CollapseStagesToGLSL();
3183
3184 if ( shader.lightmapIndex >= 0 && !hasLightmapStage ) {
3185 if ( vertexLightmap ) {
3186 ri.Printf( PRINT_DEVELOPER, "WARNING: shader '%s' has VERTEX forced lightmap!\n", shader.name );
3187 } else {
3188 ri.Printf( PRINT_DEVELOPER, "WARNING: shader '%s' has lightmap but no lightmap stage!\n", shader.name );
3189 // Don't set this, it will just add duplicate shaders to the hash
3190 //shader.lightmapIndex = LIGHTMAP_NONE;
3191 }
3192 }
3193
3194
3195 //
3196 // compute number of passes
3197 //
3198 shader.numUnfoggedPasses = stage;
3199
3200 // fogonly shaders don't have any normal passes
3201 if (stage == 0 && !shader.isSky)
3202 shader.sort = SS_FOG;
3203
3204 // determine which stage iterator function is appropriate
3205 ComputeStageIteratorFunc();
3206
3207 // determine which vertex attributes this shader needs
3208 ComputeVertexAttribs();
3209
3210 // RF default back to no compression for next shader
3211 if ( r_ext_compressed_textures->integer == 2 ) {
3212 tr.allowCompress = qfalse;
3213 }
3214
3215 return GeneratePermanentShader();
3216 }
3217
3218 //========================================================================================
3219
3220 /*
3221 ====================
3222 FindShaderInShaderText
3223
3224 Scans the combined text description of all the shader files for
3225 the given shader name.
3226
3227 return NULL if not found
3228
3229 If found, it will return a valid shader
3230 =====================
3231 */
FindShaderInShaderText(const char * shadername)3232 static char *FindShaderInShaderText( const char *shadername ) {
3233 char *p = s_shaderText;
3234 char *token;
3235
3236 if ( !p ) {
3237 return NULL;
3238 }
3239
3240 // Ridah, optimized shader loading
3241 {
3242 shaderStringPointer_t *pShaderString;
3243 unsigned short int checksum;
3244
3245 checksum = generateHashValue( shadername );
3246
3247 // if it's known, skip straight to it's position
3248 pShaderString = &shaderChecksumLookup[checksum];
3249 while ( pShaderString && pShaderString->pStr ) {
3250 p = pShaderString->pStr;
3251
3252 token = COM_ParseExt( &p, qtrue );
3253
3254 if ( ( token[0] != 0 ) && !Q_stricmp( token, shadername ) ) {
3255 return p;
3256 }
3257
3258 pShaderString = pShaderString->next;
3259 }
3260 }
3261 // done.
3262
3263 /*
3264 // look for label
3265 // note that this could get confused if a shader name is used inside
3266 // another shader definition
3267 while ( 1 ) {
3268 token = COM_ParseExt( &p, qtrue );
3269 if ( token[0] == 0 ) {
3270 break;
3271 }
3272
3273 if ( token[0] == '{' ) {
3274 // skip the definition
3275 SkipBracedSection( &p, 0 );
3276 } else if ( !Q_stricmp( token, shadername ) ) {
3277 return p;
3278 } else {
3279 // skip to end of line
3280 SkipRestOfLine( &p );
3281 }
3282 }
3283 */
3284
3285 return NULL;
3286 }
3287
3288 /*
3289 ==================
3290 R_FindShaderByName
3291
3292 Will always return a valid shader, but it might be the
3293 default shader if the real one can't be found.
3294 ==================
3295 */
R_FindShaderByName(const char * name)3296 shader_t *R_FindShaderByName( const char *name ) {
3297 char strippedName[MAX_QPATH];
3298 int hash;
3299 shader_t *sh;
3300
3301 if ( ( name == NULL ) || ( name[0] == 0 ) ) {
3302 return tr.defaultShader;
3303 }
3304
3305 COM_StripExtension( name, strippedName, sizeof( strippedName ) );
3306
3307 hash = generateHashValue( strippedName );
3308
3309 //
3310 // see if the shader is already loaded
3311 //
3312 for ( sh = hashTable[hash]; sh; sh = sh->next ) {
3313 // NOTE: if there was no shader or image available with the name strippedName
3314 // then a default shader is created with lightmapIndex == LIGHTMAP_NONE, so we
3315 // have to check all default shaders otherwise for every call to R_FindShader
3316 // with that same strippedName a new default shader is created.
3317 if ( Q_stricmp( sh->name, strippedName ) == 0 ) {
3318 // match found
3319 return sh;
3320 }
3321 }
3322
3323 return tr.defaultShader;
3324 }
3325
3326
3327 /*
3328 ===============
3329 R_FindShader
3330
3331 Will always return a valid shader, but it might be the
3332 default shader if the real one can't be found.
3333
3334 In the interest of not requiring an explicit shader text entry to
3335 be defined for every single image used in the game, three default
3336 shader behaviors can be auto-created for any image:
3337
3338 If lightmapIndex == LIGHTMAP_NONE, then the image will have
3339 dynamic diffuse lighting applied to it, as apropriate for most
3340 entity skin surfaces.
3341
3342 If lightmapIndex == LIGHTMAP_2D, then the image will be used
3343 for 2D rendering unless an explicit shader is found
3344
3345 If lightmapIndex == LIGHTMAP_BY_VERTEX, then the image will use
3346 the vertex rgba modulate values, as apropriate for misc_model
3347 pre-lit surfaces.
3348
3349 Other lightmapIndex values will have a lightmap stage created
3350 and src*dest blending applied with the texture, as apropriate for
3351 most world construction surfaces.
3352
3353 ===============
3354 */
R_FindShader(const char * name,int lightmapIndex,qboolean mipRawImage)3355 shader_t *R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImage ) {
3356 char strippedName[MAX_QPATH];
3357 int hash;
3358 char *shaderText;
3359 image_t *image;
3360 shader_t *sh;
3361
3362 if ( name[0] == 0 ) {
3363 return tr.defaultShader;
3364 }
3365
3366 // use (fullbright) vertex lighting if the bsp file doesn't have
3367 // lightmaps
3368 if ( lightmapIndex >= 0 && lightmapIndex >= tr.numLightmaps ) {
3369 lightmapIndex = LIGHTMAP_BY_VERTEX;
3370 } else if ( lightmapIndex < LIGHTMAP_2D ) {
3371 // negative lightmap indexes cause stray pointers (think tr.lightmaps[lightmapIndex])
3372 ri.Printf( PRINT_WARNING, "WARNING: shader '%s' has invalid lightmap index of %d\n", name, lightmapIndex );
3373 lightmapIndex = LIGHTMAP_BY_VERTEX;
3374 }
3375
3376 COM_StripExtension( name, strippedName, sizeof( strippedName ) );
3377
3378 hash = generateHashValue( strippedName );
3379
3380 //
3381 // see if the shader is already loaded
3382 //
3383 for ( sh = hashTable[hash]; sh; sh = sh->next ) {
3384 // index by name
3385
3386 // Ridah, modified this so we don't keep trying to load an invalid lightmap shader
3387 /*
3388 if ( sh->lightmapIndex == lightmapIndex &&
3389 !Q_stricmp(sh->name, strippedName)) {
3390 // match found
3391 return sh;
3392 }
3393 */
3394 if ( ( ( sh->lightmapIndex == lightmapIndex ) || ( sh->lightmapIndex < 0 && lightmapIndex >= 0 ) ) &&
3395 !Q_stricmp( sh->name, strippedName ) ) {
3396 // match found
3397 return sh;
3398 }
3399 }
3400
3401 InitShader( strippedName, lightmapIndex );
3402
3403 //
3404 // attempt to define shader from an explicit parameter file
3405 //
3406 shaderText = FindShaderInShaderText( strippedName );
3407 if ( shaderText ) {
3408 // enable this when building a pak file to get a global list
3409 // of all explicit shaders
3410 if ( r_printShaders->integer ) {
3411 ri.Printf( PRINT_ALL, "*SHADER* %s\n", name );
3412 }
3413
3414 if ( !ParseShader( &shaderText ) ) {
3415 // had errors, so use default shader
3416 shader.defaultShader = qtrue;
3417 }
3418 sh = FinishShader();
3419 return sh;
3420 }
3421
3422
3423 //
3424 // if not defined in the in-memory shader descriptions,
3425 // look for a single supported image file
3426 //
3427 {
3428 imgFlags_t flags;
3429
3430 flags = IMGFLAG_NONE;
3431
3432 if (mipRawImage)
3433 {
3434 flags |= IMGFLAG_MIPMAP | IMGFLAG_PICMIP;
3435
3436 if (r_genNormalMaps->integer)
3437 flags |= IMGFLAG_GENNORMALMAP;
3438 }
3439 else
3440 {
3441 flags |= IMGFLAG_CLAMPTOEDGE;
3442 }
3443
3444 image = R_FindImageFile( name, IMGTYPE_COLORALPHA, flags );
3445 if ( !image ) {
3446 ri.Printf( PRINT_DEVELOPER, "Couldn't find image file for shader %s\n", name );
3447 shader.defaultShader = qtrue;
3448 return FinishShader();
3449 }
3450 }
3451
3452 //
3453 // create the default shading commands
3454 //
3455 if ( shader.lightmapIndex == LIGHTMAP_NONE ) {
3456 // dynamic colors at vertexes
3457 stages[0].bundle[0].image[0] = image;
3458 stages[0].active = qtrue;
3459 stages[0].rgbGen = CGEN_LIGHTING_DIFFUSE;
3460 stages[0].stateBits = GLS_DEFAULT;
3461 } else if ( shader.lightmapIndex == LIGHTMAP_BY_VERTEX ) {
3462 // explicit colors at vertexes
3463 stages[0].bundle[0].image[0] = image;
3464 stages[0].active = qtrue;
3465 stages[0].rgbGen = CGEN_EXACT_VERTEX;
3466 stages[0].alphaGen = AGEN_SKIP;
3467 stages[0].stateBits = GLS_DEFAULT;
3468 } else if ( shader.lightmapIndex == LIGHTMAP_2D ) {
3469 // GUI elements
3470 stages[0].bundle[0].image[0] = image;
3471 stages[0].active = qtrue;
3472 stages[0].rgbGen = CGEN_VERTEX;
3473 stages[0].alphaGen = AGEN_VERTEX;
3474 stages[0].stateBits = GLS_DEPTHTEST_DISABLE |
3475 GLS_SRCBLEND_SRC_ALPHA |
3476 GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA;
3477 } else if ( shader.lightmapIndex == LIGHTMAP_WHITEIMAGE ) {
3478 // fullbright level
3479 stages[0].bundle[0].image[0] = tr.whiteImage;
3480 stages[0].active = qtrue;
3481 stages[0].rgbGen = CGEN_IDENTITY_LIGHTING;
3482 stages[0].stateBits = GLS_DEFAULT;
3483
3484 stages[1].bundle[0].image[0] = image;
3485 stages[1].active = qtrue;
3486 stages[1].rgbGen = CGEN_IDENTITY;
3487 stages[1].stateBits |= GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO;
3488 } else {
3489 // two pass lightmap
3490 stages[0].bundle[0].image[0] = tr.lightmaps[shader.lightmapIndex];
3491 stages[0].bundle[0].isLightmap = qtrue;
3492 stages[0].active = qtrue;
3493 stages[0].rgbGen = CGEN_IDENTITY; // lightmaps are scaled on creation
3494 // for identitylight
3495 stages[0].stateBits = GLS_DEFAULT;
3496
3497 stages[1].bundle[0].image[0] = image;
3498 stages[1].active = qtrue;
3499 stages[1].rgbGen = CGEN_IDENTITY;
3500 stages[1].stateBits |= GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO;
3501 }
3502
3503 return FinishShader();
3504 }
3505
3506
RE_RegisterShaderFromImage(const char * name,int lightmapIndex,image_t * image,qboolean mipRawImage)3507 qhandle_t RE_RegisterShaderFromImage( const char *name, int lightmapIndex, image_t *image, qboolean mipRawImage ) {
3508 int hash;
3509 shader_t *sh;
3510
3511 hash = generateHashValue( name );
3512
3513 // probably not necessary since this function
3514 // only gets called from tr_font.c with lightmapIndex == LIGHTMAP_2D
3515 // but better safe than sorry.
3516 if ( lightmapIndex >= tr.numLightmaps ) {
3517 lightmapIndex = LIGHTMAP_WHITEIMAGE;
3518 }
3519
3520 //
3521 // see if the shader is already loaded
3522 //
3523 for ( sh = hashTable[hash]; sh; sh = sh->next ) {
3524 // NOTE: if there was no shader or image available with the name strippedName
3525 // then a default shader is created with lightmapIndex == LIGHTMAP_NONE, so we
3526 // have to check all default shaders otherwise for every call to R_FindShader
3527 // with that same strippedName a new default shader is created.
3528 if ( ( sh->lightmapIndex == lightmapIndex || sh->defaultShader ) &&
3529 // index by name
3530 !Q_stricmp( sh->name, name ) ) {
3531 // match found
3532 return sh->index;
3533 }
3534 }
3535
3536 InitShader( name, lightmapIndex );
3537
3538 //
3539 // create the default shading commands
3540 //
3541 if ( shader.lightmapIndex == LIGHTMAP_NONE ) {
3542 // dynamic colors at vertexes
3543 stages[0].bundle[0].image[0] = image;
3544 stages[0].active = qtrue;
3545 stages[0].rgbGen = CGEN_LIGHTING_DIFFUSE;
3546 stages[0].stateBits = GLS_DEFAULT;
3547 } else if ( shader.lightmapIndex == LIGHTMAP_BY_VERTEX ) {
3548 // explicit colors at vertexes
3549 stages[0].bundle[0].image[0] = image;
3550 stages[0].active = qtrue;
3551 stages[0].rgbGen = CGEN_EXACT_VERTEX;
3552 stages[0].alphaGen = AGEN_SKIP;
3553 stages[0].stateBits = GLS_DEFAULT;
3554 } else if ( shader.lightmapIndex == LIGHTMAP_2D ) {
3555 // GUI elements
3556 stages[0].bundle[0].image[0] = image;
3557 stages[0].active = qtrue;
3558 stages[0].rgbGen = CGEN_VERTEX;
3559 stages[0].alphaGen = AGEN_VERTEX;
3560 stages[0].stateBits = GLS_DEPTHTEST_DISABLE |
3561 GLS_SRCBLEND_SRC_ALPHA |
3562 GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA;
3563 } else if ( shader.lightmapIndex == LIGHTMAP_WHITEIMAGE ) {
3564 // fullbright level
3565 stages[0].bundle[0].image[0] = tr.whiteImage;
3566 stages[0].active = qtrue;
3567 stages[0].rgbGen = CGEN_IDENTITY_LIGHTING;
3568 stages[0].stateBits = GLS_DEFAULT;
3569
3570 stages[1].bundle[0].image[0] = image;
3571 stages[1].active = qtrue;
3572 stages[1].rgbGen = CGEN_IDENTITY;
3573 stages[1].stateBits |= GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO;
3574 } else {
3575 // two pass lightmap
3576 stages[0].bundle[0].image[0] = tr.lightmaps[shader.lightmapIndex];
3577 stages[0].bundle[0].isLightmap = qtrue;
3578 stages[0].active = qtrue;
3579 stages[0].rgbGen = CGEN_IDENTITY; // lightmaps are scaled on creation
3580 // for identitylight
3581 stages[0].stateBits = GLS_DEFAULT;
3582
3583 stages[1].bundle[0].image[0] = image;
3584 stages[1].active = qtrue;
3585 stages[1].rgbGen = CGEN_IDENTITY;
3586 stages[1].stateBits |= GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO;
3587 }
3588
3589 sh = FinishShader();
3590 return sh->index;
3591 }
3592
3593
3594 /*
3595 ====================
3596 RE_RegisterShaderLightMap
3597
3598 This is the exported shader entry point for the rest of the system
3599 It will always return an index that will be valid.
3600
3601 This should really only be used for explicit shaders, because there is no
3602 way to ask for different implicit lighting modes (vertex, lightmap, etc)
3603 ====================
3604 */
RE_RegisterShaderLightMap(const char * name,int lightmapIndex)3605 qhandle_t RE_RegisterShaderLightMap( const char *name, int lightmapIndex ) {
3606 shader_t *sh;
3607
3608 if ( strlen( name ) >= MAX_QPATH ) {
3609 ri.Printf( PRINT_ALL, "Shader name exceeds MAX_QPATH\n" );
3610 return 0;
3611 }
3612
3613 sh = R_FindShader( name, lightmapIndex, qtrue );
3614
3615 // we want to return 0 if the shader failed to
3616 // load for some reason, but R_FindShader should
3617 // still keep a name allocated for it, so if
3618 // something calls RE_RegisterShader again with
3619 // the same name, we don't try looking for it again
3620 if ( sh->defaultShader ) {
3621 return 0;
3622 }
3623
3624 return sh->index;
3625 }
3626
3627
3628 /*
3629 ====================
3630 RE_RegisterShader
3631
3632 This is the exported shader entry point for the rest of the system
3633 It will always return an index that will be valid.
3634
3635 This should really only be used for explicit shaders, because there is no
3636 way to ask for different implicit lighting modes (vertex, lightmap, etc)
3637 ====================
3638 */
RE_RegisterShader(const char * name)3639 qhandle_t RE_RegisterShader( const char *name ) {
3640 shader_t *sh;
3641
3642 if ( strlen( name ) >= MAX_QPATH ) {
3643 ri.Printf( PRINT_ALL, "Shader name exceeds MAX_QPATH\n" );
3644 return 0;
3645 }
3646
3647 sh = R_FindShader( name, LIGHTMAP_2D, qtrue );
3648
3649 // we want to return 0 if the shader failed to
3650 // load for some reason, but R_FindShader should
3651 // still keep a name allocated for it, so if
3652 // something calls RE_RegisterShader again with
3653 // the same name, we don't try looking for it again
3654 if ( sh->defaultShader ) {
3655 return 0;
3656 }
3657
3658 return sh->index;
3659 }
3660
3661
3662 /*
3663 ====================
3664 RE_RegisterShaderNoMip
3665
3666 For menu graphics that should never be picmiped
3667 ====================
3668 */
RE_RegisterShaderNoMip(const char * name)3669 qhandle_t RE_RegisterShaderNoMip( const char *name ) {
3670 shader_t *sh;
3671
3672 if ( strlen( name ) >= MAX_QPATH ) {
3673 ri.Printf( PRINT_ALL, "Shader name exceeds MAX_QPATH\n" );
3674 return 0;
3675 }
3676
3677 sh = R_FindShader( name, LIGHTMAP_2D, qfalse );
3678
3679 // we want to return 0 if the shader failed to
3680 // load for some reason, but R_FindShader should
3681 // still keep a name allocated for it, so if
3682 // something calls RE_RegisterShader again with
3683 // the same name, we don't try looking for it again
3684 if ( sh->defaultShader ) {
3685 return 0;
3686 }
3687
3688 return sh->index;
3689 }
3690
3691
3692 /*
3693 ====================
3694 R_GetShaderByHandle
3695
3696 When a handle is passed in by another module, this range checks
3697 it and returns a valid (possibly default) shader_t to be used internally.
3698 ====================
3699 */
R_GetShaderByHandle(qhandle_t hShader)3700 shader_t *R_GetShaderByHandle( qhandle_t hShader ) {
3701 if ( hShader < 0 ) {
3702 ri.Printf( PRINT_WARNING, "R_GetShaderByHandle: out of range hShader '%d'\n", hShader );
3703 return tr.defaultShader;
3704 }
3705 if ( hShader >= tr.numShaders ) {
3706 ri.Printf( PRINT_WARNING, "R_GetShaderByHandle: out of range hShader '%d'\n", hShader );
3707 return tr.defaultShader;
3708 }
3709 return tr.shaders[hShader];
3710 }
3711
3712 /*
3713 ===============
3714 R_ShaderList_f
3715
3716 Dump information on all valid shaders to the console
3717 A second parameter will cause it to print in sorted order
3718 ===============
3719 */
R_ShaderList_f(void)3720 void R_ShaderList_f( void ) {
3721 int i;
3722 int count;
3723 shader_t *shader;
3724
3725 ri.Printf( PRINT_ALL, "-----------------------\n" );
3726
3727 count = 0;
3728 for ( i = 0 ; i < tr.numShaders ; i++ ) {
3729 if ( ri.Cmd_Argc() > 1 ) {
3730 shader = tr.sortedShaders[i];
3731 } else {
3732 shader = tr.shaders[i];
3733 }
3734
3735 ri.Printf( PRINT_ALL, "%i ", shader->numUnfoggedPasses );
3736
3737 if ( shader->lightmapIndex >= 0 ) {
3738 ri.Printf( PRINT_ALL, "L " );
3739 } else {
3740 ri.Printf( PRINT_ALL, " " );
3741 }
3742 if ( shader->explicitlyDefined ) {
3743 ri.Printf( PRINT_ALL, "E " );
3744 } else {
3745 ri.Printf( PRINT_ALL, " " );
3746 }
3747
3748 if ( shader->optimalStageIteratorFunc == RB_StageIteratorGeneric ) {
3749 ri.Printf( PRINT_ALL, "gen " );
3750 } else if ( shader->optimalStageIteratorFunc == RB_StageIteratorSky ) {
3751 ri.Printf( PRINT_ALL, "sky " );
3752 } else {
3753 ri.Printf( PRINT_ALL, " " );
3754 }
3755
3756 if ( shader->defaultShader ) {
3757 ri.Printf( PRINT_ALL, ": %s (DEFAULTED)\n", shader->name );
3758 } else {
3759 ri.Printf( PRINT_ALL, ": %s\n", shader->name );
3760 }
3761 count++;
3762 }
3763 ri.Printf( PRINT_ALL, "%i total shaders\n", count );
3764 ri.Printf( PRINT_ALL, "------------------\n" );
3765 }
3766
3767 // Ridah, optimized shader loading
3768
3769 #define MAX_SHADER_STRING_POINTERS 100000
3770 shaderStringPointer_t shaderStringPointerList[MAX_SHADER_STRING_POINTERS];
3771
3772 /*
3773 ====================
3774 BuildShaderChecksumLookup
3775 ====================
3776 */
BuildShaderChecksumLookup(void)3777 static void BuildShaderChecksumLookup( void ) {
3778 char *p = s_shaderText, *pOld;
3779 char *token;
3780 unsigned short int checksum;
3781 int numShaderStringPointers = 0;
3782
3783 // initialize the checksums
3784 memset( shaderChecksumLookup, 0, sizeof( shaderChecksumLookup ) );
3785
3786 if ( !p ) {
3787 return;
3788 }
3789
3790 // loop for all labels
3791 while ( 1 ) {
3792
3793 pOld = p;
3794
3795 token = COM_ParseExt( &p, qtrue );
3796 if ( token[0] == 0 ) {
3797 break;
3798 }
3799
3800 if ( !Q_stricmp( token, "{" ) ) {
3801 // skip braced section
3802 SkipBracedSection( &p, 0 );
3803 continue;
3804 }
3805
3806 // get it's checksum
3807 checksum = generateHashValue( token );
3808
3809 // if it's not currently used
3810 if ( !shaderChecksumLookup[checksum].pStr ) {
3811 shaderChecksumLookup[checksum].pStr = pOld;
3812 } else {
3813 // create a new list item
3814 shaderStringPointer_t *newStrPtr;
3815
3816 if ( numShaderStringPointers >= MAX_SHADER_STRING_POINTERS ) {
3817 ri.Error( ERR_DROP, "MAX_SHADER_STRING_POINTERS exceeded, too many shaders" );
3818 }
3819
3820 newStrPtr = &shaderStringPointerList[numShaderStringPointers++]; //ri.Hunk_Alloc( sizeof( shaderStringPointer_t ), h_low );
3821 newStrPtr->pStr = pOld;
3822 newStrPtr->next = shaderChecksumLookup[checksum].next;
3823 shaderChecksumLookup[checksum].next = newStrPtr;
3824 }
3825 }
3826 }
3827 // done.
3828
3829
3830 /*
3831 ====================
3832 ScanAndLoadShaderFiles
3833
3834 Finds and loads all .shader files, combining them into
3835 a single large text block that can be scanned for shader names
3836 =====================
3837 */
3838 #define MAX_SHADER_FILES 4096
ScanAndLoadShaderFiles(void)3839 static void ScanAndLoadShaderFiles( void ) {
3840 char **shaderFiles;
3841 char *buffers[MAX_SHADER_FILES] = {NULL};
3842 char *p;
3843 int numShaderFiles;
3844 int i;
3845 char *token, *textEnd;
3846 char shaderName[MAX_QPATH];
3847 int shaderLine;
3848
3849 long sum = 0, summand;
3850 // scan for shader files
3851 shaderFiles = ri.FS_ListFiles( "scripts", ".shader", &numShaderFiles );
3852
3853 if ( !shaderFiles || !numShaderFiles ) {
3854 ri.Printf( PRINT_WARNING, "WARNING: no shader files found\n" );
3855 return;
3856 }
3857
3858 if ( numShaderFiles > MAX_SHADER_FILES ) {
3859 numShaderFiles = MAX_SHADER_FILES;
3860 }
3861
3862 // load and parse shader files
3863 for ( i = 0; i < numShaderFiles; i++ )
3864 {
3865 char filename[MAX_QPATH];
3866
3867 // look for a .mtr file first
3868 {
3869 char *ext;
3870 Com_sprintf( filename, sizeof( filename ), "scripts/%s", shaderFiles[i] );
3871 if ( (ext = strrchr(filename, '.')) )
3872 {
3873 strcpy(ext, ".mtr");
3874 }
3875
3876 if ( ri.FS_ReadFile( filename, NULL ) <= 0 )
3877 {
3878 Com_sprintf( filename, sizeof( filename ), "scripts/%s", shaderFiles[i] );
3879 }
3880 }
3881 ri.Printf( PRINT_DEVELOPER, "...loading '%s'\n", filename );
3882 summand = ri.FS_ReadFile( filename, (void **)&buffers[i] );
3883
3884 if ( !buffers[i] )
3885 ri.Error( ERR_DROP, "Couldn't load %s", filename );
3886
3887 // Do a simple check on the shader structure in that file to make sure one bad shader file cannot fuck up all other shaders.
3888 p = buffers[i];
3889 COM_BeginParseSession(filename);
3890 while(1)
3891 {
3892 token = COM_ParseExt(&p, qtrue);
3893
3894 if(!*token)
3895 break;
3896
3897 Q_strncpyz(shaderName, token, sizeof(shaderName));
3898 shaderLine = COM_GetCurrentParseLine();
3899
3900 token = COM_ParseExt(&p, qtrue);
3901 if( !Q_stricmp( shaderName, token ) ) {
3902 ri.Printf(PRINT_WARNING, "WARNING: In shader file %s...Invalid shader name \"%s\" on line %d.\n",
3903 filename, shaderName, shaderLine);
3904 break;
3905 }
3906
3907 if(token[0] != '{' || token[1] != '\0')
3908 {
3909 ri.Printf(PRINT_WARNING, "WARNING: In shader file %s...Shader \"%s\" on line %d is missing opening brace",
3910 filename, shaderName, shaderLine);
3911 if (token[0])
3912 {
3913 ri.Printf(PRINT_WARNING, " (found \"%s\" on line %d)", token, COM_GetCurrentParseLine());
3914 }
3915 ri.Printf(PRINT_WARNING, "...Ignored\n");
3916 ri.FS_FreeFile(buffers[i]);
3917 buffers[i] = NULL;
3918 break;
3919 }
3920
3921 if(!SkipBracedSection(&p, 1))
3922 {
3923 ri.Printf(PRINT_WARNING, "WARNING: In shader file %s...Shader \"%s\" on line %d is missing closing brace",
3924 filename, shaderName, shaderLine);
3925 if( !Q_stricmp( filename, "common.shader" ) ) { // HACK...Broken shader in pak0.pk3
3926 ri.Printf(PRINT_WARNING, "...Ignored\n");
3927 ri.FS_FreeFile(buffers[i]);
3928 buffers[i] = NULL;
3929 break;
3930 } else {
3931 ri.Printf(PRINT_WARNING, ".\n");
3932 }
3933 }
3934 }
3935
3936 if (buffers[i])
3937 sum += summand;
3938 }
3939
3940 // build single large buffer
3941 s_shaderText = ri.Hunk_Alloc( sum + numShaderFiles*2, h_low );
3942 s_shaderText[ 0 ] = '\0';
3943 textEnd = s_shaderText;
3944
3945 // free in reverse order, so the temp files are all dumped
3946 for ( i = numShaderFiles - 1; i >= 0 ; i-- )
3947 {
3948 if ( !buffers[i] )
3949 continue;
3950
3951 strcat( textEnd, buffers[i] );
3952 strcat( textEnd, "\n" );
3953 textEnd += strlen( textEnd );
3954 ri.FS_FreeFile( buffers[i] );
3955 }
3956
3957 COM_Compress( s_shaderText );
3958
3959 // free up memory
3960 ri.FS_FreeFileList( shaderFiles );
3961
3962 // Ridah, optimized shader loading (18ms on a P3-500 for sfm1.bsp)
3963 BuildShaderChecksumLookup();
3964 // done.
3965 }
3966
3967
3968 /*
3969 ====================
3970 CreateInternalShaders
3971 ====================
3972 */
CreateInternalShaders(void)3973 static void CreateInternalShaders( void ) {
3974 tr.numShaders = 0;
3975
3976 // init the default shader
3977 InitShader( "<default>", LIGHTMAP_NONE );
3978 stages[0].bundle[0].image[0] = tr.defaultImage;
3979 stages[0].active = qtrue;
3980 stages[0].stateBits = GLS_DEFAULT;
3981 tr.defaultShader = FinishShader();
3982
3983 // shadow shader is just a marker
3984 Q_strncpyz( shader.name, "<stencil shadow>", sizeof( shader.name ) );
3985 shader.sort = SS_STENCIL_SHADOW;
3986 tr.shadowShader = FinishShader();
3987 }
3988
CreateExternalShaders(void)3989 static void CreateExternalShaders( void ) {
3990 // tr.projectionShadowShader = R_FindShader( "projectionShadow", LIGHTMAP_NONE, qtrue );
3991 tr.flareShader = R_FindShader( "flareShader", LIGHTMAP_NONE, qtrue );
3992
3993 // Hack to make fogging work correctly on flares. Fog colors are calculated
3994 // in tr_flare.c already.
3995 if(!tr.flareShader->defaultShader)
3996 {
3997 int index;
3998
3999 for(index = 0; index < tr.flareShader->numUnfoggedPasses; index++)
4000 {
4001 tr.flareShader->stages[index]->adjustColorsForFog = ACFF_NONE;
4002 tr.flareShader->stages[index]->stateBits |= GLS_DEPTHTEST_DISABLE;
4003 }
4004 }
4005
4006 tr.spotFlareShader = R_FindShader( "spotLight", LIGHTMAP_NONE, qtrue );
4007 // tr.sunShader = R_FindShader( "sun", LIGHTMAP_NONE, qtrue ); //----(SA) let sky shader set this
4008 tr.sunflareShader_old[0] = R_FindShader( "sunflare1", LIGHTMAP_NONE, qtrue );
4009 // tr.dlightShader = R_FindShader( "dlightshader", LIGHTMAP_NONE, qtrue );
4010
4011 tr.sunFlareShader = R_FindShader( "sunflare1", LIGHTMAP_NONE, qtrue);
4012
4013 // HACK: if sunflare is missing, make one using the flare image or dlight image
4014 if (tr.sunFlareShader->defaultShader)
4015 {
4016 image_t *image;
4017
4018 if (!tr.flareShader->defaultShader && tr.flareShader->stages[0] && tr.flareShader->stages[0]->bundle[0].image[0])
4019 image = tr.flareShader->stages[0]->bundle[0].image[0];
4020 else
4021 image = tr.dlightImage;
4022
4023
4024 InitShader( "sunflare1", LIGHTMAP_NONE );
4025 stages[0].bundle[0].image[0] = image;
4026 stages[0].active = qtrue;
4027 stages[0].stateBits = GLS_DEFAULT;
4028 tr.sunFlareShader = FinishShader();
4029 }
4030 }
4031
4032 /*
4033 ==================
4034 R_InitShaders
4035 ==================
4036 */
R_InitShaders(void)4037 void R_InitShaders( void ) {
4038
4039 glfogNum = FOG_NONE;
4040 ri.Cvar_Set( "r_waterFogColor", "0" ); // clear fog
4041 ri.Cvar_Set( "r_mapFogColor", "0" ); //
4042 ri.Cvar_Set( "r_savegameFogColor", "0" );
4043
4044 ri.Printf( PRINT_ALL, "Initializing Shaders\n" );
4045
4046 memset( hashTable, 0, sizeof( hashTable ) );
4047
4048 CreateInternalShaders();
4049
4050 ScanAndLoadShaderFiles();
4051
4052 CreateExternalShaders();
4053 }
4054