tr_shader.c 76 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1999-2005 Id Software, Inc.
  4. This file is part of Quake III Arena source code.
  5. Quake III Arena source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake III Arena source code is distributed in the hope that it will be
  10. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Foobar; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. #include "tr_local.h"
  19. // tr_shader.c -- this file deals with the parsing and definition of shaders
  20. static char *s_shaderText;
  21. // the shader is parsed into these global variables, then copied into
  22. // dynamically allocated memory if it is valid.
  23. static shaderStage_t stages[MAX_SHADER_STAGES];
  24. static shader_t shader;
  25. static texModInfo_t texMods[MAX_SHADER_STAGES][TR_MAX_TEXMODS];
  26. static qboolean deferLoad;
  27. #define FILE_HASH_SIZE 1024
  28. static shader_t* hashTable[FILE_HASH_SIZE];
  29. #define MAX_SHADERTEXT_HASH 2048
  30. static char **shaderTextHashTable[MAX_SHADERTEXT_HASH];
  31. /*
  32. ================
  33. return a hash value for the filename
  34. ================
  35. */
  36. static long generateHashValue( const char *fname, const int size ) {
  37. int i;
  38. long hash;
  39. char letter;
  40. hash = 0;
  41. i = 0;
  42. while (fname[i] != '\0') {
  43. letter = tolower(fname[i]);
  44. if (letter =='.') break; // don't include extension
  45. if (letter =='\\') letter = '/'; // damn path names
  46. if (letter == PATH_SEP) letter = '/'; // damn path names
  47. hash+=(long)(letter)*(i+119);
  48. i++;
  49. }
  50. hash = (hash ^ (hash >> 10) ^ (hash >> 20));
  51. hash &= (size-1);
  52. return hash;
  53. }
  54. void R_RemapShader(const char *shaderName, const char *newShaderName, const char *timeOffset) {
  55. char strippedName[MAX_QPATH];
  56. int hash;
  57. shader_t *sh, *sh2;
  58. qhandle_t h;
  59. sh = R_FindShaderByName( shaderName );
  60. if (sh == NULL || sh == tr.defaultShader) {
  61. h = RE_RegisterShaderLightMap(shaderName, 0);
  62. sh = R_GetShaderByHandle(h);
  63. }
  64. if (sh == NULL || sh == tr.defaultShader) {
  65. ri.Printf( PRINT_WARNING, "WARNING: R_RemapShader: shader %s not found\n", shaderName );
  66. return;
  67. }
  68. sh2 = R_FindShaderByName( newShaderName );
  69. if (sh2 == NULL || sh2 == tr.defaultShader) {
  70. h = RE_RegisterShaderLightMap(newShaderName, 0);
  71. sh2 = R_GetShaderByHandle(h);
  72. }
  73. if (sh2 == NULL || sh2 == tr.defaultShader) {
  74. ri.Printf( PRINT_WARNING, "WARNING: R_RemapShader: new shader %s not found\n", newShaderName );
  75. return;
  76. }
  77. // remap all the shaders with the given name
  78. // even tho they might have different lightmaps
  79. COM_StripExtension( shaderName, strippedName );
  80. hash = generateHashValue(strippedName, FILE_HASH_SIZE);
  81. for (sh = hashTable[hash]; sh; sh = sh->next) {
  82. if (Q_stricmp(sh->name, strippedName) == 0) {
  83. if (sh != sh2) {
  84. sh->remappedShader = sh2;
  85. } else {
  86. sh->remappedShader = NULL;
  87. }
  88. }
  89. }
  90. if (timeOffset) {
  91. sh2->timeOffset = atof(timeOffset);
  92. }
  93. }
  94. /*
  95. ===============
  96. ParseVector
  97. ===============
  98. */
  99. static qboolean ParseVector( char **text, int count, float *v ) {
  100. char *token;
  101. int i;
  102. // FIXME: spaces are currently required after parens, should change parseext...
  103. token = COM_ParseExt( text, qfalse );
  104. if ( strcmp( token, "(" ) ) {
  105. ri.Printf( PRINT_WARNING, "WARNING: missing parenthesis in shader '%s'\n", shader.name );
  106. return qfalse;
  107. }
  108. for ( i = 0 ; i < count ; i++ ) {
  109. token = COM_ParseExt( text, qfalse );
  110. if ( !token[0] ) {
  111. ri.Printf( PRINT_WARNING, "WARNING: missing vector element in shader '%s'\n", shader.name );
  112. return qfalse;
  113. }
  114. v[i] = atof( token );
  115. }
  116. token = COM_ParseExt( text, qfalse );
  117. if ( strcmp( token, ")" ) ) {
  118. ri.Printf( PRINT_WARNING, "WARNING: missing parenthesis in shader '%s'\n", shader.name );
  119. return qfalse;
  120. }
  121. return qtrue;
  122. }
  123. /*
  124. ===============
  125. NameToAFunc
  126. ===============
  127. */
  128. static unsigned NameToAFunc( const char *funcname )
  129. {
  130. if ( !Q_stricmp( funcname, "GT0" ) )
  131. {
  132. return GLS_ATEST_GT_0;
  133. }
  134. else if ( !Q_stricmp( funcname, "LT128" ) )
  135. {
  136. return GLS_ATEST_LT_80;
  137. }
  138. else if ( !Q_stricmp( funcname, "GE128" ) )
  139. {
  140. return GLS_ATEST_GE_80;
  141. }
  142. ri.Printf( PRINT_WARNING, "WARNING: invalid alphaFunc name '%s' in shader '%s'\n", funcname, shader.name );
  143. return 0;
  144. }
  145. /*
  146. ===============
  147. NameToSrcBlendMode
  148. ===============
  149. */
  150. static int NameToSrcBlendMode( const char *name )
  151. {
  152. if ( !Q_stricmp( name, "GL_ONE" ) )
  153. {
  154. return GLS_SRCBLEND_ONE;
  155. }
  156. else if ( !Q_stricmp( name, "GL_ZERO" ) )
  157. {
  158. return GLS_SRCBLEND_ZERO;
  159. }
  160. else if ( !Q_stricmp( name, "GL_DST_COLOR" ) )
  161. {
  162. return GLS_SRCBLEND_DST_COLOR;
  163. }
  164. else if ( !Q_stricmp( name, "GL_ONE_MINUS_DST_COLOR" ) )
  165. {
  166. return GLS_SRCBLEND_ONE_MINUS_DST_COLOR;
  167. }
  168. else if ( !Q_stricmp( name, "GL_SRC_ALPHA" ) )
  169. {
  170. return GLS_SRCBLEND_SRC_ALPHA;
  171. }
  172. else if ( !Q_stricmp( name, "GL_ONE_MINUS_SRC_ALPHA" ) )
  173. {
  174. return GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA;
  175. }
  176. else if ( !Q_stricmp( name, "GL_DST_ALPHA" ) )
  177. {
  178. return GLS_SRCBLEND_DST_ALPHA;
  179. }
  180. else if ( !Q_stricmp( name, "GL_ONE_MINUS_DST_ALPHA" ) )
  181. {
  182. return GLS_SRCBLEND_ONE_MINUS_DST_ALPHA;
  183. }
  184. else if ( !Q_stricmp( name, "GL_SRC_ALPHA_SATURATE" ) )
  185. {
  186. return GLS_SRCBLEND_ALPHA_SATURATE;
  187. }
  188. ri.Printf( PRINT_WARNING, "WARNING: unknown blend mode '%s' in shader '%s', substituting GL_ONE\n", name, shader.name );
  189. return GLS_SRCBLEND_ONE;
  190. }
  191. /*
  192. ===============
  193. NameToDstBlendMode
  194. ===============
  195. */
  196. static int NameToDstBlendMode( const char *name )
  197. {
  198. if ( !Q_stricmp( name, "GL_ONE" ) )
  199. {
  200. return GLS_DSTBLEND_ONE;
  201. }
  202. else if ( !Q_stricmp( name, "GL_ZERO" ) )
  203. {
  204. return GLS_DSTBLEND_ZERO;
  205. }
  206. else if ( !Q_stricmp( name, "GL_SRC_ALPHA" ) )
  207. {
  208. return GLS_DSTBLEND_SRC_ALPHA;
  209. }
  210. else if ( !Q_stricmp( name, "GL_ONE_MINUS_SRC_ALPHA" ) )
  211. {
  212. return GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA;
  213. }
  214. else if ( !Q_stricmp( name, "GL_DST_ALPHA" ) )
  215. {
  216. return GLS_DSTBLEND_DST_ALPHA;
  217. }
  218. else if ( !Q_stricmp( name, "GL_ONE_MINUS_DST_ALPHA" ) )
  219. {
  220. return GLS_DSTBLEND_ONE_MINUS_DST_ALPHA;
  221. }
  222. else if ( !Q_stricmp( name, "GL_SRC_COLOR" ) )
  223. {
  224. return GLS_DSTBLEND_SRC_COLOR;
  225. }
  226. else if ( !Q_stricmp( name, "GL_ONE_MINUS_SRC_COLOR" ) )
  227. {
  228. return GLS_DSTBLEND_ONE_MINUS_SRC_COLOR;
  229. }
  230. ri.Printf( PRINT_WARNING, "WARNING: unknown blend mode '%s' in shader '%s', substituting GL_ONE\n", name, shader.name );
  231. return GLS_DSTBLEND_ONE;
  232. }
  233. /*
  234. ===============
  235. NameToGenFunc
  236. ===============
  237. */
  238. static genFunc_t NameToGenFunc( const char *funcname )
  239. {
  240. if ( !Q_stricmp( funcname, "sin" ) )
  241. {
  242. return GF_SIN;
  243. }
  244. else if ( !Q_stricmp( funcname, "square" ) )
  245. {
  246. return GF_SQUARE;
  247. }
  248. else if ( !Q_stricmp( funcname, "triangle" ) )
  249. {
  250. return GF_TRIANGLE;
  251. }
  252. else if ( !Q_stricmp( funcname, "sawtooth" ) )
  253. {
  254. return GF_SAWTOOTH;
  255. }
  256. else if ( !Q_stricmp( funcname, "inversesawtooth" ) )
  257. {
  258. return GF_INVERSE_SAWTOOTH;
  259. }
  260. else if ( !Q_stricmp( funcname, "noise" ) )
  261. {
  262. return GF_NOISE;
  263. }
  264. ri.Printf( PRINT_WARNING, "WARNING: invalid genfunc name '%s' in shader '%s'\n", funcname, shader.name );
  265. return GF_SIN;
  266. }
  267. /*
  268. ===================
  269. ParseWaveForm
  270. ===================
  271. */
  272. static void ParseWaveForm( char **text, waveForm_t *wave )
  273. {
  274. char *token;
  275. token = COM_ParseExt( text, qfalse );
  276. if ( token[0] == 0 )
  277. {
  278. ri.Printf( PRINT_WARNING, "WARNING: missing waveform parm in shader '%s'\n", shader.name );
  279. return;
  280. }
  281. wave->func = NameToGenFunc( token );
  282. // BASE, AMP, PHASE, FREQ
  283. token = COM_ParseExt( text, qfalse );
  284. if ( token[0] == 0 )
  285. {
  286. ri.Printf( PRINT_WARNING, "WARNING: missing waveform parm in shader '%s'\n", shader.name );
  287. return;
  288. }
  289. wave->base = atof( token );
  290. token = COM_ParseExt( text, qfalse );
  291. if ( token[0] == 0 )
  292. {
  293. ri.Printf( PRINT_WARNING, "WARNING: missing waveform parm in shader '%s'\n", shader.name );
  294. return;
  295. }
  296. wave->amplitude = atof( token );
  297. token = COM_ParseExt( text, qfalse );
  298. if ( token[0] == 0 )
  299. {
  300. ri.Printf( PRINT_WARNING, "WARNING: missing waveform parm in shader '%s'\n", shader.name );
  301. return;
  302. }
  303. wave->phase = atof( token );
  304. token = COM_ParseExt( text, qfalse );
  305. if ( token[0] == 0 )
  306. {
  307. ri.Printf( PRINT_WARNING, "WARNING: missing waveform parm in shader '%s'\n", shader.name );
  308. return;
  309. }
  310. wave->frequency = atof( token );
  311. }
  312. /*
  313. ===================
  314. ParseTexMod
  315. ===================
  316. */
  317. static void ParseTexMod( char *_text, shaderStage_t *stage )
  318. {
  319. const char *token;
  320. char **text = &_text;
  321. texModInfo_t *tmi;
  322. if ( stage->bundle[0].numTexMods == TR_MAX_TEXMODS ) {
  323. ri.Error( ERR_DROP, "ERROR: too many tcMod stages in shader '%s'\n", shader.name );
  324. return;
  325. }
  326. tmi = &stage->bundle[0].texMods[stage->bundle[0].numTexMods];
  327. stage->bundle[0].numTexMods++;
  328. token = COM_ParseExt( text, qfalse );
  329. //
  330. // turb
  331. //
  332. if ( !Q_stricmp( token, "turb" ) )
  333. {
  334. token = COM_ParseExt( text, qfalse );
  335. if ( token[0] == 0 )
  336. {
  337. ri.Printf( PRINT_WARNING, "WARNING: missing tcMod turb parms in shader '%s'\n", shader.name );
  338. return;
  339. }
  340. tmi->wave.base = atof( token );
  341. token = COM_ParseExt( text, qfalse );
  342. if ( token[0] == 0 )
  343. {
  344. ri.Printf( PRINT_WARNING, "WARNING: missing tcMod turb in shader '%s'\n", shader.name );
  345. return;
  346. }
  347. tmi->wave.amplitude = atof( token );
  348. token = COM_ParseExt( text, qfalse );
  349. if ( token[0] == 0 )
  350. {
  351. ri.Printf( PRINT_WARNING, "WARNING: missing tcMod turb in shader '%s'\n", shader.name );
  352. return;
  353. }
  354. tmi->wave.phase = atof( token );
  355. token = COM_ParseExt( text, qfalse );
  356. if ( token[0] == 0 )
  357. {
  358. ri.Printf( PRINT_WARNING, "WARNING: missing tcMod turb in shader '%s'\n", shader.name );
  359. return;
  360. }
  361. tmi->wave.frequency = atof( token );
  362. tmi->type = TMOD_TURBULENT;
  363. }
  364. //
  365. // scale
  366. //
  367. else if ( !Q_stricmp( token, "scale" ) )
  368. {
  369. token = COM_ParseExt( text, qfalse );
  370. if ( token[0] == 0 )
  371. {
  372. ri.Printf( PRINT_WARNING, "WARNING: missing scale parms in shader '%s'\n", shader.name );
  373. return;
  374. }
  375. tmi->scale[0] = atof( token );
  376. token = COM_ParseExt( text, qfalse );
  377. if ( token[0] == 0 )
  378. {
  379. ri.Printf( PRINT_WARNING, "WARNING: missing scale parms in shader '%s'\n", shader.name );
  380. return;
  381. }
  382. tmi->scale[1] = atof( token );
  383. tmi->type = TMOD_SCALE;
  384. }
  385. //
  386. // scroll
  387. //
  388. else if ( !Q_stricmp( token, "scroll" ) )
  389. {
  390. token = COM_ParseExt( text, qfalse );
  391. if ( token[0] == 0 )
  392. {
  393. ri.Printf( PRINT_WARNING, "WARNING: missing scale scroll parms in shader '%s'\n", shader.name );
  394. return;
  395. }
  396. tmi->scroll[0] = atof( token );
  397. token = COM_ParseExt( text, qfalse );
  398. if ( token[0] == 0 )
  399. {
  400. ri.Printf( PRINT_WARNING, "WARNING: missing scale scroll parms in shader '%s'\n", shader.name );
  401. return;
  402. }
  403. tmi->scroll[1] = atof( token );
  404. tmi->type = TMOD_SCROLL;
  405. }
  406. //
  407. // stretch
  408. //
  409. else if ( !Q_stricmp( token, "stretch" ) )
  410. {
  411. token = COM_ParseExt( text, qfalse );
  412. if ( token[0] == 0 )
  413. {
  414. ri.Printf( PRINT_WARNING, "WARNING: missing stretch parms in shader '%s'\n", shader.name );
  415. return;
  416. }
  417. tmi->wave.func = NameToGenFunc( token );
  418. token = COM_ParseExt( text, qfalse );
  419. if ( token[0] == 0 )
  420. {
  421. ri.Printf( PRINT_WARNING, "WARNING: missing stretch parms in shader '%s'\n", shader.name );
  422. return;
  423. }
  424. tmi->wave.base = atof( token );
  425. token = COM_ParseExt( text, qfalse );
  426. if ( token[0] == 0 )
  427. {
  428. ri.Printf( PRINT_WARNING, "WARNING: missing stretch parms in shader '%s'\n", shader.name );
  429. return;
  430. }
  431. tmi->wave.amplitude = atof( token );
  432. token = COM_ParseExt( text, qfalse );
  433. if ( token[0] == 0 )
  434. {
  435. ri.Printf( PRINT_WARNING, "WARNING: missing stretch parms in shader '%s'\n", shader.name );
  436. return;
  437. }
  438. tmi->wave.phase = atof( token );
  439. token = COM_ParseExt( text, qfalse );
  440. if ( token[0] == 0 )
  441. {
  442. ri.Printf( PRINT_WARNING, "WARNING: missing stretch parms in shader '%s'\n", shader.name );
  443. return;
  444. }
  445. tmi->wave.frequency = atof( token );
  446. tmi->type = TMOD_STRETCH;
  447. }
  448. //
  449. // transform
  450. //
  451. else if ( !Q_stricmp( token, "transform" ) )
  452. {
  453. token = COM_ParseExt( text, qfalse );
  454. if ( token[0] == 0 )
  455. {
  456. ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name );
  457. return;
  458. }
  459. tmi->matrix[0][0] = atof( token );
  460. token = COM_ParseExt( text, qfalse );
  461. if ( token[0] == 0 )
  462. {
  463. ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name );
  464. return;
  465. }
  466. tmi->matrix[0][1] = atof( token );
  467. token = COM_ParseExt( text, qfalse );
  468. if ( token[0] == 0 )
  469. {
  470. ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name );
  471. return;
  472. }
  473. tmi->matrix[1][0] = atof( token );
  474. token = COM_ParseExt( text, qfalse );
  475. if ( token[0] == 0 )
  476. {
  477. ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name );
  478. return;
  479. }
  480. tmi->matrix[1][1] = atof( token );
  481. token = COM_ParseExt( text, qfalse );
  482. if ( token[0] == 0 )
  483. {
  484. ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name );
  485. return;
  486. }
  487. tmi->translate[0] = atof( token );
  488. token = COM_ParseExt( text, qfalse );
  489. if ( token[0] == 0 )
  490. {
  491. ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name );
  492. return;
  493. }
  494. tmi->translate[1] = atof( token );
  495. tmi->type = TMOD_TRANSFORM;
  496. }
  497. //
  498. // rotate
  499. //
  500. else if ( !Q_stricmp( token, "rotate" ) )
  501. {
  502. token = COM_ParseExt( text, qfalse );
  503. if ( token[0] == 0 )
  504. {
  505. ri.Printf( PRINT_WARNING, "WARNING: missing tcMod rotate parms in shader '%s'\n", shader.name );
  506. return;
  507. }
  508. tmi->rotateSpeed = atof( token );
  509. tmi->type = TMOD_ROTATE;
  510. }
  511. //
  512. // entityTranslate
  513. //
  514. else if ( !Q_stricmp( token, "entityTranslate" ) )
  515. {
  516. tmi->type = TMOD_ENTITY_TRANSLATE;
  517. }
  518. else
  519. {
  520. ri.Printf( PRINT_WARNING, "WARNING: unknown tcMod '%s' in shader '%s'\n", token, shader.name );
  521. }
  522. }
  523. /*
  524. ===================
  525. ParseStage
  526. ===================
  527. */
  528. static qboolean ParseStage( shaderStage_t *stage, char **text )
  529. {
  530. char *token;
  531. int depthMaskBits = GLS_DEPTHMASK_TRUE, blendSrcBits = 0, blendDstBits = 0, atestBits = 0, depthFuncBits = 0;
  532. qboolean depthMaskExplicit = qfalse;
  533. stage->active = qtrue;
  534. while ( 1 )
  535. {
  536. token = COM_ParseExt( text, qtrue );
  537. if ( !token[0] )
  538. {
  539. ri.Printf( PRINT_WARNING, "WARNING: no matching '}' found\n" );
  540. return qfalse;
  541. }
  542. if ( token[0] == '}' )
  543. {
  544. break;
  545. }
  546. //
  547. // map <name>
  548. //
  549. else if ( !Q_stricmp( token, "map" ) )
  550. {
  551. token = COM_ParseExt( text, qfalse );
  552. if ( !token[0] )
  553. {
  554. ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'map' keyword in shader '%s'\n", shader.name );
  555. return qfalse;
  556. }
  557. if ( !Q_stricmp( token, "$whiteimage" ) )
  558. {
  559. stage->bundle[0].image[0] = tr.whiteImage;
  560. continue;
  561. }
  562. else if ( !Q_stricmp( token, "$lightmap" ) )
  563. {
  564. stage->bundle[0].isLightmap = qtrue;
  565. if ( shader.lightmapIndex < 0 ) {
  566. stage->bundle[0].image[0] = tr.whiteImage;
  567. } else {
  568. stage->bundle[0].image[0] = tr.lightmaps[shader.lightmapIndex];
  569. }
  570. continue;
  571. }
  572. else
  573. {
  574. stage->bundle[0].image[0] = R_FindImageFile( token, !shader.noMipMaps, !shader.noPicMip, GL_REPEAT );
  575. if ( !stage->bundle[0].image[0] )
  576. {
  577. ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name );
  578. return qfalse;
  579. }
  580. }
  581. }
  582. //
  583. // clampmap <name>
  584. //
  585. else if ( !Q_stricmp( token, "clampmap" ) )
  586. {
  587. token = COM_ParseExt( text, qfalse );
  588. if ( !token[0] )
  589. {
  590. ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'clampmap' keyword in shader '%s'\n", shader.name );
  591. return qfalse;
  592. }
  593. stage->bundle[0].image[0] = R_FindImageFile( token, !shader.noMipMaps, !shader.noPicMip, GL_CLAMP );
  594. if ( !stage->bundle[0].image[0] )
  595. {
  596. ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name );
  597. return qfalse;
  598. }
  599. }
  600. //
  601. // animMap <frequency> <image1> .... <imageN>
  602. //
  603. else if ( !Q_stricmp( token, "animMap" ) )
  604. {
  605. token = COM_ParseExt( text, qfalse );
  606. if ( !token[0] )
  607. {
  608. ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'animMmap' keyword in shader '%s'\n", shader.name );
  609. return qfalse;
  610. }
  611. stage->bundle[0].imageAnimationSpeed = atof( token );
  612. // parse up to MAX_IMAGE_ANIMATIONS animations
  613. while ( 1 ) {
  614. int num;
  615. token = COM_ParseExt( text, qfalse );
  616. if ( !token[0] ) {
  617. break;
  618. }
  619. num = stage->bundle[0].numImageAnimations;
  620. if ( num < MAX_IMAGE_ANIMATIONS ) {
  621. stage->bundle[0].image[num] = R_FindImageFile( token, !shader.noMipMaps, !shader.noPicMip, GL_REPEAT );
  622. if ( !stage->bundle[0].image[num] )
  623. {
  624. ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name );
  625. return qfalse;
  626. }
  627. stage->bundle[0].numImageAnimations++;
  628. }
  629. }
  630. }
  631. else if ( !Q_stricmp( token, "videoMap" ) )
  632. {
  633. token = COM_ParseExt( text, qfalse );
  634. if ( !token[0] )
  635. {
  636. ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'videoMmap' keyword in shader '%s'\n", shader.name );
  637. return qfalse;
  638. }
  639. stage->bundle[0].videoMapHandle = ri.CIN_PlayCinematic( token, 0, 0, 256, 256, (CIN_loop | CIN_silent | CIN_shader));
  640. if (stage->bundle[0].videoMapHandle != -1) {
  641. stage->bundle[0].isVideoMap = qtrue;
  642. stage->bundle[0].image[0] = tr.scratchImage[stage->bundle[0].videoMapHandle];
  643. }
  644. }
  645. //
  646. // alphafunc <func>
  647. //
  648. else if ( !Q_stricmp( token, "alphaFunc" ) )
  649. {
  650. token = COM_ParseExt( text, qfalse );
  651. if ( !token[0] )
  652. {
  653. ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'alphaFunc' keyword in shader '%s'\n", shader.name );
  654. return qfalse;
  655. }
  656. atestBits = NameToAFunc( token );
  657. }
  658. //
  659. // depthFunc <func>
  660. //
  661. else if ( !Q_stricmp( token, "depthfunc" ) )
  662. {
  663. token = COM_ParseExt( text, qfalse );
  664. if ( !token[0] )
  665. {
  666. ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'depthfunc' keyword in shader '%s'\n", shader.name );
  667. return qfalse;
  668. }
  669. if ( !Q_stricmp( token, "lequal" ) )
  670. {
  671. depthFuncBits = 0;
  672. }
  673. else if ( !Q_stricmp( token, "equal" ) )
  674. {
  675. depthFuncBits = GLS_DEPTHFUNC_EQUAL;
  676. }
  677. else
  678. {
  679. ri.Printf( PRINT_WARNING, "WARNING: unknown depthfunc '%s' in shader '%s'\n", token, shader.name );
  680. continue;
  681. }
  682. }
  683. //
  684. // detail
  685. //
  686. else if ( !Q_stricmp( token, "detail" ) )
  687. {
  688. stage->isDetail = qtrue;
  689. }
  690. //
  691. // blendfunc <srcFactor> <dstFactor>
  692. // or blendfunc <add|filter|blend>
  693. //
  694. else if ( !Q_stricmp( token, "blendfunc" ) )
  695. {
  696. token = COM_ParseExt( text, qfalse );
  697. if ( token[0] == 0 )
  698. {
  699. ri.Printf( PRINT_WARNING, "WARNING: missing parm for blendFunc in shader '%s'\n", shader.name );
  700. continue;
  701. }
  702. // check for "simple" blends first
  703. if ( !Q_stricmp( token, "add" ) ) {
  704. blendSrcBits = GLS_SRCBLEND_ONE;
  705. blendDstBits = GLS_DSTBLEND_ONE;
  706. } else if ( !Q_stricmp( token, "filter" ) ) {
  707. blendSrcBits = GLS_SRCBLEND_DST_COLOR;
  708. blendDstBits = GLS_DSTBLEND_ZERO;
  709. } else if ( !Q_stricmp( token, "blend" ) ) {
  710. blendSrcBits = GLS_SRCBLEND_SRC_ALPHA;
  711. blendDstBits = GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA;
  712. } else {
  713. // complex double blends
  714. blendSrcBits = NameToSrcBlendMode( token );
  715. token = COM_ParseExt( text, qfalse );
  716. if ( token[0] == 0 )
  717. {
  718. ri.Printf( PRINT_WARNING, "WARNING: missing parm for blendFunc in shader '%s'\n", shader.name );
  719. continue;
  720. }
  721. blendDstBits = NameToDstBlendMode( token );
  722. }
  723. // clear depth mask for blended surfaces
  724. if ( !depthMaskExplicit )
  725. {
  726. depthMaskBits = 0;
  727. }
  728. }
  729. //
  730. // rgbGen
  731. //
  732. else if ( !Q_stricmp( token, "rgbGen" ) )
  733. {
  734. token = COM_ParseExt( text, qfalse );
  735. if ( token[0] == 0 )
  736. {
  737. ri.Printf( PRINT_WARNING, "WARNING: missing parameters for rgbGen in shader '%s'\n", shader.name );
  738. continue;
  739. }
  740. if ( !Q_stricmp( token, "wave" ) )
  741. {
  742. ParseWaveForm( text, &stage->rgbWave );
  743. stage->rgbGen = CGEN_WAVEFORM;
  744. }
  745. else if ( !Q_stricmp( token, "const" ) )
  746. {
  747. vec3_t color;
  748. ParseVector( text, 3, color );
  749. stage->constantColor[0] = 255 * color[0];
  750. stage->constantColor[1] = 255 * color[1];
  751. stage->constantColor[2] = 255 * color[2];
  752. stage->rgbGen = CGEN_CONST;
  753. }
  754. else if ( !Q_stricmp( token, "identity" ) )
  755. {
  756. stage->rgbGen = CGEN_IDENTITY;
  757. }
  758. else if ( !Q_stricmp( token, "identityLighting" ) )
  759. {
  760. stage->rgbGen = CGEN_IDENTITY_LIGHTING;
  761. }
  762. else if ( !Q_stricmp( token, "entity" ) )
  763. {
  764. stage->rgbGen = CGEN_ENTITY;
  765. }
  766. else if ( !Q_stricmp( token, "oneMinusEntity" ) )
  767. {
  768. stage->rgbGen = CGEN_ONE_MINUS_ENTITY;
  769. }
  770. else if ( !Q_stricmp( token, "vertex" ) )
  771. {
  772. stage->rgbGen = CGEN_VERTEX;
  773. if ( stage->alphaGen == 0 ) {
  774. stage->alphaGen = AGEN_VERTEX;
  775. }
  776. }
  777. else if ( !Q_stricmp( token, "exactVertex" ) )
  778. {
  779. stage->rgbGen = CGEN_EXACT_VERTEX;
  780. }
  781. else if ( !Q_stricmp( token, "lightingDiffuse" ) )
  782. {
  783. stage->rgbGen = CGEN_LIGHTING_DIFFUSE;
  784. }
  785. else if ( !Q_stricmp( token, "oneMinusVertex" ) )
  786. {
  787. stage->rgbGen = CGEN_ONE_MINUS_VERTEX;
  788. }
  789. else
  790. {
  791. ri.Printf( PRINT_WARNING, "WARNING: unknown rgbGen parameter '%s' in shader '%s'\n", token, shader.name );
  792. continue;
  793. }
  794. }
  795. //
  796. // alphaGen
  797. //
  798. else if ( !Q_stricmp( token, "alphaGen" ) )
  799. {
  800. token = COM_ParseExt( text, qfalse );
  801. if ( token[0] == 0 )
  802. {
  803. ri.Printf( PRINT_WARNING, "WARNING: missing parameters for alphaGen in shader '%s'\n", shader.name );
  804. continue;
  805. }
  806. if ( !Q_stricmp( token, "wave" ) )
  807. {
  808. ParseWaveForm( text, &stage->alphaWave );
  809. stage->alphaGen = AGEN_WAVEFORM;
  810. }
  811. else if ( !Q_stricmp( token, "const" ) )
  812. {
  813. token = COM_ParseExt( text, qfalse );
  814. stage->constantColor[3] = 255 * atof( token );
  815. stage->alphaGen = AGEN_CONST;
  816. }
  817. else if ( !Q_stricmp( token, "identity" ) )
  818. {
  819. stage->alphaGen = AGEN_IDENTITY;
  820. }
  821. else if ( !Q_stricmp( token, "entity" ) )
  822. {
  823. stage->alphaGen = AGEN_ENTITY;
  824. }
  825. else if ( !Q_stricmp( token, "oneMinusEntity" ) )
  826. {
  827. stage->alphaGen = AGEN_ONE_MINUS_ENTITY;
  828. }
  829. else if ( !Q_stricmp( token, "vertex" ) )
  830. {
  831. stage->alphaGen = AGEN_VERTEX;
  832. }
  833. else if ( !Q_stricmp( token, "lightingSpecular" ) )
  834. {
  835. stage->alphaGen = AGEN_LIGHTING_SPECULAR;
  836. }
  837. else if ( !Q_stricmp( token, "oneMinusVertex" ) )
  838. {
  839. stage->alphaGen = AGEN_ONE_MINUS_VERTEX;
  840. }
  841. else if ( !Q_stricmp( token, "portal" ) )
  842. {
  843. stage->alphaGen = AGEN_PORTAL;
  844. token = COM_ParseExt( text, qfalse );
  845. if ( token[0] == 0 )
  846. {
  847. shader.portalRange = 256;
  848. ri.Printf( PRINT_WARNING, "WARNING: missing range parameter for alphaGen portal in shader '%s', defaulting to 256\n", shader.name );
  849. }
  850. else
  851. {
  852. shader.portalRange = atof( token );
  853. }
  854. }
  855. else
  856. {
  857. ri.Printf( PRINT_WARNING, "WARNING: unknown alphaGen parameter '%s' in shader '%s'\n", token, shader.name );
  858. continue;
  859. }
  860. }
  861. //
  862. // tcGen <function>
  863. //
  864. else if ( !Q_stricmp(token, "texgen") || !Q_stricmp( token, "tcGen" ) )
  865. {
  866. token = COM_ParseExt( text, qfalse );
  867. if ( token[0] == 0 )
  868. {
  869. ri.Printf( PRINT_WARNING, "WARNING: missing texgen parm in shader '%s'\n", shader.name );
  870. continue;
  871. }
  872. if ( !Q_stricmp( token, "environment" ) )
  873. {
  874. stage->bundle[0].tcGen = TCGEN_ENVIRONMENT_MAPPED;
  875. }
  876. else if ( !Q_stricmp( token, "lightmap" ) )
  877. {
  878. stage->bundle[0].tcGen = TCGEN_LIGHTMAP;
  879. }
  880. else if ( !Q_stricmp( token, "texture" ) || !Q_stricmp( token, "base" ) )
  881. {
  882. stage->bundle[0].tcGen = TCGEN_TEXTURE;
  883. }
  884. else if ( !Q_stricmp( token, "vector" ) )
  885. {
  886. ParseVector( text, 3, stage->bundle[0].tcGenVectors[0] );
  887. ParseVector( text, 3, stage->bundle[0].tcGenVectors[1] );
  888. stage->bundle[0].tcGen = TCGEN_VECTOR;
  889. }
  890. else
  891. {
  892. ri.Printf( PRINT_WARNING, "WARNING: unknown texgen parm in shader '%s'\n", shader.name );
  893. }
  894. }
  895. //
  896. // tcMod <type> <...>
  897. //
  898. else if ( !Q_stricmp( token, "tcMod" ) )
  899. {
  900. char buffer[1024] = "";
  901. while ( 1 )
  902. {
  903. token = COM_ParseExt( text, qfalse );
  904. if ( token[0] == 0 )
  905. break;
  906. strcat( buffer, token );
  907. strcat( buffer, " " );
  908. }
  909. ParseTexMod( buffer, stage );
  910. continue;
  911. }
  912. //
  913. // depthmask
  914. //
  915. else if ( !Q_stricmp( token, "depthwrite" ) )
  916. {
  917. depthMaskBits = GLS_DEPTHMASK_TRUE;
  918. depthMaskExplicit = qtrue;
  919. continue;
  920. }
  921. else
  922. {
  923. ri.Printf( PRINT_WARNING, "WARNING: unknown parameter '%s' in shader '%s'\n", token, shader.name );
  924. return qfalse;
  925. }
  926. }
  927. //
  928. // if cgen isn't explicitly specified, use either identity or identitylighting
  929. //
  930. if ( stage->rgbGen == CGEN_BAD ) {
  931. if ( blendSrcBits == 0 ||
  932. blendSrcBits == GLS_SRCBLEND_ONE ||
  933. blendSrcBits == GLS_SRCBLEND_SRC_ALPHA ) {
  934. stage->rgbGen = CGEN_IDENTITY_LIGHTING;
  935. } else {
  936. stage->rgbGen = CGEN_IDENTITY;
  937. }
  938. }
  939. //
  940. // implicitly assume that a GL_ONE GL_ZERO blend mask disables blending
  941. //
  942. if ( ( blendSrcBits == GLS_SRCBLEND_ONE ) &&
  943. ( blendDstBits == GLS_DSTBLEND_ZERO ) )
  944. {
  945. blendDstBits = blendSrcBits = 0;
  946. depthMaskBits = GLS_DEPTHMASK_TRUE;
  947. }
  948. // decide which agens we can skip
  949. if ( stage->alphaGen == CGEN_IDENTITY ) {
  950. if ( stage->rgbGen == CGEN_IDENTITY
  951. || stage->rgbGen == CGEN_LIGHTING_DIFFUSE ) {
  952. stage->alphaGen = AGEN_SKIP;
  953. }
  954. }
  955. //
  956. // compute state bits
  957. //
  958. stage->stateBits = depthMaskBits |
  959. blendSrcBits | blendDstBits |
  960. atestBits |
  961. depthFuncBits;
  962. return qtrue;
  963. }
  964. /*
  965. ===============
  966. ParseDeform
  967. deformVertexes wave <spread> <waveform> <base> <amplitude> <phase> <frequency>
  968. deformVertexes normal <frequency> <amplitude>
  969. deformVertexes move <vector> <waveform> <base> <amplitude> <phase> <frequency>
  970. deformVertexes bulge <bulgeWidth> <bulgeHeight> <bulgeSpeed>
  971. deformVertexes projectionShadow
  972. deformVertexes autoSprite
  973. deformVertexes autoSprite2
  974. deformVertexes text[0-7]
  975. ===============
  976. */
  977. static void ParseDeform( char **text ) {
  978. char *token;
  979. deformStage_t *ds;
  980. token = COM_ParseExt( text, qfalse );
  981. if ( token[0] == 0 )
  982. {
  983. ri.Printf( PRINT_WARNING, "WARNING: missing deform parm in shader '%s'\n", shader.name );
  984. return;
  985. }
  986. if ( shader.numDeforms == MAX_SHADER_DEFORMS ) {
  987. ri.Printf( PRINT_WARNING, "WARNING: MAX_SHADER_DEFORMS in '%s'\n", shader.name );
  988. return;
  989. }
  990. ds = &shader.deforms[ shader.numDeforms ];
  991. shader.numDeforms++;
  992. if ( !Q_stricmp( token, "projectionShadow" ) ) {
  993. ds->deformation = DEFORM_PROJECTION_SHADOW;
  994. return;
  995. }
  996. if ( !Q_stricmp( token, "autosprite" ) ) {
  997. ds->deformation = DEFORM_AUTOSPRITE;
  998. return;
  999. }
  1000. if ( !Q_stricmp( token, "autosprite2" ) ) {
  1001. ds->deformation = DEFORM_AUTOSPRITE2;
  1002. return;
  1003. }
  1004. if ( !Q_stricmpn( token, "text", 4 ) ) {
  1005. int n;
  1006. n = token[4] - '0';
  1007. if ( n < 0 || n > 7 ) {
  1008. n = 0;
  1009. }
  1010. ds->deformation = DEFORM_TEXT0 + n;
  1011. return;
  1012. }
  1013. if ( !Q_stricmp( token, "bulge" ) ) {
  1014. token = COM_ParseExt( text, qfalse );
  1015. if ( token[0] == 0 )
  1016. {
  1017. ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes bulge parm in shader '%s'\n", shader.name );
  1018. return;
  1019. }
  1020. ds->bulgeWidth = atof( token );
  1021. token = COM_ParseExt( text, qfalse );
  1022. if ( token[0] == 0 )
  1023. {
  1024. ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes bulge parm in shader '%s'\n", shader.name );
  1025. return;
  1026. }
  1027. ds->bulgeHeight = atof( token );
  1028. token = COM_ParseExt( text, qfalse );
  1029. if ( token[0] == 0 )
  1030. {
  1031. ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes bulge parm in shader '%s'\n", shader.name );
  1032. return;
  1033. }
  1034. ds->bulgeSpeed = atof( token );
  1035. ds->deformation = DEFORM_BULGE;
  1036. return;
  1037. }
  1038. if ( !Q_stricmp( token, "wave" ) )
  1039. {
  1040. token = COM_ParseExt( text, qfalse );
  1041. if ( token[0] == 0 )
  1042. {
  1043. ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes parm in shader '%s'\n", shader.name );
  1044. return;
  1045. }
  1046. if ( atof( token ) != 0 )
  1047. {
  1048. ds->deformationSpread = 1.0f / atof( token );
  1049. }
  1050. else
  1051. {
  1052. ds->deformationSpread = 100.0f;
  1053. ri.Printf( PRINT_WARNING, "WARNING: illegal div value of 0 in deformVertexes command for shader '%s'\n", shader.name );
  1054. }
  1055. ParseWaveForm( text, &ds->deformationWave );
  1056. ds->deformation = DEFORM_WAVE;
  1057. return;
  1058. }
  1059. if ( !Q_stricmp( token, "normal" ) )
  1060. {
  1061. token = COM_ParseExt( text, qfalse );
  1062. if ( token[0] == 0 )
  1063. {
  1064. ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes parm in shader '%s'\n", shader.name );
  1065. return;
  1066. }
  1067. ds->deformationWave.amplitude = atof( token );
  1068. token = COM_ParseExt( text, qfalse );
  1069. if ( token[0] == 0 )
  1070. {
  1071. ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes parm in shader '%s'\n", shader.name );
  1072. return;
  1073. }
  1074. ds->deformationWave.frequency = atof( token );
  1075. ds->deformation = DEFORM_NORMALS;
  1076. return;
  1077. }
  1078. if ( !Q_stricmp( token, "move" ) ) {
  1079. int i;
  1080. for ( i = 0 ; i < 3 ; i++ ) {
  1081. token = COM_ParseExt( text, qfalse );
  1082. if ( token[0] == 0 ) {
  1083. ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes parm in shader '%s'\n", shader.name );
  1084. return;
  1085. }
  1086. ds->moveVector[i] = atof( token );
  1087. }
  1088. ParseWaveForm( text, &ds->deformationWave );
  1089. ds->deformation = DEFORM_MOVE;
  1090. return;
  1091. }
  1092. ri.Printf( PRINT_WARNING, "WARNING: unknown deformVertexes subtype '%s' found in shader '%s'\n", token, shader.name );
  1093. }
  1094. /*
  1095. ===============
  1096. ParseSkyParms
  1097. skyParms <outerbox> <cloudheight> <innerbox>
  1098. ===============
  1099. */
  1100. static void ParseSkyParms( char **text ) {
  1101. char *token;
  1102. static char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
  1103. char pathname[MAX_QPATH];
  1104. int i;
  1105. // outerbox
  1106. token = COM_ParseExt( text, qfalse );
  1107. if ( token[0] == 0 ) {
  1108. ri.Printf( PRINT_WARNING, "WARNING: 'skyParms' missing parameter in shader '%s'\n", shader.name );
  1109. return;
  1110. }
  1111. if ( strcmp( token, "-" ) ) {
  1112. for (i=0 ; i<6 ; i++) {
  1113. Com_sprintf( pathname, sizeof(pathname), "%s_%s.tga"
  1114. , token, suf[i] );
  1115. shader.sky.outerbox[i] = R_FindImageFile( ( char * ) pathname, qtrue, qtrue, GL_CLAMP );
  1116. if ( !shader.sky.outerbox[i] ) {
  1117. shader.sky.outerbox[i] = tr.defaultImage;
  1118. }
  1119. }
  1120. }
  1121. // cloudheight
  1122. token = COM_ParseExt( text, qfalse );
  1123. if ( token[0] == 0 ) {
  1124. ri.Printf( PRINT_WARNING, "WARNING: 'skyParms' missing parameter in shader '%s'\n", shader.name );
  1125. return;
  1126. }
  1127. shader.sky.cloudHeight = atof( token );
  1128. if ( !shader.sky.cloudHeight ) {
  1129. shader.sky.cloudHeight = 512;
  1130. }
  1131. R_InitSkyTexCoords( shader.sky.cloudHeight );
  1132. // innerbox
  1133. token = COM_ParseExt( text, qfalse );
  1134. if ( token[0] == 0 ) {
  1135. ri.Printf( PRINT_WARNING, "WARNING: 'skyParms' missing parameter in shader '%s'\n", shader.name );
  1136. return;
  1137. }
  1138. if ( strcmp( token, "-" ) ) {
  1139. for (i=0 ; i<6 ; i++) {
  1140. Com_sprintf( pathname, sizeof(pathname), "%s_%s.tga"
  1141. , token, suf[i] );
  1142. shader.sky.innerbox[i] = R_FindImageFile( ( char * ) pathname, qtrue, qtrue, GL_REPEAT );
  1143. if ( !shader.sky.innerbox[i] ) {
  1144. shader.sky.innerbox[i] = tr.defaultImage;
  1145. }
  1146. }
  1147. }
  1148. shader.isSky = qtrue;
  1149. }
  1150. /*
  1151. =================
  1152. ParseSort
  1153. =================
  1154. */
  1155. void ParseSort( char **text ) {
  1156. char *token;
  1157. token = COM_ParseExt( text, qfalse );
  1158. if ( token[0] == 0 ) {
  1159. ri.Printf( PRINT_WARNING, "WARNING: missing sort parameter in shader '%s'\n", shader.name );
  1160. return;
  1161. }
  1162. if ( !Q_stricmp( token, "portal" ) ) {
  1163. shader.sort = SS_PORTAL;
  1164. } else if ( !Q_stricmp( token, "sky" ) ) {
  1165. shader.sort = SS_ENVIRONMENT;
  1166. } else if ( !Q_stricmp( token, "opaque" ) ) {
  1167. shader.sort = SS_OPAQUE;
  1168. }else if ( !Q_stricmp( token, "decal" ) ) {
  1169. shader.sort = SS_DECAL;
  1170. } else if ( !Q_stricmp( token, "seeThrough" ) ) {
  1171. shader.sort = SS_SEE_THROUGH;
  1172. } else if ( !Q_stricmp( token, "banner" ) ) {
  1173. shader.sort = SS_BANNER;
  1174. } else if ( !Q_stricmp( token, "additive" ) ) {
  1175. shader.sort = SS_BLEND1;
  1176. } else if ( !Q_stricmp( token, "nearest" ) ) {
  1177. shader.sort = SS_NEAREST;
  1178. } else if ( !Q_stricmp( token, "underwater" ) ) {
  1179. shader.sort = SS_UNDERWATER;
  1180. } else {
  1181. shader.sort = atof( token );
  1182. }
  1183. }
  1184. // this table is also present in q3map
  1185. typedef struct {
  1186. char *name;
  1187. int clearSolid, surfaceFlags, contents;
  1188. } infoParm_t;
  1189. infoParm_t infoParms[] = {
  1190. // server relevant contents
  1191. {"water", 1, 0, CONTENTS_WATER },
  1192. {"slime", 1, 0, CONTENTS_SLIME }, // mildly damaging
  1193. {"lava", 1, 0, CONTENTS_LAVA }, // very damaging
  1194. {"playerclip", 1, 0, CONTENTS_PLAYERCLIP },
  1195. {"monsterclip", 1, 0, CONTENTS_MONSTERCLIP },
  1196. {"nodrop", 1, 0, CONTENTS_NODROP }, // don't drop items or leave bodies (death fog, lava, etc)
  1197. {"nonsolid", 1, SURF_NONSOLID, 0}, // clears the solid flag
  1198. // utility relevant attributes
  1199. {"origin", 1, 0, CONTENTS_ORIGIN }, // center of rotating brushes
  1200. {"trans", 0, 0, CONTENTS_TRANSLUCENT }, // don't eat contained surfaces
  1201. {"detail", 0, 0, CONTENTS_DETAIL }, // don't include in structural bsp
  1202. {"structural", 0, 0, CONTENTS_STRUCTURAL }, // force into structural bsp even if trnas
  1203. {"areaportal", 1, 0, CONTENTS_AREAPORTAL }, // divides areas
  1204. {"clusterportal", 1,0, CONTENTS_CLUSTERPORTAL }, // for bots
  1205. {"donotenter", 1, 0, CONTENTS_DONOTENTER }, // for bots
  1206. {"fog", 1, 0, CONTENTS_FOG}, // carves surfaces entering
  1207. {"sky", 0, SURF_SKY, 0 }, // emit light from an environment map
  1208. {"lightfilter", 0, SURF_LIGHTFILTER, 0 }, // filter light going through it
  1209. {"alphashadow", 0, SURF_ALPHASHADOW, 0 }, // test light on a per-pixel basis
  1210. {"hint", 0, SURF_HINT, 0 }, // use as a primary splitter
  1211. // server attributes
  1212. {"slick", 0, SURF_SLICK, 0 },
  1213. {"noimpact", 0, SURF_NOIMPACT, 0 }, // don't make impact explosions or marks
  1214. {"nomarks", 0, SURF_NOMARKS, 0 }, // don't make impact marks, but still explode
  1215. {"ladder", 0, SURF_LADDER, 0 },
  1216. {"nodamage", 0, SURF_NODAMAGE, 0 },
  1217. {"metalsteps", 0, SURF_METALSTEPS,0 },
  1218. {"flesh", 0, SURF_FLESH, 0 },
  1219. {"nosteps", 0, SURF_NOSTEPS, 0 },
  1220. // drawsurf attributes
  1221. {"nodraw", 0, SURF_NODRAW, 0 }, // don't generate a drawsurface (or a lightmap)
  1222. {"pointlight", 0, SURF_POINTLIGHT, 0 }, // sample lighting at vertexes
  1223. {"nolightmap", 0, SURF_NOLIGHTMAP,0 }, // don't generate a lightmap
  1224. {"nodlight", 0, SURF_NODLIGHT, 0 }, // don't ever add dynamic lights
  1225. {"dust", 0, SURF_DUST, 0} // leave a dust trail when walking on this surface
  1226. };
  1227. /*
  1228. ===============
  1229. ParseSurfaceParm
  1230. surfaceparm <name>
  1231. ===============
  1232. */
  1233. static void ParseSurfaceParm( char **text ) {
  1234. char *token;
  1235. int numInfoParms = sizeof(infoParms) / sizeof(infoParms[0]);
  1236. int i;
  1237. token = COM_ParseExt( text, qfalse );
  1238. for ( i = 0 ; i < numInfoParms ; i++ ) {
  1239. if ( !Q_stricmp( token, infoParms[i].name ) ) {
  1240. shader.surfaceFlags |= infoParms[i].surfaceFlags;
  1241. shader.contentFlags |= infoParms[i].contents;
  1242. #if 0
  1243. if ( infoParms[i].clearSolid ) {
  1244. si->contents &= ~CONTENTS_SOLID;
  1245. }
  1246. #endif
  1247. break;
  1248. }
  1249. }
  1250. }
  1251. /*
  1252. =================
  1253. ParseShader
  1254. The current text pointer is at the explicit text definition of the
  1255. shader. Parse it into the global shader variable. Later functions
  1256. will optimize it.
  1257. =================
  1258. */
  1259. static qboolean ParseShader( char **text )
  1260. {
  1261. char *token;
  1262. int s;
  1263. s = 0;
  1264. token = COM_ParseExt( text, qtrue );
  1265. if ( token[0] != '{' )
  1266. {
  1267. ri.Printf( PRINT_WARNING, "WARNING: expecting '{', found '%s' instead in shader '%s'\n", token, shader.name );
  1268. return qfalse;
  1269. }
  1270. while ( 1 )
  1271. {
  1272. token = COM_ParseExt( text, qtrue );
  1273. if ( !token[0] )
  1274. {
  1275. ri.Printf( PRINT_WARNING, "WARNING: no concluding '}' in shader %s\n", shader.name );
  1276. return qfalse;
  1277. }
  1278. // end of shader definition
  1279. if ( token[0] == '}' )
  1280. {
  1281. break;
  1282. }
  1283. // stage definition
  1284. else if ( token[0] == '{' )
  1285. {
  1286. if ( !ParseStage( &stages[s], text ) )
  1287. {
  1288. return qfalse;
  1289. }
  1290. stages[s].active = qtrue;
  1291. s++;
  1292. continue;
  1293. }
  1294. // skip stuff that only the QuakeEdRadient needs
  1295. else if ( !Q_stricmpn( token, "qer", 3 ) ) {
  1296. SkipRestOfLine( text );
  1297. continue;
  1298. }
  1299. // sun parms
  1300. else if ( !Q_stricmp( token, "q3map_sun" ) ) {
  1301. float a, b;
  1302. token = COM_ParseExt( text, qfalse );
  1303. tr.sunLight[0] = atof( token );
  1304. token = COM_ParseExt( text, qfalse );
  1305. tr.sunLight[1] = atof( token );
  1306. token = COM_ParseExt( text, qfalse );
  1307. tr.sunLight[2] = atof( token );
  1308. VectorNormalize( tr.sunLight );
  1309. token = COM_ParseExt( text, qfalse );
  1310. a = atof( token );
  1311. VectorScale( tr.sunLight, a, tr.sunLight);
  1312. token = COM_ParseExt( text, qfalse );
  1313. a = atof( token );
  1314. a = a / 180 * M_PI;
  1315. token = COM_ParseExt( text, qfalse );
  1316. b = atof( token );
  1317. b = b / 180 * M_PI;
  1318. tr.sunDirection[0] = cos( a ) * cos( b );
  1319. tr.sunDirection[1] = sin( a ) * cos( b );
  1320. tr.sunDirection[2] = sin( b );
  1321. }
  1322. else if ( !Q_stricmp( token, "deformVertexes" ) ) {
  1323. ParseDeform( text );
  1324. continue;
  1325. }
  1326. else if ( !Q_stricmp( token, "tesssize" ) ) {
  1327. SkipRestOfLine( text );
  1328. continue;
  1329. }
  1330. else if ( !Q_stricmp( token, "clampTime" ) ) {
  1331. token = COM_ParseExt( text, qfalse );
  1332. if (token[0]) {
  1333. shader.clampTime = atof(token);
  1334. }
  1335. }
  1336. // skip stuff that only the q3map needs
  1337. else if ( !Q_stricmpn( token, "q3map", 5 ) ) {
  1338. SkipRestOfLine( text );
  1339. continue;
  1340. }
  1341. // skip stuff that only q3map or the server needs
  1342. else if ( !Q_stricmp( token, "surfaceParm" ) ) {
  1343. ParseSurfaceParm( text );
  1344. continue;
  1345. }
  1346. // no mip maps
  1347. else if ( !Q_stricmp( token, "nomipmaps" ) )
  1348. {
  1349. shader.noMipMaps = qtrue;
  1350. shader.noPicMip = qtrue;
  1351. continue;
  1352. }
  1353. // no picmip adjustment
  1354. else if ( !Q_stricmp( token, "nopicmip" ) )
  1355. {
  1356. shader.noPicMip = qtrue;
  1357. continue;
  1358. }
  1359. // polygonOffset
  1360. else if ( !Q_stricmp( token, "polygonOffset" ) )
  1361. {
  1362. shader.polygonOffset = qtrue;
  1363. continue;
  1364. }
  1365. // entityMergable, allowing sprite surfaces from multiple entities
  1366. // to be merged into one batch. This is a savings for smoke
  1367. // puffs and blood, but can't be used for anything where the
  1368. // shader calcs (not the surface function) reference the entity color or scroll
  1369. else if ( !Q_stricmp( token, "entityMergable" ) )
  1370. {
  1371. shader.entityMergable = qtrue;
  1372. continue;
  1373. }
  1374. // fogParms
  1375. else if ( !Q_stricmp( token, "fogParms" ) )
  1376. {
  1377. if ( !ParseVector( text, 3, shader.fogParms.color ) ) {
  1378. return qfalse;
  1379. }
  1380. token = COM_ParseExt( text, qfalse );
  1381. if ( !token[0] )
  1382. {
  1383. ri.Printf( PRINT_WARNING, "WARNING: missing parm for 'fogParms' keyword in shader '%s'\n", shader.name );
  1384. continue;
  1385. }
  1386. shader.fogParms.depthForOpaque = atof( token );
  1387. // skip any old gradient directions
  1388. SkipRestOfLine( text );
  1389. continue;
  1390. }
  1391. // portal
  1392. else if ( !Q_stricmp(token, "portal") )
  1393. {
  1394. shader.sort = SS_PORTAL;
  1395. continue;
  1396. }
  1397. // skyparms <cloudheight> <outerbox> <innerbox>
  1398. else if ( !Q_stricmp( token, "skyparms" ) )
  1399. {
  1400. ParseSkyParms( text );
  1401. continue;
  1402. }
  1403. // light <value> determines flaring in q3map, not needed here
  1404. else if ( !Q_stricmp(token, "light") )
  1405. {
  1406. token = COM_ParseExt( text, qfalse );
  1407. continue;
  1408. }
  1409. // cull <face>
  1410. else if ( !Q_stricmp( token, "cull") )
  1411. {
  1412. token = COM_ParseExt( text, qfalse );
  1413. if ( token[0] == 0 )
  1414. {
  1415. ri.Printf( PRINT_WARNING, "WARNING: missing cull parms in shader '%s'\n", shader.name );
  1416. continue;
  1417. }
  1418. if ( !Q_stricmp( token, "none" ) || !Q_stricmp( token, "twosided" ) || !Q_stricmp( token, "disable" ) )
  1419. {
  1420. shader.cullType = CT_TWO_SIDED;
  1421. }
  1422. else if ( !Q_stricmp( token, "back" ) || !Q_stricmp( token, "backside" ) || !Q_stricmp( token, "backsided" ) )
  1423. {
  1424. shader.cullType = CT_BACK_SIDED;
  1425. }
  1426. else
  1427. {
  1428. ri.Printf( PRINT_WARNING, "WARNING: invalid cull parm '%s' in shader '%s'\n", token, shader.name );
  1429. }
  1430. continue;
  1431. }
  1432. // sort
  1433. else if ( !Q_stricmp( token, "sort" ) )
  1434. {
  1435. ParseSort( text );
  1436. continue;
  1437. }
  1438. else
  1439. {
  1440. ri.Printf( PRINT_WARNING, "WARNING: unknown general shader parameter '%s' in '%s'\n", token, shader.name );
  1441. return qfalse;
  1442. }
  1443. }
  1444. //
  1445. // ignore shaders that don't have any stages, unless it is a sky or fog
  1446. //
  1447. if ( s == 0 && !shader.isSky && !(shader.contentFlags & CONTENTS_FOG ) ) {
  1448. return qfalse;
  1449. }
  1450. shader.explicitlyDefined = qtrue;
  1451. return qtrue;
  1452. }
  1453. /*
  1454. ========================================================================================
  1455. SHADER OPTIMIZATION AND FOGGING
  1456. ========================================================================================
  1457. */
  1458. /*
  1459. ===================
  1460. ComputeStageIteratorFunc
  1461. See if we can use on of the simple fastpath stage functions,
  1462. otherwise set to the generic stage function
  1463. ===================
  1464. */
  1465. static void ComputeStageIteratorFunc( void )
  1466. {
  1467. shader.optimalStageIteratorFunc = RB_StageIteratorGeneric;
  1468. //
  1469. // see if this should go into the sky path
  1470. //
  1471. if ( shader.isSky )
  1472. {
  1473. shader.optimalStageIteratorFunc = RB_StageIteratorSky;
  1474. goto done;
  1475. }
  1476. if ( r_ignoreFastPath->integer )
  1477. {
  1478. return;
  1479. }
  1480. //
  1481. // see if this can go into the vertex lit fast path
  1482. //
  1483. if ( shader.numUnfoggedPasses == 1 )
  1484. {
  1485. if ( stages[0].rgbGen == CGEN_LIGHTING_DIFFUSE )
  1486. {
  1487. if ( stages[0].alphaGen == AGEN_IDENTITY )
  1488. {
  1489. if ( stages[0].bundle[0].tcGen == TCGEN_TEXTURE )
  1490. {
  1491. if ( !shader.polygonOffset )
  1492. {
  1493. if ( !shader.multitextureEnv )
  1494. {
  1495. if ( !shader.numDeforms )
  1496. {
  1497. shader.optimalStageIteratorFunc = RB_StageIteratorVertexLitTexture;
  1498. goto done;
  1499. }
  1500. }
  1501. }
  1502. }
  1503. }
  1504. }
  1505. }
  1506. //
  1507. // see if this can go into an optimized LM, multitextured path
  1508. //
  1509. if ( shader.numUnfoggedPasses == 1 )
  1510. {
  1511. if ( ( stages[0].rgbGen == CGEN_IDENTITY ) && ( stages[0].alphaGen == AGEN_IDENTITY ) )
  1512. {
  1513. if ( stages[0].bundle[0].tcGen == TCGEN_TEXTURE &&
  1514. stages[0].bundle[1].tcGen == TCGEN_LIGHTMAP )
  1515. {
  1516. if ( !shader.polygonOffset )
  1517. {
  1518. if ( !shader.numDeforms )
  1519. {
  1520. if ( shader.multitextureEnv )
  1521. {
  1522. shader.optimalStageIteratorFunc = RB_StageIteratorLightmappedMultitexture;
  1523. goto done;
  1524. }
  1525. }
  1526. }
  1527. }
  1528. }
  1529. }
  1530. done:
  1531. return;
  1532. }
  1533. typedef struct {
  1534. int blendA;
  1535. int blendB;
  1536. int multitextureEnv;
  1537. int multitextureBlend;
  1538. } collapse_t;
  1539. static collapse_t collapse[] = {
  1540. { 0, GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO,
  1541. GL_MODULATE, 0 },
  1542. { 0, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR,
  1543. GL_MODULATE, 0 },
  1544. { GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR,
  1545. GL_MODULATE, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR },
  1546. { GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR,
  1547. GL_MODULATE, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR },
  1548. { GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR, GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO,
  1549. GL_MODULATE, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR },
  1550. { GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO, GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO,
  1551. GL_MODULATE, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR },
  1552. { 0, GLS_DSTBLEND_ONE | GLS_SRCBLEND_ONE,
  1553. GL_ADD, 0 },
  1554. { GLS_DSTBLEND_ONE | GLS_SRCBLEND_ONE, GLS_DSTBLEND_ONE | GLS_SRCBLEND_ONE,
  1555. GL_ADD, GLS_DSTBLEND_ONE | GLS_SRCBLEND_ONE },
  1556. #if 0
  1557. { 0, GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_SRCBLEND_SRC_ALPHA,
  1558. GL_DECAL, 0 },
  1559. #endif
  1560. { -1 }
  1561. };
  1562. /*
  1563. ================
  1564. CollapseMultitexture
  1565. Attempt to combine two stages into a single multitexture stage
  1566. FIXME: I think modulated add + modulated add collapses incorrectly
  1567. =================
  1568. */
  1569. static qboolean CollapseMultitexture( void ) {
  1570. int abits, bbits;
  1571. int i;
  1572. textureBundle_t tmpBundle;
  1573. if ( !qglActiveTextureARB ) {
  1574. return qfalse;
  1575. }
  1576. // make sure both stages are active
  1577. if ( !stages[0].active || !stages[1].active ) {
  1578. return qfalse;
  1579. }
  1580. // on voodoo2, don't combine different tmus
  1581. if ( glConfig.driverType == GLDRV_VOODOO ) {
  1582. if ( stages[0].bundle[0].image[0]->TMU ==
  1583. stages[1].bundle[0].image[0]->TMU ) {
  1584. return qfalse;
  1585. }
  1586. }
  1587. abits = stages[0].stateBits;
  1588. bbits = stages[1].stateBits;
  1589. // make sure that both stages have identical state other than blend modes
  1590. if ( ( abits & ~( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS | GLS_DEPTHMASK_TRUE ) ) !=
  1591. ( bbits & ~( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS | GLS_DEPTHMASK_TRUE ) ) ) {
  1592. return qfalse;
  1593. }
  1594. abits &= ( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS );
  1595. bbits &= ( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS );
  1596. // search for a valid multitexture blend function
  1597. for ( i = 0; collapse[i].blendA != -1 ; i++ ) {
  1598. if ( abits == collapse[i].blendA
  1599. && bbits == collapse[i].blendB ) {
  1600. break;
  1601. }
  1602. }
  1603. // nothing found
  1604. if ( collapse[i].blendA == -1 ) {
  1605. return qfalse;
  1606. }
  1607. // GL_ADD is a separate extension
  1608. if ( collapse[i].multitextureEnv == GL_ADD && !glConfig.textureEnvAddAvailable ) {
  1609. return qfalse;
  1610. }
  1611. // make sure waveforms have identical parameters
  1612. if ( ( stages[0].rgbGen != stages[1].rgbGen ) ||
  1613. ( stages[0].alphaGen != stages[1].alphaGen ) ) {
  1614. return qfalse;
  1615. }
  1616. // an add collapse can only have identity colors
  1617. if ( collapse[i].multitextureEnv == GL_ADD && stages[0].rgbGen != CGEN_IDENTITY ) {
  1618. return qfalse;
  1619. }
  1620. if ( stages[0].rgbGen == CGEN_WAVEFORM )
  1621. {
  1622. if ( memcmp( &stages[0].rgbWave,
  1623. &stages[1].rgbWave,
  1624. sizeof( stages[0].rgbWave ) ) )
  1625. {
  1626. return qfalse;
  1627. }
  1628. }
  1629. if ( stages[0].alphaGen == CGEN_WAVEFORM )
  1630. {
  1631. if ( memcmp( &stages[0].alphaWave,
  1632. &stages[1].alphaWave,
  1633. sizeof( stages[0].alphaWave ) ) )
  1634. {
  1635. return qfalse;
  1636. }
  1637. }
  1638. // make sure that lightmaps are in bundle 1 for 3dfx
  1639. if ( stages[0].bundle[0].isLightmap )
  1640. {
  1641. tmpBundle = stages[0].bundle[0];
  1642. stages[0].bundle[0] = stages[1].bundle[0];
  1643. stages[0].bundle[1] = tmpBundle;
  1644. }
  1645. else
  1646. {
  1647. stages[0].bundle[1] = stages[1].bundle[0];
  1648. }
  1649. // set the new blend state bits
  1650. shader.multitextureEnv = collapse[i].multitextureEnv;
  1651. stages[0].stateBits &= ~( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS );
  1652. stages[0].stateBits |= collapse[i].multitextureBlend;
  1653. //
  1654. // move down subsequent shaders
  1655. //
  1656. memmove( &stages[1], &stages[2], sizeof( stages[0] ) * ( MAX_SHADER_STAGES - 2 ) );
  1657. Com_Memset( &stages[MAX_SHADER_STAGES-1], 0, sizeof( stages[0] ) );
  1658. return qtrue;
  1659. }
  1660. /*
  1661. =============
  1662. FixRenderCommandList
  1663. https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=493
  1664. Arnout: this is a nasty issue. Shaders can be registered after drawsurfaces are generated
  1665. but before the frame is rendered. This will, for the duration of one frame, cause drawsurfaces
  1666. to be rendered with bad shaders. To fix this, need to go through all render commands and fix
  1667. sortedIndex.
  1668. ==============
  1669. */
  1670. static void FixRenderCommandList( int newShader ) {
  1671. renderCommandList_t *cmdList = &backEndData[tr.smpFrame]->commands;
  1672. if( cmdList ) {
  1673. const void *curCmd = cmdList->cmds;
  1674. while ( 1 ) {
  1675. switch ( *(const int *)curCmd ) {
  1676. case RC_SET_COLOR:
  1677. {
  1678. const setColorCommand_t *sc_cmd = (const setColorCommand_t *)curCmd;
  1679. curCmd = (const void *)(sc_cmd + 1);
  1680. break;
  1681. }
  1682. case RC_STRETCH_PIC:
  1683. {
  1684. const stretchPicCommand_t *sp_cmd = (const stretchPicCommand_t *)curCmd;
  1685. curCmd = (const void *)(sp_cmd + 1);
  1686. break;
  1687. }
  1688. case RC_DRAW_SURFS:
  1689. {
  1690. int i;
  1691. drawSurf_t *drawSurf;
  1692. shader_t *shader;
  1693. int fogNum;
  1694. int entityNum;
  1695. int dlightMap;
  1696. int sortedIndex;
  1697. const drawSurfsCommand_t *ds_cmd = (const drawSurfsCommand_t *)curCmd;
  1698. for( i = 0, drawSurf = ds_cmd->drawSurfs; i < ds_cmd->numDrawSurfs; i++, drawSurf++ ) {
  1699. R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlightMap );
  1700. sortedIndex = (( drawSurf->sort >> QSORT_SHADERNUM_SHIFT ) & (MAX_SHADERS-1));
  1701. if( sortedIndex >= newShader ) {
  1702. sortedIndex++;
  1703. drawSurf->sort = (sortedIndex << QSORT_SHADERNUM_SHIFT) | entityNum | ( fogNum << QSORT_FOGNUM_SHIFT ) | (int)dlightMap;
  1704. }
  1705. }
  1706. curCmd = (const void *)(ds_cmd + 1);
  1707. break;
  1708. }
  1709. case RC_DRAW_BUFFER:
  1710. {
  1711. const drawBufferCommand_t *db_cmd = (const drawBufferCommand_t *)curCmd;
  1712. curCmd = (const void *)(db_cmd + 1);
  1713. break;
  1714. }
  1715. case RC_SWAP_BUFFERS:
  1716. {
  1717. const swapBuffersCommand_t *sb_cmd = (const swapBuffersCommand_t *)curCmd;
  1718. curCmd = (const void *)(sb_cmd + 1);
  1719. break;
  1720. }
  1721. case RC_END_OF_LIST:
  1722. default:
  1723. return;
  1724. }
  1725. }
  1726. }
  1727. }
  1728. /*
  1729. ==============
  1730. SortNewShader
  1731. Positions the most recently created shader in the tr.sortedShaders[]
  1732. array so that the shader->sort key is sorted reletive to the other
  1733. shaders.
  1734. Sets shader->sortedIndex
  1735. ==============
  1736. */
  1737. static void SortNewShader( void ) {
  1738. int i;
  1739. float sort;
  1740. shader_t *newShader;
  1741. newShader = tr.shaders[ tr.numShaders - 1 ];
  1742. sort = newShader->sort;
  1743. for ( i = tr.numShaders - 2 ; i >= 0 ; i-- ) {
  1744. if ( tr.sortedShaders[ i ]->sort <= sort ) {
  1745. break;
  1746. }
  1747. tr.sortedShaders[i+1] = tr.sortedShaders[i];
  1748. tr.sortedShaders[i+1]->sortedIndex++;
  1749. }
  1750. // Arnout: fix rendercommandlist
  1751. // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=493
  1752. FixRenderCommandList( i+1 );
  1753. newShader->sortedIndex = i+1;
  1754. tr.sortedShaders[i+1] = newShader;
  1755. }
  1756. /*
  1757. ====================
  1758. GeneratePermanentShader
  1759. ====================
  1760. */
  1761. static shader_t *GeneratePermanentShader( void ) {
  1762. shader_t *newShader;
  1763. int i, b;
  1764. int size, hash;
  1765. if ( tr.numShaders == MAX_SHADERS ) {
  1766. ri.Printf( PRINT_WARNING, "WARNING: GeneratePermanentShader - MAX_SHADERS hit\n");
  1767. return tr.defaultShader;
  1768. }
  1769. newShader = ri.Hunk_Alloc( sizeof( shader_t ), h_low );
  1770. *newShader = shader;
  1771. if ( shader.sort <= SS_OPAQUE ) {
  1772. newShader->fogPass = FP_EQUAL;
  1773. } else if ( shader.contentFlags & CONTENTS_FOG ) {
  1774. newShader->fogPass = FP_LE;
  1775. }
  1776. tr.shaders[ tr.numShaders ] = newShader;
  1777. newShader->index = tr.numShaders;
  1778. tr.sortedShaders[ tr.numShaders ] = newShader;
  1779. newShader->sortedIndex = tr.numShaders;
  1780. tr.numShaders++;
  1781. for ( i = 0 ; i < newShader->numUnfoggedPasses ; i++ ) {
  1782. if ( !stages[i].active ) {
  1783. break;
  1784. }
  1785. newShader->stages[i] = ri.Hunk_Alloc( sizeof( stages[i] ), h_low );
  1786. *newShader->stages[i] = stages[i];
  1787. for ( b = 0 ; b < NUM_TEXTURE_BUNDLES ; b++ ) {
  1788. size = newShader->stages[i]->bundle[b].numTexMods * sizeof( texModInfo_t );
  1789. newShader->stages[i]->bundle[b].texMods = ri.Hunk_Alloc( size, h_low );
  1790. Com_Memcpy( newShader->stages[i]->bundle[b].texMods, stages[i].bundle[b].texMods, size );
  1791. }
  1792. }
  1793. SortNewShader();
  1794. hash = generateHashValue(newShader->name, FILE_HASH_SIZE);
  1795. newShader->next = hashTable[hash];
  1796. hashTable[hash] = newShader;
  1797. return newShader;
  1798. }
  1799. /*
  1800. =================
  1801. VertexLightingCollapse
  1802. If vertex lighting is enabled, only render a single
  1803. pass, trying to guess which is the correct one to best aproximate
  1804. what it is supposed to look like.
  1805. =================
  1806. */
  1807. static void VertexLightingCollapse( void ) {
  1808. int stage;
  1809. shaderStage_t *bestStage;
  1810. int bestImageRank;
  1811. int rank;
  1812. // if we aren't opaque, just use the first pass
  1813. if ( shader.sort == SS_OPAQUE ) {
  1814. // pick the best texture for the single pass
  1815. bestStage = &stages[0];
  1816. bestImageRank = -999999;
  1817. for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ ) {
  1818. shaderStage_t *pStage = &stages[stage];
  1819. if ( !pStage->active ) {
  1820. break;
  1821. }
  1822. rank = 0;
  1823. if ( pStage->bundle[0].isLightmap ) {
  1824. rank -= 100;
  1825. }
  1826. if ( pStage->bundle[0].tcGen != TCGEN_TEXTURE ) {
  1827. rank -= 5;
  1828. }
  1829. if ( pStage->bundle[0].numTexMods ) {
  1830. rank -= 5;
  1831. }
  1832. if ( pStage->rgbGen != CGEN_IDENTITY && pStage->rgbGen != CGEN_IDENTITY_LIGHTING ) {
  1833. rank -= 3;
  1834. }
  1835. if ( rank > bestImageRank ) {
  1836. bestImageRank = rank;
  1837. bestStage = pStage;
  1838. }
  1839. }
  1840. stages[0].bundle[0] = bestStage->bundle[0];
  1841. stages[0].stateBits &= ~( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS );
  1842. stages[0].stateBits |= GLS_DEPTHMASK_TRUE;
  1843. if ( shader.lightmapIndex == LIGHTMAP_NONE ) {
  1844. stages[0].rgbGen = CGEN_LIGHTING_DIFFUSE;
  1845. } else {
  1846. stages[0].rgbGen = CGEN_EXACT_VERTEX;
  1847. }
  1848. stages[0].alphaGen = AGEN_SKIP;
  1849. } else {
  1850. // don't use a lightmap (tesla coils)
  1851. if ( stages[0].bundle[0].isLightmap ) {
  1852. stages[0] = stages[1];
  1853. }
  1854. // if we were in a cross-fade cgen, hack it to normal
  1855. if ( stages[0].rgbGen == CGEN_ONE_MINUS_ENTITY || stages[1].rgbGen == CGEN_ONE_MINUS_ENTITY ) {
  1856. stages[0].rgbGen = CGEN_IDENTITY_LIGHTING;
  1857. }
  1858. if ( ( stages[0].rgbGen == CGEN_WAVEFORM && stages[0].rgbWave.func == GF_SAWTOOTH )
  1859. && ( stages[1].rgbGen == CGEN_WAVEFORM && stages[1].rgbWave.func == GF_INVERSE_SAWTOOTH ) ) {
  1860. stages[0].rgbGen = CGEN_IDENTITY_LIGHTING;
  1861. }
  1862. if ( ( stages[0].rgbGen == CGEN_WAVEFORM && stages[0].rgbWave.func == GF_INVERSE_SAWTOOTH )
  1863. && ( stages[1].rgbGen == CGEN_WAVEFORM && stages[1].rgbWave.func == GF_SAWTOOTH ) ) {
  1864. stages[0].rgbGen = CGEN_IDENTITY_LIGHTING;
  1865. }
  1866. }
  1867. for ( stage = 1; stage < MAX_SHADER_STAGES; stage++ ) {
  1868. shaderStage_t *pStage = &stages[stage];
  1869. if ( !pStage->active ) {
  1870. break;
  1871. }
  1872. Com_Memset( pStage, 0, sizeof( *pStage ) );
  1873. }
  1874. }
  1875. /*
  1876. =========================
  1877. FinishShader
  1878. Returns a freshly allocated shader with all the needed info
  1879. from the current global working shader
  1880. =========================
  1881. */
  1882. static shader_t *FinishShader( void ) {
  1883. int stage;
  1884. qboolean hasLightmapStage;
  1885. qboolean vertexLightmap;
  1886. hasLightmapStage = qfalse;
  1887. vertexLightmap = qfalse;
  1888. //
  1889. // set sky stuff appropriate
  1890. //
  1891. if ( shader.isSky ) {
  1892. shader.sort = SS_ENVIRONMENT;
  1893. }
  1894. //
  1895. // set polygon offset
  1896. //
  1897. if ( shader.polygonOffset && !shader.sort ) {
  1898. shader.sort = SS_DECAL;
  1899. }
  1900. //
  1901. // set appropriate stage information
  1902. //
  1903. for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ ) {
  1904. shaderStage_t *pStage = &stages[stage];
  1905. if ( !pStage->active ) {
  1906. break;
  1907. }
  1908. // check for a missing texture
  1909. if ( !pStage->bundle[0].image[0] ) {
  1910. ri.Printf( PRINT_WARNING, "Shader %s has a stage with no image\n", shader.name );
  1911. pStage->active = qfalse;
  1912. continue;
  1913. }
  1914. //
  1915. // ditch this stage if it's detail and detail textures are disabled
  1916. //
  1917. if ( pStage->isDetail && !r_detailTextures->integer ) {
  1918. if ( stage < ( MAX_SHADER_STAGES - 1 ) ) {
  1919. memmove( pStage, pStage + 1, sizeof( *pStage ) * ( MAX_SHADER_STAGES - stage - 1 ) );
  1920. Com_Memset( pStage + 1, 0, sizeof( *pStage ) );
  1921. }
  1922. continue;
  1923. }
  1924. //
  1925. // default texture coordinate generation
  1926. //
  1927. if ( pStage->bundle[0].isLightmap ) {
  1928. if ( pStage->bundle[0].tcGen == TCGEN_BAD ) {
  1929. pStage->bundle[0].tcGen = TCGEN_LIGHTMAP;
  1930. }
  1931. hasLightmapStage = qtrue;
  1932. } else {
  1933. if ( pStage->bundle[0].tcGen == TCGEN_BAD ) {
  1934. pStage->bundle[0].tcGen = TCGEN_TEXTURE;
  1935. }
  1936. }
  1937. // not a true lightmap but we want to leave existing
  1938. // behaviour in place and not print out a warning
  1939. //if (pStage->rgbGen == CGEN_VERTEX) {
  1940. // vertexLightmap = qtrue;
  1941. //}
  1942. //
  1943. // determine sort order and fog color adjustment
  1944. //
  1945. if ( ( pStage->stateBits & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) ) &&
  1946. ( stages[0].stateBits & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) ) ) {
  1947. int blendSrcBits = pStage->stateBits & GLS_SRCBLEND_BITS;
  1948. int blendDstBits = pStage->stateBits & GLS_DSTBLEND_BITS;
  1949. // fog color adjustment only works for blend modes that have a contribution
  1950. // that aproaches 0 as the modulate values aproach 0 --
  1951. // GL_ONE, GL_ONE
  1952. // GL_ZERO, GL_ONE_MINUS_SRC_COLOR
  1953. // GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA
  1954. // modulate, additive
  1955. if ( ( ( blendSrcBits == GLS_SRCBLEND_ONE ) && ( blendDstBits == GLS_DSTBLEND_ONE ) ) ||
  1956. ( ( blendSrcBits == GLS_SRCBLEND_ZERO ) && ( blendDstBits == GLS_DSTBLEND_ONE_MINUS_SRC_COLOR ) ) ) {
  1957. pStage->adjustColorsForFog = ACFF_MODULATE_RGB;
  1958. }
  1959. // strict blend
  1960. else if ( ( blendSrcBits == GLS_SRCBLEND_SRC_ALPHA ) && ( blendDstBits == GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ) )
  1961. {
  1962. pStage->adjustColorsForFog = ACFF_MODULATE_ALPHA;
  1963. }
  1964. // premultiplied alpha
  1965. else if ( ( blendSrcBits == GLS_SRCBLEND_ONE ) && ( blendDstBits == GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ) )
  1966. {
  1967. pStage->adjustColorsForFog = ACFF_MODULATE_RGBA;
  1968. } else {
  1969. // we can't adjust this one correctly, so it won't be exactly correct in fog
  1970. }
  1971. // don't screw with sort order if this is a portal or environment
  1972. if ( !shader.sort ) {
  1973. // see through item, like a grill or grate
  1974. if ( pStage->stateBits & GLS_DEPTHMASK_TRUE ) {
  1975. shader.sort = SS_SEE_THROUGH;
  1976. } else {
  1977. shader.sort = SS_BLEND0;
  1978. }
  1979. }
  1980. }
  1981. }
  1982. // there are times when you will need to manually apply a sort to
  1983. // opaque alpha tested shaders that have later blend passes
  1984. if ( !shader.sort ) {
  1985. shader.sort = SS_OPAQUE;
  1986. }
  1987. //
  1988. // if we are in r_vertexLight mode, never use a lightmap texture
  1989. //
  1990. if ( stage > 1 && ( (r_vertexLight->integer && !r_uiFullScreen->integer) || glConfig.hardwareType == GLHW_PERMEDIA2 ) ) {
  1991. VertexLightingCollapse();
  1992. stage = 1;
  1993. hasLightmapStage = qfalse;
  1994. }
  1995. //
  1996. // look for multitexture potential
  1997. //
  1998. if ( stage > 1 && CollapseMultitexture() ) {
  1999. stage--;
  2000. }
  2001. if ( shader.lightmapIndex >= 0 && !hasLightmapStage ) {
  2002. if (vertexLightmap) {
  2003. ri.Printf( PRINT_DEVELOPER, "WARNING: shader '%s' has VERTEX forced lightmap!\n", shader.name );
  2004. } else {
  2005. ri.Printf( PRINT_DEVELOPER, "WARNING: shader '%s' has lightmap but no lightmap stage!\n", shader.name );
  2006. shader.lightmapIndex = LIGHTMAP_NONE;
  2007. }
  2008. }
  2009. //
  2010. // compute number of passes
  2011. //
  2012. shader.numUnfoggedPasses = stage;
  2013. // fogonly shaders don't have any normal passes
  2014. if ( stage == 0 ) {
  2015. shader.sort = SS_FOG;
  2016. }
  2017. // determine which stage iterator function is appropriate
  2018. ComputeStageIteratorFunc();
  2019. return GeneratePermanentShader();
  2020. }
  2021. //========================================================================================
  2022. /*
  2023. ====================
  2024. FindShaderInShaderText
  2025. Scans the combined text description of all the shader files for
  2026. the given shader name.
  2027. return NULL if not found
  2028. If found, it will return a valid shader
  2029. =====================
  2030. */
  2031. static char *FindShaderInShaderText( const char *shadername ) {
  2032. char *token, *p;
  2033. int i, hash;
  2034. hash = generateHashValue(shadername, MAX_SHADERTEXT_HASH);
  2035. for (i = 0; shaderTextHashTable[hash][i]; i++) {
  2036. p = shaderTextHashTable[hash][i];
  2037. token = COM_ParseExt(&p, qtrue);
  2038. if ( !Q_stricmp( token, shadername ) ) {
  2039. return p;
  2040. }
  2041. }
  2042. p = s_shaderText;
  2043. if ( !p ) {
  2044. return NULL;
  2045. }
  2046. // look for label
  2047. while ( 1 ) {
  2048. token = COM_ParseExt( &p, qtrue );
  2049. if ( token[0] == 0 ) {
  2050. break;
  2051. }
  2052. if ( !Q_stricmp( token, shadername ) ) {
  2053. return p;
  2054. }
  2055. else {
  2056. // skip the definition
  2057. SkipBracedSection( &p );
  2058. }
  2059. }
  2060. return NULL;
  2061. }
  2062. /*
  2063. ==================
  2064. R_FindShaderByName
  2065. Will always return a valid shader, but it might be the
  2066. default shader if the real one can't be found.
  2067. ==================
  2068. */
  2069. shader_t *R_FindShaderByName( const char *name ) {
  2070. char strippedName[MAX_QPATH];
  2071. int hash;
  2072. shader_t *sh;
  2073. if ( (name==NULL) || (name[0] == 0) ) { // bk001205
  2074. return tr.defaultShader;
  2075. }
  2076. COM_StripExtension( name, strippedName );
  2077. hash = generateHashValue(strippedName, FILE_HASH_SIZE);
  2078. //
  2079. // see if the shader is already loaded
  2080. //
  2081. for (sh=hashTable[hash]; sh; sh=sh->next) {
  2082. // NOTE: if there was no shader or image available with the name strippedName
  2083. // then a default shader is created with lightmapIndex == LIGHTMAP_NONE, so we
  2084. // have to check all default shaders otherwise for every call to R_FindShader
  2085. // with that same strippedName a new default shader is created.
  2086. if (Q_stricmp(sh->name, strippedName) == 0) {
  2087. // match found
  2088. return sh;
  2089. }
  2090. }
  2091. return tr.defaultShader;
  2092. }
  2093. /*
  2094. ===============
  2095. R_FindShader
  2096. Will always return a valid shader, but it might be the
  2097. default shader if the real one can't be found.
  2098. In the interest of not requiring an explicit shader text entry to
  2099. be defined for every single image used in the game, three default
  2100. shader behaviors can be auto-created for any image:
  2101. If lightmapIndex == LIGHTMAP_NONE, then the image will have
  2102. dynamic diffuse lighting applied to it, as apropriate for most
  2103. entity skin surfaces.
  2104. If lightmapIndex == LIGHTMAP_2D, then the image will be used
  2105. for 2D rendering unless an explicit shader is found
  2106. If lightmapIndex == LIGHTMAP_BY_VERTEX, then the image will use
  2107. the vertex rgba modulate values, as apropriate for misc_model
  2108. pre-lit surfaces.
  2109. Other lightmapIndex values will have a lightmap stage created
  2110. and src*dest blending applied with the texture, as apropriate for
  2111. most world construction surfaces.
  2112. ===============
  2113. */
  2114. shader_t *R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImage ) {
  2115. char strippedName[MAX_QPATH];
  2116. char fileName[MAX_QPATH];
  2117. int i, hash;
  2118. char *shaderText;
  2119. image_t *image;
  2120. shader_t *sh;
  2121. if ( name[0] == 0 ) {
  2122. return tr.defaultShader;
  2123. }
  2124. // use (fullbright) vertex lighting if the bsp file doesn't have
  2125. // lightmaps
  2126. if ( lightmapIndex >= 0 && lightmapIndex >= tr.numLightmaps ) {
  2127. lightmapIndex = LIGHTMAP_BY_VERTEX;
  2128. }
  2129. COM_StripExtension( name, strippedName );
  2130. hash = generateHashValue(strippedName, FILE_HASH_SIZE);
  2131. //
  2132. // see if the shader is already loaded
  2133. //
  2134. for (sh = hashTable[hash]; sh; sh = sh->next) {
  2135. // NOTE: if there was no shader or image available with the name strippedName
  2136. // then a default shader is created with lightmapIndex == LIGHTMAP_NONE, so we
  2137. // have to check all default shaders otherwise for every call to R_FindShader
  2138. // with that same strippedName a new default shader is created.
  2139. if ( (sh->lightmapIndex == lightmapIndex || sh->defaultShader) &&
  2140. !Q_stricmp(sh->name, strippedName)) {
  2141. // match found
  2142. return sh;
  2143. }
  2144. }
  2145. // make sure the render thread is stopped, because we are probably
  2146. // going to have to upload an image
  2147. if (r_smp->integer) {
  2148. R_SyncRenderThread();
  2149. }
  2150. // clear the global shader
  2151. Com_Memset( &shader, 0, sizeof( shader ) );
  2152. Com_Memset( &stages, 0, sizeof( stages ) );
  2153. Q_strncpyz(shader.name, strippedName, sizeof(shader.name));
  2154. shader.lightmapIndex = lightmapIndex;
  2155. for ( i = 0 ; i < MAX_SHADER_STAGES ; i++ ) {
  2156. stages[i].bundle[0].texMods = texMods[i];
  2157. }
  2158. // FIXME: set these "need" values apropriately
  2159. shader.needsNormal = qtrue;
  2160. shader.needsST1 = qtrue;
  2161. shader.needsST2 = qtrue;
  2162. shader.needsColor = qtrue;
  2163. //
  2164. // attempt to define shader from an explicit parameter file
  2165. //
  2166. shaderText = FindShaderInShaderText( strippedName );
  2167. if ( shaderText ) {
  2168. // enable this when building a pak file to get a global list
  2169. // of all explicit shaders
  2170. if ( r_printShaders->integer ) {
  2171. ri.Printf( PRINT_ALL, "*SHADER* %s\n", name );
  2172. }
  2173. if ( !ParseShader( &shaderText ) ) {
  2174. // had errors, so use default shader
  2175. shader.defaultShader = qtrue;
  2176. }
  2177. sh = FinishShader();
  2178. return sh;
  2179. }
  2180. //
  2181. // if not defined in the in-memory shader descriptions,
  2182. // look for a single TGA, BMP, or PCX
  2183. //
  2184. Q_strncpyz( fileName, name, sizeof( fileName ) );
  2185. COM_DefaultExtension( fileName, sizeof( fileName ), ".tga" );
  2186. image = R_FindImageFile( fileName, mipRawImage, mipRawImage, mipRawImage ? GL_REPEAT : GL_CLAMP );
  2187. if ( !image ) {
  2188. ri.Printf( PRINT_DEVELOPER, "Couldn't find image for shader %s\n", name );
  2189. shader.defaultShader = qtrue;
  2190. return FinishShader();
  2191. }
  2192. //
  2193. // create the default shading commands
  2194. //
  2195. if ( shader.lightmapIndex == LIGHTMAP_NONE ) {
  2196. // dynamic colors at vertexes
  2197. stages[0].bundle[0].image[0] = image;
  2198. stages[0].active = qtrue;
  2199. stages[0].rgbGen = CGEN_LIGHTING_DIFFUSE;
  2200. stages[0].stateBits = GLS_DEFAULT;
  2201. } else if ( shader.lightmapIndex == LIGHTMAP_BY_VERTEX ) {
  2202. // explicit colors at vertexes
  2203. stages[0].bundle[0].image[0] = image;
  2204. stages[0].active = qtrue;
  2205. stages[0].rgbGen = CGEN_EXACT_VERTEX;
  2206. stages[0].alphaGen = AGEN_SKIP;
  2207. stages[0].stateBits = GLS_DEFAULT;
  2208. } else if ( shader.lightmapIndex == LIGHTMAP_2D ) {
  2209. // GUI elements
  2210. stages[0].bundle[0].image[0] = image;
  2211. stages[0].active = qtrue;
  2212. stages[0].rgbGen = CGEN_VERTEX;
  2213. stages[0].alphaGen = AGEN_VERTEX;
  2214. stages[0].stateBits = GLS_DEPTHTEST_DISABLE |
  2215. GLS_SRCBLEND_SRC_ALPHA |
  2216. GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA;
  2217. } else if ( shader.lightmapIndex == LIGHTMAP_WHITEIMAGE ) {
  2218. // fullbright level
  2219. stages[0].bundle[0].image[0] = tr.whiteImage;
  2220. stages[0].active = qtrue;
  2221. stages[0].rgbGen = CGEN_IDENTITY_LIGHTING;
  2222. stages[0].stateBits = GLS_DEFAULT;
  2223. stages[1].bundle[0].image[0] = image;
  2224. stages[1].active = qtrue;
  2225. stages[1].rgbGen = CGEN_IDENTITY;
  2226. stages[1].stateBits |= GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO;
  2227. } else {
  2228. // two pass lightmap
  2229. stages[0].bundle[0].image[0] = tr.lightmaps[shader.lightmapIndex];
  2230. stages[0].bundle[0].isLightmap = qtrue;
  2231. stages[0].active = qtrue;
  2232. stages[0].rgbGen = CGEN_IDENTITY; // lightmaps are scaled on creation
  2233. // for identitylight
  2234. stages[0].stateBits = GLS_DEFAULT;
  2235. stages[1].bundle[0].image[0] = image;
  2236. stages[1].active = qtrue;
  2237. stages[1].rgbGen = CGEN_IDENTITY;
  2238. stages[1].stateBits |= GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO;
  2239. }
  2240. return FinishShader();
  2241. }
  2242. qhandle_t RE_RegisterShaderFromImage(const char *name, int lightmapIndex, image_t *image, qboolean mipRawImage) {
  2243. int i, hash;
  2244. shader_t *sh;
  2245. hash = generateHashValue(name, FILE_HASH_SIZE);
  2246. //
  2247. // see if the shader is already loaded
  2248. //
  2249. for (sh=hashTable[hash]; sh; sh=sh->next) {
  2250. // NOTE: if there was no shader or image available with the name strippedName
  2251. // then a default shader is created with lightmapIndex == LIGHTMAP_NONE, so we
  2252. // have to check all default shaders otherwise for every call to R_FindShader
  2253. // with that same strippedName a new default shader is created.
  2254. if ( (sh->lightmapIndex == lightmapIndex || sh->defaultShader) &&
  2255. // index by name
  2256. !Q_stricmp(sh->name, name)) {
  2257. // match found
  2258. return sh->index;
  2259. }
  2260. }
  2261. // make sure the render thread is stopped, because we are probably
  2262. // going to have to upload an image
  2263. if (r_smp->integer) {
  2264. R_SyncRenderThread();
  2265. }
  2266. // clear the global shader
  2267. Com_Memset( &shader, 0, sizeof( shader ) );
  2268. Com_Memset( &stages, 0, sizeof( stages ) );
  2269. Q_strncpyz(shader.name, name, sizeof(shader.name));
  2270. shader.lightmapIndex = lightmapIndex;
  2271. for ( i = 0 ; i < MAX_SHADER_STAGES ; i++ ) {
  2272. stages[i].bundle[0].texMods = texMods[i];
  2273. }
  2274. // FIXME: set these "need" values apropriately
  2275. shader.needsNormal = qtrue;
  2276. shader.needsST1 = qtrue;
  2277. shader.needsST2 = qtrue;
  2278. shader.needsColor = qtrue;
  2279. //
  2280. // create the default shading commands
  2281. //
  2282. if ( shader.lightmapIndex == LIGHTMAP_NONE ) {
  2283. // dynamic colors at vertexes
  2284. stages[0].bundle[0].image[0] = image;
  2285. stages[0].active = qtrue;
  2286. stages[0].rgbGen = CGEN_LIGHTING_DIFFUSE;
  2287. stages[0].stateBits = GLS_DEFAULT;
  2288. } else if ( shader.lightmapIndex == LIGHTMAP_BY_VERTEX ) {
  2289. // explicit colors at vertexes
  2290. stages[0].bundle[0].image[0] = image;
  2291. stages[0].active = qtrue;
  2292. stages[0].rgbGen = CGEN_EXACT_VERTEX;
  2293. stages[0].alphaGen = AGEN_SKIP;
  2294. stages[0].stateBits = GLS_DEFAULT;
  2295. } else if ( shader.lightmapIndex == LIGHTMAP_2D ) {
  2296. // GUI elements
  2297. stages[0].bundle[0].image[0] = image;
  2298. stages[0].active = qtrue;
  2299. stages[0].rgbGen = CGEN_VERTEX;
  2300. stages[0].alphaGen = AGEN_VERTEX;
  2301. stages[0].stateBits = GLS_DEPTHTEST_DISABLE |
  2302. GLS_SRCBLEND_SRC_ALPHA |
  2303. GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA;
  2304. } else if ( shader.lightmapIndex == LIGHTMAP_WHITEIMAGE ) {
  2305. // fullbright level
  2306. stages[0].bundle[0].image[0] = tr.whiteImage;
  2307. stages[0].active = qtrue;
  2308. stages[0].rgbGen = CGEN_IDENTITY_LIGHTING;
  2309. stages[0].stateBits = GLS_DEFAULT;
  2310. stages[1].bundle[0].image[0] = image;
  2311. stages[1].active = qtrue;
  2312. stages[1].rgbGen = CGEN_IDENTITY;
  2313. stages[1].stateBits |= GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO;
  2314. } else {
  2315. // two pass lightmap
  2316. stages[0].bundle[0].image[0] = tr.lightmaps[shader.lightmapIndex];
  2317. stages[0].bundle[0].isLightmap = qtrue;
  2318. stages[0].active = qtrue;
  2319. stages[0].rgbGen = CGEN_IDENTITY; // lightmaps are scaled on creation
  2320. // for identitylight
  2321. stages[0].stateBits = GLS_DEFAULT;
  2322. stages[1].bundle[0].image[0] = image;
  2323. stages[1].active = qtrue;
  2324. stages[1].rgbGen = CGEN_IDENTITY;
  2325. stages[1].stateBits |= GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO;
  2326. }
  2327. sh = FinishShader();
  2328. return sh->index;
  2329. }
  2330. /*
  2331. ====================
  2332. RE_RegisterShader
  2333. This is the exported shader entry point for the rest of the system
  2334. It will always return an index that will be valid.
  2335. This should really only be used for explicit shaders, because there is no
  2336. way to ask for different implicit lighting modes (vertex, lightmap, etc)
  2337. ====================
  2338. */
  2339. qhandle_t RE_RegisterShaderLightMap( const char *name, int lightmapIndex ) {
  2340. shader_t *sh;
  2341. if ( strlen( name ) >= MAX_QPATH ) {
  2342. Com_Printf( "Shader name exceeds MAX_QPATH\n" );
  2343. return 0;
  2344. }
  2345. sh = R_FindShader( name, lightmapIndex, qtrue );
  2346. // we want to return 0 if the shader failed to
  2347. // load for some reason, but R_FindShader should
  2348. // still keep a name allocated for it, so if
  2349. // something calls RE_RegisterShader again with
  2350. // the same name, we don't try looking for it again
  2351. if ( sh->defaultShader ) {
  2352. return 0;
  2353. }
  2354. return sh->index;
  2355. }
  2356. /*
  2357. ====================
  2358. RE_RegisterShader
  2359. This is the exported shader entry point for the rest of the system
  2360. It will always return an index that will be valid.
  2361. This should really only be used for explicit shaders, because there is no
  2362. way to ask for different implicit lighting modes (vertex, lightmap, etc)
  2363. ====================
  2364. */
  2365. qhandle_t RE_RegisterShader( const char *name ) {
  2366. shader_t *sh;
  2367. if ( strlen( name ) >= MAX_QPATH ) {
  2368. Com_Printf( "Shader name exceeds MAX_QPATH\n" );
  2369. return 0;
  2370. }
  2371. sh = R_FindShader( name, LIGHTMAP_2D, qtrue );
  2372. // we want to return 0 if the shader failed to
  2373. // load for some reason, but R_FindShader should
  2374. // still keep a name allocated for it, so if
  2375. // something calls RE_RegisterShader again with
  2376. // the same name, we don't try looking for it again
  2377. if ( sh->defaultShader ) {
  2378. return 0;
  2379. }
  2380. return sh->index;
  2381. }
  2382. /*
  2383. ====================
  2384. RE_RegisterShaderNoMip
  2385. For menu graphics that should never be picmiped
  2386. ====================
  2387. */
  2388. qhandle_t RE_RegisterShaderNoMip( const char *name ) {
  2389. shader_t *sh;
  2390. if ( strlen( name ) >= MAX_QPATH ) {
  2391. Com_Printf( "Shader name exceeds MAX_QPATH\n" );
  2392. return 0;
  2393. }
  2394. sh = R_FindShader( name, LIGHTMAP_2D, qfalse );
  2395. // we want to return 0 if the shader failed to
  2396. // load for some reason, but R_FindShader should
  2397. // still keep a name allocated for it, so if
  2398. // something calls RE_RegisterShader again with
  2399. // the same name, we don't try looking for it again
  2400. if ( sh->defaultShader ) {
  2401. return 0;
  2402. }
  2403. return sh->index;
  2404. }
  2405. /*
  2406. ====================
  2407. R_GetShaderByHandle
  2408. When a handle is passed in by another module, this range checks
  2409. it and returns a valid (possibly default) shader_t to be used internally.
  2410. ====================
  2411. */
  2412. shader_t *R_GetShaderByHandle( qhandle_t hShader ) {
  2413. if ( hShader < 0 ) {
  2414. ri.Printf( PRINT_WARNING, "R_GetShaderByHandle: out of range hShader '%d'\n", hShader ); // bk: FIXME name
  2415. return tr.defaultShader;
  2416. }
  2417. if ( hShader >= tr.numShaders ) {
  2418. ri.Printf( PRINT_WARNING, "R_GetShaderByHandle: out of range hShader '%d'\n", hShader );
  2419. return tr.defaultShader;
  2420. }
  2421. return tr.shaders[hShader];
  2422. }
  2423. /*
  2424. ===============
  2425. R_ShaderList_f
  2426. Dump information on all valid shaders to the console
  2427. A second parameter will cause it to print in sorted order
  2428. ===============
  2429. */
  2430. void R_ShaderList_f (void) {
  2431. int i;
  2432. int count;
  2433. shader_t *shader;
  2434. ri.Printf (PRINT_ALL, "-----------------------\n");
  2435. count = 0;
  2436. for ( i = 0 ; i < tr.numShaders ; i++ ) {
  2437. if ( ri.Cmd_Argc() > 1 ) {
  2438. shader = tr.sortedShaders[i];
  2439. } else {
  2440. shader = tr.shaders[i];
  2441. }
  2442. ri.Printf( PRINT_ALL, "%i ", shader->numUnfoggedPasses );
  2443. if (shader->lightmapIndex >= 0 ) {
  2444. ri.Printf (PRINT_ALL, "L ");
  2445. } else {
  2446. ri.Printf (PRINT_ALL, " ");
  2447. }
  2448. if ( shader->multitextureEnv == GL_ADD ) {
  2449. ri.Printf( PRINT_ALL, "MT(a) " );
  2450. } else if ( shader->multitextureEnv == GL_MODULATE ) {
  2451. ri.Printf( PRINT_ALL, "MT(m) " );
  2452. } else if ( shader->multitextureEnv == GL_DECAL ) {
  2453. ri.Printf( PRINT_ALL, "MT(d) " );
  2454. } else {
  2455. ri.Printf( PRINT_ALL, " " );
  2456. }
  2457. if ( shader->explicitlyDefined ) {
  2458. ri.Printf( PRINT_ALL, "E " );
  2459. } else {
  2460. ri.Printf( PRINT_ALL, " " );
  2461. }
  2462. if ( shader->optimalStageIteratorFunc == RB_StageIteratorGeneric ) {
  2463. ri.Printf( PRINT_ALL, "gen " );
  2464. } else if ( shader->optimalStageIteratorFunc == RB_StageIteratorSky ) {
  2465. ri.Printf( PRINT_ALL, "sky " );
  2466. } else if ( shader->optimalStageIteratorFunc == RB_StageIteratorLightmappedMultitexture ) {
  2467. ri.Printf( PRINT_ALL, "lmmt" );
  2468. } else if ( shader->optimalStageIteratorFunc == RB_StageIteratorVertexLitTexture ) {
  2469. ri.Printf( PRINT_ALL, "vlt " );
  2470. } else {
  2471. ri.Printf( PRINT_ALL, " " );
  2472. }
  2473. if ( shader->defaultShader ) {
  2474. ri.Printf (PRINT_ALL, ": %s (DEFAULTED)\n", shader->name);
  2475. } else {
  2476. ri.Printf (PRINT_ALL, ": %s\n", shader->name);
  2477. }
  2478. count++;
  2479. }
  2480. ri.Printf (PRINT_ALL, "%i total shaders\n", count);
  2481. ri.Printf (PRINT_ALL, "------------------\n");
  2482. }
  2483. /*
  2484. ====================
  2485. ScanAndLoadShaderFiles
  2486. Finds and loads all .shader files, combining them into
  2487. a single large text block that can be scanned for shader names
  2488. =====================
  2489. */
  2490. #define MAX_SHADER_FILES 4096
  2491. static void ScanAndLoadShaderFiles( void )
  2492. {
  2493. char **shaderFiles;
  2494. char *buffers[MAX_SHADER_FILES];
  2495. char *p;
  2496. int numShaders;
  2497. int i;
  2498. char *oldp, *token, *hashMem;
  2499. int shaderTextHashTableSizes[MAX_SHADERTEXT_HASH], hash, size;
  2500. long sum = 0;
  2501. // scan for shader files
  2502. shaderFiles = ri.FS_ListFiles( "scripts", ".shader", &numShaders );
  2503. if ( !shaderFiles || !numShaders )
  2504. {
  2505. ri.Printf( PRINT_WARNING, "WARNING: no shader files found\n" );
  2506. return;
  2507. }
  2508. if ( numShaders > MAX_SHADER_FILES ) {
  2509. numShaders = MAX_SHADER_FILES;
  2510. }
  2511. // load and parse shader files
  2512. for ( i = 0; i < numShaders; i++ )
  2513. {
  2514. char filename[MAX_QPATH];
  2515. Com_sprintf( filename, sizeof( filename ), "scripts/%s", shaderFiles[i] );
  2516. ri.Printf( PRINT_ALL, "...loading '%s'\n", filename );
  2517. sum += ri.FS_ReadFile( filename, (void **)&buffers[i] );
  2518. if ( !buffers[i] ) {
  2519. ri.Error( ERR_DROP, "Couldn't load %s", filename );
  2520. }
  2521. }
  2522. // build single large buffer
  2523. s_shaderText = ri.Hunk_Alloc( sum + numShaders*2, h_low );
  2524. // free in reverse order, so the temp files are all dumped
  2525. for ( i = numShaders - 1; i >= 0 ; i-- ) {
  2526. strcat( s_shaderText, "\n" );
  2527. p = &s_shaderText[strlen(s_shaderText)];
  2528. strcat( s_shaderText, buffers[i] );
  2529. ri.FS_FreeFile( buffers[i] );
  2530. buffers[i] = p;
  2531. COM_Compress(p);
  2532. }
  2533. // free up memory
  2534. ri.FS_FreeFileList( shaderFiles );
  2535. Com_Memset(shaderTextHashTableSizes, 0, sizeof(shaderTextHashTableSizes));
  2536. size = 0;
  2537. //
  2538. for ( i = 0; i < numShaders; i++ ) {
  2539. // pointer to the first shader file
  2540. p = buffers[i];
  2541. // look for label
  2542. while ( 1 ) {
  2543. token = COM_ParseExt( &p, qtrue );
  2544. if ( token[0] == 0 ) {
  2545. break;
  2546. }
  2547. hash = generateHashValue(token, MAX_SHADERTEXT_HASH);
  2548. shaderTextHashTableSizes[hash]++;
  2549. size++;
  2550. SkipBracedSection(&p);
  2551. // if we passed the pointer to the next shader file
  2552. if ( i < numShaders - 1 ) {
  2553. if ( p > buffers[i+1] ) {
  2554. break;
  2555. }
  2556. }
  2557. }
  2558. }
  2559. size += MAX_SHADERTEXT_HASH;
  2560. hashMem = ri.Hunk_Alloc( size * sizeof(char *), h_low );
  2561. for (i = 0; i < MAX_SHADERTEXT_HASH; i++) {
  2562. shaderTextHashTable[i] = (char **) hashMem;
  2563. hashMem = ((char *) hashMem) + ((shaderTextHashTableSizes[i] + 1) * sizeof(char *));
  2564. }
  2565. Com_Memset(shaderTextHashTableSizes, 0, sizeof(shaderTextHashTableSizes));
  2566. //
  2567. for ( i = 0; i < numShaders; i++ ) {
  2568. // pointer to the first shader file
  2569. p = buffers[i];
  2570. // look for label
  2571. while ( 1 ) {
  2572. oldp = p;
  2573. token = COM_ParseExt( &p, qtrue );
  2574. if ( token[0] == 0 ) {
  2575. break;
  2576. }
  2577. hash = generateHashValue(token, MAX_SHADERTEXT_HASH);
  2578. shaderTextHashTable[hash][shaderTextHashTableSizes[hash]++] = oldp;
  2579. SkipBracedSection(&p);
  2580. // if we passed the pointer to the next shader file
  2581. if ( i < numShaders - 1 ) {
  2582. if ( p > buffers[i+1] ) {
  2583. break;
  2584. }
  2585. }
  2586. }
  2587. }
  2588. return;
  2589. }
  2590. /*
  2591. ====================
  2592. CreateInternalShaders
  2593. ====================
  2594. */
  2595. static void CreateInternalShaders( void ) {
  2596. tr.numShaders = 0;
  2597. // init the default shader
  2598. Com_Memset( &shader, 0, sizeof( shader ) );
  2599. Com_Memset( &stages, 0, sizeof( stages ) );
  2600. Q_strncpyz( shader.name, "<default>", sizeof( shader.name ) );
  2601. shader.lightmapIndex = LIGHTMAP_NONE;
  2602. stages[0].bundle[0].image[0] = tr.defaultImage;
  2603. stages[0].active = qtrue;
  2604. stages[0].stateBits = GLS_DEFAULT;
  2605. tr.defaultShader = FinishShader();
  2606. // shadow shader is just a marker
  2607. Q_strncpyz( shader.name, "<stencil shadow>", sizeof( shader.name ) );
  2608. shader.sort = SS_STENCIL_SHADOW;
  2609. tr.shadowShader = FinishShader();
  2610. }
  2611. static void CreateExternalShaders( void ) {
  2612. tr.projectionShadowShader = R_FindShader( "projectionShadow", LIGHTMAP_NONE, qtrue );
  2613. tr.flareShader = R_FindShader( "flareShader", LIGHTMAP_NONE, qtrue );
  2614. tr.sunShader = R_FindShader( "sun", LIGHTMAP_NONE, qtrue );
  2615. }
  2616. /*
  2617. ==================
  2618. R_InitShaders
  2619. ==================
  2620. */
  2621. void R_InitShaders( void ) {
  2622. ri.Printf( PRINT_ALL, "Initializing Shaders\n" );
  2623. Com_Memset(hashTable, 0, sizeof(hashTable));
  2624. deferLoad = qfalse;
  2625. CreateInternalShaders();
  2626. ScanAndLoadShaderFiles();
  2627. CreateExternalShaders();
  2628. }