Material.cpp 74 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "../idlib/precompiled.h"
  21. #pragma hdrstop
  22. #include "tr_local.h"
  23. /*
  24. Any errors during parsing just set MF_DEFAULTED and return, rather than throwing
  25. a hard error. This will cause the material to fall back to default material,
  26. but otherwise let things continue.
  27. Each material may have a set of calculations that must be evaluated before
  28. drawing with it.
  29. Every expression that a material uses can be evaluated at one time, which
  30. will allow for perfect common subexpression removal when I get around to
  31. writing it.
  32. Without this, scrolling an entire surface could result in evaluating the
  33. same texture matrix calculations a half dozen times.
  34. Open question: should I allow arbitrary per-vertex color, texCoord, and vertex
  35. calculations to be specified in the material code?
  36. Every stage will definately have a valid image pointer.
  37. We might want the ability to change the sort value based on conditionals,
  38. but it could be a hassle to implement,
  39. */
  40. // keep all of these on the stack, when they are static it makes material parsing non-reentrant
  41. typedef struct mtrParsingData_s {
  42. bool registerIsTemporary[MAX_EXPRESSION_REGISTERS];
  43. float shaderRegisters[MAX_EXPRESSION_REGISTERS];
  44. expOp_t shaderOps[MAX_EXPRESSION_OPS];
  45. shaderStage_t parseStages[MAX_SHADER_STAGES];
  46. bool registersAreConstant;
  47. bool forceOverlays;
  48. } mtrParsingData_t;
  49. /*
  50. =============
  51. idMaterial::CommonInit
  52. =============
  53. */
  54. void idMaterial::CommonInit() {
  55. desc = "<none>";
  56. renderBump = "";
  57. contentFlags = CONTENTS_SOLID;
  58. surfaceFlags = SURFTYPE_NONE;
  59. materialFlags = 0;
  60. sort = SS_BAD;
  61. coverage = MC_BAD;
  62. cullType = CT_FRONT_SIDED;
  63. deform = DFRM_NONE;
  64. numOps = 0;
  65. ops = NULL;
  66. numRegisters = 0;
  67. expressionRegisters = NULL;
  68. constantRegisters = NULL;
  69. numStages = 0;
  70. numAmbientStages = 0;
  71. stages = NULL;
  72. editorImage = NULL;
  73. lightFalloffImage = NULL;
  74. shouldCreateBackSides = false;
  75. entityGui = 0;
  76. fogLight = false;
  77. blendLight = false;
  78. ambientLight = false;
  79. noFog = false;
  80. hasSubview = false;
  81. allowOverlays = true;
  82. unsmoothedTangents = false;
  83. gui = NULL;
  84. memset( deformRegisters, 0, sizeof( deformRegisters ) );
  85. editorAlpha = 1.0;
  86. spectrum = 0;
  87. polygonOffset = 0;
  88. suppressInSubview = false;
  89. refCount = 0;
  90. portalSky = false;
  91. decalInfo.stayTime = 10000;
  92. decalInfo.fadeTime = 4000;
  93. decalInfo.start[0] = 1;
  94. decalInfo.start[1] = 1;
  95. decalInfo.start[2] = 1;
  96. decalInfo.start[3] = 1;
  97. decalInfo.end[0] = 0;
  98. decalInfo.end[1] = 0;
  99. decalInfo.end[2] = 0;
  100. decalInfo.end[3] = 0;
  101. }
  102. /*
  103. =============
  104. idMaterial::idMaterial
  105. =============
  106. */
  107. idMaterial::idMaterial() {
  108. CommonInit();
  109. // we put this here instead of in CommonInit, because
  110. // we don't want it cleared when a material is purged
  111. surfaceArea = 0;
  112. }
  113. /*
  114. =============
  115. idMaterial::~idMaterial
  116. =============
  117. */
  118. idMaterial::~idMaterial() {
  119. }
  120. /*
  121. ===============
  122. idMaterial::FreeData
  123. ===============
  124. */
  125. void idMaterial::FreeData() {
  126. int i;
  127. if ( stages ) {
  128. // delete any idCinematic textures
  129. for ( i = 0; i < numStages; i++ ) {
  130. if ( stages[i].texture.cinematic != NULL ) {
  131. delete stages[i].texture.cinematic;
  132. stages[i].texture.cinematic = NULL;
  133. }
  134. if ( stages[i].newStage != NULL ) {
  135. Mem_Free( stages[i].newStage );
  136. stages[i].newStage = NULL;
  137. }
  138. }
  139. R_StaticFree( stages );
  140. stages = NULL;
  141. }
  142. if ( expressionRegisters != NULL ) {
  143. R_StaticFree( expressionRegisters );
  144. expressionRegisters = NULL;
  145. }
  146. if ( constantRegisters != NULL ) {
  147. R_StaticFree( constantRegisters );
  148. constantRegisters = NULL;
  149. }
  150. if ( ops != NULL ) {
  151. R_StaticFree( ops );
  152. ops = NULL;
  153. }
  154. }
  155. /*
  156. ==============
  157. idMaterial::GetEditorImage
  158. ==============
  159. */
  160. idImage *idMaterial::GetEditorImage( void ) const {
  161. if ( editorImage ) {
  162. return editorImage;
  163. }
  164. // if we don't have an editorImageName, use the first stage image
  165. if ( !editorImageName.Length()) {
  166. // _D3XP :: First check for a diffuse image, then use the first
  167. if ( numStages && stages ) {
  168. int i;
  169. for( i = 0; i < numStages; i++ ) {
  170. if ( stages[i].lighting == SL_DIFFUSE ) {
  171. editorImage = stages[i].texture.image;
  172. break;
  173. }
  174. }
  175. if ( !editorImage ) {
  176. editorImage = stages[0].texture.image;
  177. }
  178. } else {
  179. editorImage = globalImages->defaultImage;
  180. }
  181. } else {
  182. // look for an explicit one
  183. editorImage = globalImages->ImageFromFile( editorImageName, TF_DEFAULT, true, TR_REPEAT, TD_DEFAULT );
  184. }
  185. if ( !editorImage ) {
  186. editorImage = globalImages->defaultImage;
  187. }
  188. return editorImage;
  189. }
  190. // info parms
  191. typedef struct {
  192. char *name;
  193. int clearSolid, surfaceFlags, contents;
  194. } infoParm_t;
  195. static infoParm_t infoParms[] = {
  196. // game relevant attributes
  197. {"solid", 0, 0, CONTENTS_SOLID }, // may need to override a clearSolid
  198. {"water", 1, 0, CONTENTS_WATER }, // used for water
  199. {"playerclip", 0, 0, CONTENTS_PLAYERCLIP }, // solid to players
  200. {"monsterclip", 0, 0, CONTENTS_MONSTERCLIP }, // solid to monsters
  201. {"moveableclip",0, 0, CONTENTS_MOVEABLECLIP },// solid to moveable entities
  202. {"ikclip", 0, 0, CONTENTS_IKCLIP }, // solid to IK
  203. {"blood", 0, 0, CONTENTS_BLOOD }, // used to detect blood decals
  204. {"trigger", 0, 0, CONTENTS_TRIGGER }, // used for triggers
  205. {"aassolid", 0, 0, CONTENTS_AAS_SOLID }, // solid for AAS
  206. {"aasobstacle", 0, 0, CONTENTS_AAS_OBSTACLE },// used to compile an obstacle into AAS that can be enabled/disabled
  207. {"flashlight_trigger", 0, 0, CONTENTS_FLASHLIGHT_TRIGGER }, // used for triggers that are activated by the flashlight
  208. {"nonsolid", 1, 0, 0 }, // clears the solid flag
  209. {"nullNormal", 0, SURF_NULLNORMAL,0 }, // renderbump will draw as 0x80 0x80 0x80
  210. // utility relevant attributes
  211. {"areaportal", 1, 0, CONTENTS_AREAPORTAL }, // divides areas
  212. {"qer_nocarve", 1, 0, CONTENTS_NOCSG}, // don't cut brushes in editor
  213. {"discrete", 1, SURF_DISCRETE, 0 }, // surfaces should not be automatically merged together or
  214. // clipped to the world,
  215. // because they represent discrete objects like gui shaders
  216. // mirrors, or autosprites
  217. {"noFragment", 0, SURF_NOFRAGMENT, 0 },
  218. {"slick", 0, SURF_SLICK, 0 },
  219. {"collision", 0, SURF_COLLISION, 0 },
  220. {"noimpact", 0, SURF_NOIMPACT, 0 }, // don't make impact explosions or marks
  221. {"nodamage", 0, SURF_NODAMAGE, 0 }, // no falling damage when hitting
  222. {"ladder", 0, SURF_LADDER, 0 }, // climbable
  223. {"nosteps", 0, SURF_NOSTEPS, 0 }, // no footsteps
  224. // material types for particle, sound, footstep feedback
  225. {"metal", 0, SURFTYPE_METAL, 0 }, // metal
  226. {"stone", 0, SURFTYPE_STONE, 0 }, // stone
  227. {"flesh", 0, SURFTYPE_FLESH, 0 }, // flesh
  228. {"wood", 0, SURFTYPE_WOOD, 0 }, // wood
  229. {"cardboard", 0, SURFTYPE_CARDBOARD, 0 }, // cardboard
  230. {"liquid", 0, SURFTYPE_LIQUID, 0 }, // liquid
  231. {"glass", 0, SURFTYPE_GLASS, 0 }, // glass
  232. {"plastic", 0, SURFTYPE_PLASTIC, 0 }, // plastic
  233. {"ricochet", 0, SURFTYPE_RICOCHET, 0 }, // behaves like metal but causes a ricochet sound
  234. // unassigned surface types
  235. {"surftype10", 0, SURFTYPE_10, 0 },
  236. {"surftype11", 0, SURFTYPE_11, 0 },
  237. {"surftype12", 0, SURFTYPE_12, 0 },
  238. {"surftype13", 0, SURFTYPE_13, 0 },
  239. {"surftype14", 0, SURFTYPE_14, 0 },
  240. {"surftype15", 0, SURFTYPE_15, 0 },
  241. };
  242. static const int numInfoParms = sizeof(infoParms) / sizeof (infoParms[0]);
  243. /*
  244. ===============
  245. idMaterial::CheckSurfaceParm
  246. See if the current token matches one of the surface parm bit flags
  247. ===============
  248. */
  249. bool idMaterial::CheckSurfaceParm( idToken *token ) {
  250. for ( int i = 0 ; i < numInfoParms ; i++ ) {
  251. if ( !token->Icmp( infoParms[i].name ) ) {
  252. if ( infoParms[i].surfaceFlags & SURF_TYPE_MASK ) {
  253. // ensure we only have one surface type set
  254. surfaceFlags &= ~SURF_TYPE_MASK;
  255. }
  256. surfaceFlags |= infoParms[i].surfaceFlags;
  257. contentFlags |= infoParms[i].contents;
  258. if ( infoParms[i].clearSolid ) {
  259. contentFlags &= ~CONTENTS_SOLID;
  260. }
  261. return true;
  262. }
  263. }
  264. return false;
  265. }
  266. /*
  267. ===============
  268. idMaterial::MatchToken
  269. Sets defaultShader and returns false if the next token doesn't match
  270. ===============
  271. */
  272. bool idMaterial::MatchToken( idLexer &src, const char *match ) {
  273. if ( !src.ExpectTokenString( match ) ) {
  274. SetMaterialFlag( MF_DEFAULTED );
  275. return false;
  276. }
  277. return true;
  278. }
  279. /*
  280. =================
  281. idMaterial::ParseSort
  282. =================
  283. */
  284. void idMaterial::ParseSort( idLexer &src ) {
  285. idToken token;
  286. if ( !src.ReadTokenOnLine( &token ) ) {
  287. src.Warning( "missing sort parameter" );
  288. SetMaterialFlag( MF_DEFAULTED );
  289. return;
  290. }
  291. if ( !token.Icmp( "subview" ) ) {
  292. sort = SS_SUBVIEW;
  293. } else if ( !token.Icmp( "opaque" ) ) {
  294. sort = SS_OPAQUE;
  295. }else if ( !token.Icmp( "decal" ) ) {
  296. sort = SS_DECAL;
  297. } else if ( !token.Icmp( "far" ) ) {
  298. sort = SS_FAR;
  299. } else if ( !token.Icmp( "medium" ) ) {
  300. sort = SS_MEDIUM;
  301. } else if ( !token.Icmp( "close" ) ) {
  302. sort = SS_CLOSE;
  303. } else if ( !token.Icmp( "almostNearest" ) ) {
  304. sort = SS_ALMOST_NEAREST;
  305. } else if ( !token.Icmp( "nearest" ) ) {
  306. sort = SS_NEAREST;
  307. } else if ( !token.Icmp( "postProcess" ) ) {
  308. sort = SS_POST_PROCESS;
  309. } else if ( !token.Icmp( "portalSky" ) ) {
  310. sort = SS_PORTAL_SKY;
  311. } else {
  312. sort = atof( token );
  313. }
  314. }
  315. /*
  316. =================
  317. idMaterial::ParseDecalInfo
  318. =================
  319. */
  320. void idMaterial::ParseDecalInfo( idLexer &src ) {
  321. idToken token;
  322. decalInfo.stayTime = src.ParseFloat() * 1000;
  323. decalInfo.fadeTime = src.ParseFloat() * 1000;
  324. float start[4], end[4];
  325. src.Parse1DMatrix( 4, start );
  326. src.Parse1DMatrix( 4, end );
  327. for ( int i = 0 ; i < 4 ; i++ ) {
  328. decalInfo.start[i] = start[i];
  329. decalInfo.end[i] = end[i];
  330. }
  331. }
  332. /*
  333. =============
  334. idMaterial::GetExpressionConstant
  335. =============
  336. */
  337. int idMaterial::GetExpressionConstant( float f ) {
  338. int i;
  339. for ( i = EXP_REG_NUM_PREDEFINED ; i < numRegisters ; i++ ) {
  340. if ( !pd->registerIsTemporary[i] && pd->shaderRegisters[i] == f ) {
  341. return i;
  342. }
  343. }
  344. if ( numRegisters == MAX_EXPRESSION_REGISTERS ) {
  345. common->Warning( "GetExpressionConstant: material '%s' hit MAX_EXPRESSION_REGISTERS", GetName() );
  346. SetMaterialFlag( MF_DEFAULTED );
  347. return 0;
  348. }
  349. pd->registerIsTemporary[i] = false;
  350. pd->shaderRegisters[i] = f;
  351. numRegisters++;
  352. return i;
  353. }
  354. /*
  355. =============
  356. idMaterial::GetExpressionTemporary
  357. =============
  358. */
  359. int idMaterial::GetExpressionTemporary( void ) {
  360. if ( numRegisters == MAX_EXPRESSION_REGISTERS ) {
  361. common->Warning( "GetExpressionTemporary: material '%s' hit MAX_EXPRESSION_REGISTERS", GetName() );
  362. SetMaterialFlag( MF_DEFAULTED );
  363. return 0;
  364. }
  365. pd->registerIsTemporary[numRegisters] = true;
  366. numRegisters++;
  367. return numRegisters - 1;
  368. }
  369. /*
  370. =============
  371. idMaterial::GetExpressionOp
  372. =============
  373. */
  374. expOp_t *idMaterial::GetExpressionOp( void ) {
  375. if ( numOps == MAX_EXPRESSION_OPS ) {
  376. common->Warning( "GetExpressionOp: material '%s' hit MAX_EXPRESSION_OPS", GetName() );
  377. SetMaterialFlag( MF_DEFAULTED );
  378. return &pd->shaderOps[0];
  379. }
  380. return &pd->shaderOps[numOps++];
  381. }
  382. /*
  383. =================
  384. idMaterial::EmitOp
  385. =================
  386. */
  387. int idMaterial::EmitOp( int a, int b, expOpType_t opType ) {
  388. expOp_t *op;
  389. // optimize away identity operations
  390. if ( opType == OP_TYPE_ADD ) {
  391. if ( !pd->registerIsTemporary[a] && pd->shaderRegisters[a] == 0 ) {
  392. return b;
  393. }
  394. if ( !pd->registerIsTemporary[b] && pd->shaderRegisters[b] == 0 ) {
  395. return a;
  396. }
  397. if ( !pd->registerIsTemporary[a] && !pd->registerIsTemporary[b] ) {
  398. return GetExpressionConstant( pd->shaderRegisters[a] + pd->shaderRegisters[b] );
  399. }
  400. }
  401. if ( opType == OP_TYPE_MULTIPLY ) {
  402. if ( !pd->registerIsTemporary[a] && pd->shaderRegisters[a] == 1 ) {
  403. return b;
  404. }
  405. if ( !pd->registerIsTemporary[a] && pd->shaderRegisters[a] == 0 ) {
  406. return a;
  407. }
  408. if ( !pd->registerIsTemporary[b] && pd->shaderRegisters[b] == 1 ) {
  409. return a;
  410. }
  411. if ( !pd->registerIsTemporary[b] && pd->shaderRegisters[b] == 0 ) {
  412. return b;
  413. }
  414. if ( !pd->registerIsTemporary[a] && !pd->registerIsTemporary[b] ) {
  415. return GetExpressionConstant( pd->shaderRegisters[a] * pd->shaderRegisters[b] );
  416. }
  417. }
  418. op = GetExpressionOp();
  419. op->opType = opType;
  420. op->a = a;
  421. op->b = b;
  422. op->c = GetExpressionTemporary();
  423. return op->c;
  424. }
  425. /*
  426. =================
  427. idMaterial::ParseEmitOp
  428. =================
  429. */
  430. int idMaterial::ParseEmitOp( idLexer &src, int a, expOpType_t opType, int priority ) {
  431. int b;
  432. b = ParseExpressionPriority( src, priority );
  433. return EmitOp( a, b, opType );
  434. }
  435. /*
  436. =================
  437. idMaterial::ParseTerm
  438. Returns a register index
  439. =================
  440. */
  441. int idMaterial::ParseTerm( idLexer &src ) {
  442. idToken token;
  443. int a, b;
  444. src.ReadToken( &token );
  445. if ( token == "(" ) {
  446. a = ParseExpression( src );
  447. MatchToken( src, ")" );
  448. return a;
  449. }
  450. if ( !token.Icmp( "time" ) ) {
  451. pd->registersAreConstant = false;
  452. return EXP_REG_TIME;
  453. }
  454. if ( !token.Icmp( "parm0" ) ) {
  455. pd->registersAreConstant = false;
  456. return EXP_REG_PARM0;
  457. }
  458. if ( !token.Icmp( "parm1" ) ) {
  459. pd->registersAreConstant = false;
  460. return EXP_REG_PARM1;
  461. }
  462. if ( !token.Icmp( "parm2" ) ) {
  463. pd->registersAreConstant = false;
  464. return EXP_REG_PARM2;
  465. }
  466. if ( !token.Icmp( "parm3" ) ) {
  467. pd->registersAreConstant = false;
  468. return EXP_REG_PARM3;
  469. }
  470. if ( !token.Icmp( "parm4" ) ) {
  471. pd->registersAreConstant = false;
  472. return EXP_REG_PARM4;
  473. }
  474. if ( !token.Icmp( "parm5" ) ) {
  475. pd->registersAreConstant = false;
  476. return EXP_REG_PARM5;
  477. }
  478. if ( !token.Icmp( "parm6" ) ) {
  479. pd->registersAreConstant = false;
  480. return EXP_REG_PARM6;
  481. }
  482. if ( !token.Icmp( "parm7" ) ) {
  483. pd->registersAreConstant = false;
  484. return EXP_REG_PARM7;
  485. }
  486. if ( !token.Icmp( "parm8" ) ) {
  487. pd->registersAreConstant = false;
  488. return EXP_REG_PARM8;
  489. }
  490. if ( !token.Icmp( "parm9" ) ) {
  491. pd->registersAreConstant = false;
  492. return EXP_REG_PARM9;
  493. }
  494. if ( !token.Icmp( "parm10" ) ) {
  495. pd->registersAreConstant = false;
  496. return EXP_REG_PARM10;
  497. }
  498. if ( !token.Icmp( "parm11" ) ) {
  499. pd->registersAreConstant = false;
  500. return EXP_REG_PARM11;
  501. }
  502. if ( !token.Icmp( "global0" ) ) {
  503. pd->registersAreConstant = false;
  504. return EXP_REG_GLOBAL0;
  505. }
  506. if ( !token.Icmp( "global1" ) ) {
  507. pd->registersAreConstant = false;
  508. return EXP_REG_GLOBAL1;
  509. }
  510. if ( !token.Icmp( "global2" ) ) {
  511. pd->registersAreConstant = false;
  512. return EXP_REG_GLOBAL2;
  513. }
  514. if ( !token.Icmp( "global3" ) ) {
  515. pd->registersAreConstant = false;
  516. return EXP_REG_GLOBAL3;
  517. }
  518. if ( !token.Icmp( "global4" ) ) {
  519. pd->registersAreConstant = false;
  520. return EXP_REG_GLOBAL4;
  521. }
  522. if ( !token.Icmp( "global5" ) ) {
  523. pd->registersAreConstant = false;
  524. return EXP_REG_GLOBAL5;
  525. }
  526. if ( !token.Icmp( "global6" ) ) {
  527. pd->registersAreConstant = false;
  528. return EXP_REG_GLOBAL6;
  529. }
  530. if ( !token.Icmp( "global7" ) ) {
  531. pd->registersAreConstant = false;
  532. return EXP_REG_GLOBAL7;
  533. }
  534. if ( !token.Icmp( "fragmentPrograms" ) ) {
  535. return GetExpressionConstant( (float) glConfig.ARBFragmentProgramAvailable );
  536. }
  537. if ( !token.Icmp( "sound" ) ) {
  538. pd->registersAreConstant = false;
  539. return EmitOp( 0, 0, OP_TYPE_SOUND );
  540. }
  541. // parse negative numbers
  542. if ( token == "-" ) {
  543. src.ReadToken( &token );
  544. if ( token.type == TT_NUMBER || token == "." ) {
  545. return GetExpressionConstant( -(float) token.GetFloatValue() );
  546. }
  547. src.Warning( "Bad negative number '%s'", token.c_str() );
  548. SetMaterialFlag( MF_DEFAULTED );
  549. return 0;
  550. }
  551. if ( token.type == TT_NUMBER || token == "." || token == "-" ) {
  552. return GetExpressionConstant( (float) token.GetFloatValue() );
  553. }
  554. // see if it is a table name
  555. const idDeclTable *table = static_cast<const idDeclTable *>( declManager->FindType( DECL_TABLE, token.c_str(), false ) );
  556. if ( !table ) {
  557. src.Warning( "Bad term '%s'", token.c_str() );
  558. SetMaterialFlag( MF_DEFAULTED );
  559. return 0;
  560. }
  561. // parse a table expression
  562. MatchToken( src, "[" );
  563. b = ParseExpression( src );
  564. MatchToken( src, "]" );
  565. return EmitOp( table->Index(), b, OP_TYPE_TABLE );
  566. }
  567. /*
  568. =================
  569. idMaterial::ParseExpressionPriority
  570. Returns a register index
  571. =================
  572. */
  573. #define TOP_PRIORITY 4
  574. int idMaterial::ParseExpressionPriority( idLexer &src, int priority ) {
  575. idToken token;
  576. int a;
  577. if ( priority == 0 ) {
  578. return ParseTerm( src );
  579. }
  580. a = ParseExpressionPriority( src, priority - 1 );
  581. if ( TestMaterialFlag( MF_DEFAULTED ) ) { // we have a parse error
  582. return 0;
  583. }
  584. if ( !src.ReadToken( &token ) ) {
  585. // we won't get EOF in a real file, but we can
  586. // when parsing from generated strings
  587. return a;
  588. }
  589. if ( priority == 1 && token == "*" ) {
  590. return ParseEmitOp( src, a, OP_TYPE_MULTIPLY, priority );
  591. }
  592. if ( priority == 1 && token == "/" ) {
  593. return ParseEmitOp( src, a, OP_TYPE_DIVIDE, priority );
  594. }
  595. if ( priority == 1 && token == "%" ) { // implied truncate both to integer
  596. return ParseEmitOp( src, a, OP_TYPE_MOD, priority );
  597. }
  598. if ( priority == 2 && token == "+" ) {
  599. return ParseEmitOp( src, a, OP_TYPE_ADD, priority );
  600. }
  601. if ( priority == 2 && token == "-" ) {
  602. return ParseEmitOp( src, a, OP_TYPE_SUBTRACT, priority );
  603. }
  604. if ( priority == 3 && token == ">" ) {
  605. return ParseEmitOp( src, a, OP_TYPE_GT, priority );
  606. }
  607. if ( priority == 3 && token == ">=" ) {
  608. return ParseEmitOp( src, a, OP_TYPE_GE, priority );
  609. }
  610. if ( priority == 3 && token == "<" ) {
  611. return ParseEmitOp( src, a, OP_TYPE_LT, priority );
  612. }
  613. if ( priority == 3 && token == "<=" ) {
  614. return ParseEmitOp( src, a, OP_TYPE_LE, priority );
  615. }
  616. if ( priority == 3 && token == "==" ) {
  617. return ParseEmitOp( src, a, OP_TYPE_EQ, priority );
  618. }
  619. if ( priority == 3 && token == "!=" ) {
  620. return ParseEmitOp( src, a, OP_TYPE_NE, priority );
  621. }
  622. if ( priority == 4 && token == "&&" ) {
  623. return ParseEmitOp( src, a, OP_TYPE_AND, priority );
  624. }
  625. if ( priority == 4 && token == "||" ) {
  626. return ParseEmitOp( src, a, OP_TYPE_OR, priority );
  627. }
  628. // assume that anything else terminates the expression
  629. // not too robust error checking...
  630. src.UnreadToken( &token );
  631. return a;
  632. }
  633. /*
  634. =================
  635. idMaterial::ParseExpression
  636. Returns a register index
  637. =================
  638. */
  639. int idMaterial::ParseExpression( idLexer &src ) {
  640. return ParseExpressionPriority( src, TOP_PRIORITY );
  641. }
  642. /*
  643. ===============
  644. idMaterial::ClearStage
  645. ===============
  646. */
  647. void idMaterial::ClearStage( shaderStage_t *ss ) {
  648. ss->drawStateBits = 0;
  649. ss->conditionRegister = GetExpressionConstant( 1 );
  650. ss->color.registers[0] =
  651. ss->color.registers[1] =
  652. ss->color.registers[2] =
  653. ss->color.registers[3] = GetExpressionConstant( 1 );
  654. }
  655. /*
  656. ===============
  657. idMaterial::NameToSrcBlendMode
  658. ===============
  659. */
  660. int idMaterial::NameToSrcBlendMode( const idStr &name ) {
  661. if ( !name.Icmp( "GL_ONE" ) ) {
  662. return GLS_SRCBLEND_ONE;
  663. } else if ( !name.Icmp( "GL_ZERO" ) ) {
  664. return GLS_SRCBLEND_ZERO;
  665. } else if ( !name.Icmp( "GL_DST_COLOR" ) ) {
  666. return GLS_SRCBLEND_DST_COLOR;
  667. } else if ( !name.Icmp( "GL_ONE_MINUS_DST_COLOR" ) ) {
  668. return GLS_SRCBLEND_ONE_MINUS_DST_COLOR;
  669. } else if ( !name.Icmp( "GL_SRC_ALPHA" ) ) {
  670. return GLS_SRCBLEND_SRC_ALPHA;
  671. } else if ( !name.Icmp( "GL_ONE_MINUS_SRC_ALPHA" ) ) {
  672. return GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA;
  673. } else if ( !name.Icmp( "GL_DST_ALPHA" ) ) {
  674. return GLS_SRCBLEND_DST_ALPHA;
  675. } else if ( !name.Icmp( "GL_ONE_MINUS_DST_ALPHA" ) ) {
  676. return GLS_SRCBLEND_ONE_MINUS_DST_ALPHA;
  677. } else if ( !name.Icmp( "GL_SRC_ALPHA_SATURATE" ) ) {
  678. return GLS_SRCBLEND_ALPHA_SATURATE;
  679. }
  680. common->Warning( "unknown blend mode '%s' in material '%s'", name.c_str(), GetName() );
  681. SetMaterialFlag( MF_DEFAULTED );
  682. return GLS_SRCBLEND_ONE;
  683. }
  684. /*
  685. ===============
  686. idMaterial::NameToDstBlendMode
  687. ===============
  688. */
  689. int idMaterial::NameToDstBlendMode( const idStr &name ) {
  690. if ( !name.Icmp( "GL_ONE" ) ) {
  691. return GLS_DSTBLEND_ONE;
  692. } else if ( !name.Icmp( "GL_ZERO" ) ) {
  693. return GLS_DSTBLEND_ZERO;
  694. } else if ( !name.Icmp( "GL_SRC_ALPHA" ) ) {
  695. return GLS_DSTBLEND_SRC_ALPHA;
  696. } else if ( !name.Icmp( "GL_ONE_MINUS_SRC_ALPHA" ) ) {
  697. return GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA;
  698. } else if ( !name.Icmp( "GL_DST_ALPHA" ) ) {
  699. return GLS_DSTBLEND_DST_ALPHA;
  700. } else if ( !name.Icmp( "GL_ONE_MINUS_DST_ALPHA" ) ) {
  701. return GLS_DSTBLEND_ONE_MINUS_DST_ALPHA;
  702. } else if ( !name.Icmp( "GL_SRC_COLOR" ) ) {
  703. return GLS_DSTBLEND_SRC_COLOR;
  704. } else if ( !name.Icmp( "GL_ONE_MINUS_SRC_COLOR" ) ) {
  705. return GLS_DSTBLEND_ONE_MINUS_SRC_COLOR;
  706. }
  707. common->Warning( "unknown blend mode '%s' in material '%s'", name.c_str(), GetName() );
  708. SetMaterialFlag( MF_DEFAULTED );
  709. return GLS_DSTBLEND_ONE;
  710. }
  711. /*
  712. ================
  713. idMaterial::ParseBlend
  714. ================
  715. */
  716. void idMaterial::ParseBlend( idLexer &src, shaderStage_t *stage ) {
  717. idToken token;
  718. int srcBlend, dstBlend;
  719. if ( !src.ReadToken( &token ) ) {
  720. return;
  721. }
  722. // blending combinations
  723. if ( !token.Icmp( "blend" ) ) {
  724. stage->drawStateBits = GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA;
  725. return;
  726. }
  727. if ( !token.Icmp( "add" ) ) {
  728. stage->drawStateBits = GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE;
  729. return;
  730. }
  731. if ( !token.Icmp( "filter" ) || !token.Icmp( "modulate" ) ) {
  732. stage->drawStateBits = GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO;
  733. return;
  734. }
  735. if ( !token.Icmp( "none" ) ) {
  736. // none is used when defining an alpha mask that doesn't draw
  737. stage->drawStateBits = GLS_SRCBLEND_ZERO | GLS_DSTBLEND_ONE;
  738. return;
  739. }
  740. if ( !token.Icmp( "bumpmap" ) ) {
  741. stage->lighting = SL_BUMP;
  742. return;
  743. }
  744. if ( !token.Icmp( "diffusemap" ) ) {
  745. stage->lighting = SL_DIFFUSE;
  746. return;
  747. }
  748. if ( !token.Icmp( "specularmap" ) ) {
  749. stage->lighting = SL_SPECULAR;
  750. return;
  751. }
  752. srcBlend = NameToSrcBlendMode( token );
  753. MatchToken( src, "," );
  754. if ( !src.ReadToken( &token ) ) {
  755. return;
  756. }
  757. dstBlend = NameToDstBlendMode( token );
  758. stage->drawStateBits = srcBlend | dstBlend;
  759. }
  760. /*
  761. ================
  762. idMaterial::ParseVertexParm
  763. If there is a single value, it will be repeated across all elements
  764. If there are two values, 3 = 0.0, 4 = 1.0
  765. if there are three values, 4 = 1.0
  766. ================
  767. */
  768. void idMaterial::ParseVertexParm( idLexer &src, newShaderStage_t *newStage ) {
  769. idToken token;
  770. src.ReadTokenOnLine( &token );
  771. int parm = token.GetIntValue();
  772. if ( !token.IsNumeric() || parm < 0 || parm >= MAX_VERTEX_PARMS ) {
  773. common->Warning( "bad vertexParm number\n" );
  774. SetMaterialFlag( MF_DEFAULTED );
  775. return;
  776. }
  777. if ( parm >= newStage->numVertexParms ) {
  778. newStage->numVertexParms = parm+1;
  779. }
  780. newStage->vertexParms[parm][0] = ParseExpression( src );
  781. src.ReadTokenOnLine( &token );
  782. if ( !token[0] || token.Icmp( "," ) ) {
  783. newStage->vertexParms[parm][1] =
  784. newStage->vertexParms[parm][2] =
  785. newStage->vertexParms[parm][3] = newStage->vertexParms[parm][0];
  786. return;
  787. }
  788. newStage->vertexParms[parm][1] = ParseExpression( src );
  789. src.ReadTokenOnLine( &token );
  790. if ( !token[0] || token.Icmp( "," ) ) {
  791. newStage->vertexParms[parm][2] = GetExpressionConstant( 0 );
  792. newStage->vertexParms[parm][3] = GetExpressionConstant( 1 );
  793. return;
  794. }
  795. newStage->vertexParms[parm][2] = ParseExpression( src );
  796. src.ReadTokenOnLine( &token );
  797. if ( !token[0] || token.Icmp( "," ) ) {
  798. newStage->vertexParms[parm][3] = GetExpressionConstant( 1 );
  799. return;
  800. }
  801. newStage->vertexParms[parm][3] = ParseExpression( src );
  802. }
  803. /*
  804. ================
  805. idMaterial::ParseFragmentMap
  806. ================
  807. */
  808. void idMaterial::ParseFragmentMap( idLexer &src, newShaderStage_t *newStage ) {
  809. const char *str;
  810. textureFilter_t tf;
  811. textureRepeat_t trp;
  812. textureDepth_t td;
  813. cubeFiles_t cubeMap;
  814. bool allowPicmip;
  815. idToken token;
  816. tf = TF_DEFAULT;
  817. trp = TR_REPEAT;
  818. td = TD_DEFAULT;
  819. allowPicmip = true;
  820. cubeMap = CF_2D;
  821. src.ReadTokenOnLine( &token );
  822. int unit = token.GetIntValue();
  823. if ( !token.IsNumeric() || unit < 0 || unit >= MAX_FRAGMENT_IMAGES ) {
  824. common->Warning( "bad fragmentMap number\n" );
  825. SetMaterialFlag( MF_DEFAULTED );
  826. return;
  827. }
  828. // unit 1 is the normal map.. make sure it gets flagged as the proper depth
  829. if ( unit == 1 ) {
  830. td = TD_BUMP;
  831. }
  832. if ( unit >= newStage->numFragmentProgramImages ) {
  833. newStage->numFragmentProgramImages = unit+1;
  834. }
  835. while( 1 ) {
  836. src.ReadTokenOnLine( &token );
  837. if ( !token.Icmp( "cubeMap" ) ) {
  838. cubeMap = CF_NATIVE;
  839. continue;
  840. }
  841. if ( !token.Icmp( "cameraCubeMap" ) ) {
  842. cubeMap = CF_CAMERA;
  843. continue;
  844. }
  845. if ( !token.Icmp( "nearest" ) ) {
  846. tf = TF_NEAREST;
  847. continue;
  848. }
  849. if ( !token.Icmp( "linear" ) ) {
  850. tf = TF_LINEAR;
  851. continue;
  852. }
  853. if ( !token.Icmp( "clamp" ) ) {
  854. trp = TR_CLAMP;
  855. continue;
  856. }
  857. if ( !token.Icmp( "noclamp" ) ) {
  858. trp = TR_REPEAT;
  859. continue;
  860. }
  861. if ( !token.Icmp( "zeroclamp" ) ) {
  862. trp = TR_CLAMP_TO_ZERO;
  863. continue;
  864. }
  865. if ( !token.Icmp( "alphazeroclamp" ) ) {
  866. trp = TR_CLAMP_TO_ZERO_ALPHA;
  867. continue;
  868. }
  869. if ( !token.Icmp( "forceHighQuality" ) ) {
  870. td = TD_HIGH_QUALITY;
  871. continue;
  872. }
  873. if ( !token.Icmp( "uncompressed" ) || !token.Icmp( "highquality" ) ) {
  874. if ( !globalImages->image_ignoreHighQuality.GetInteger() ) {
  875. td = TD_HIGH_QUALITY;
  876. }
  877. continue;
  878. }
  879. if ( !token.Icmp( "nopicmip" ) ) {
  880. allowPicmip = false;
  881. continue;
  882. }
  883. // assume anything else is the image name
  884. src.UnreadToken( &token );
  885. break;
  886. }
  887. str = R_ParsePastImageProgram( src );
  888. newStage->fragmentProgramImages[unit] =
  889. globalImages->ImageFromFile( str, tf, allowPicmip, trp, td, cubeMap );
  890. if ( !newStage->fragmentProgramImages[unit] ) {
  891. newStage->fragmentProgramImages[unit] = globalImages->defaultImage;
  892. }
  893. }
  894. /*
  895. ===============
  896. idMaterial::MultiplyTextureMatrix
  897. ===============
  898. */
  899. void idMaterial::MultiplyTextureMatrix( textureStage_t *ts, int registers[2][3] ) {
  900. int old[2][3];
  901. if ( !ts->hasMatrix ) {
  902. ts->hasMatrix = true;
  903. memcpy( ts->matrix, registers, sizeof( ts->matrix ) );
  904. return;
  905. }
  906. memcpy( old, ts->matrix, sizeof( old ) );
  907. // multiply the two maticies
  908. ts->matrix[0][0] = EmitOp(
  909. EmitOp( old[0][0], registers[0][0], OP_TYPE_MULTIPLY ),
  910. EmitOp( old[0][1], registers[1][0], OP_TYPE_MULTIPLY ), OP_TYPE_ADD );
  911. ts->matrix[0][1] = EmitOp(
  912. EmitOp( old[0][0], registers[0][1], OP_TYPE_MULTIPLY ),
  913. EmitOp( old[0][1], registers[1][1], OP_TYPE_MULTIPLY ), OP_TYPE_ADD );
  914. ts->matrix[0][2] = EmitOp(
  915. EmitOp(
  916. EmitOp( old[0][0], registers[0][2], OP_TYPE_MULTIPLY ),
  917. EmitOp( old[0][1], registers[1][2], OP_TYPE_MULTIPLY ), OP_TYPE_ADD ),
  918. old[0][2], OP_TYPE_ADD );
  919. ts->matrix[1][0] = EmitOp(
  920. EmitOp( old[1][0], registers[0][0], OP_TYPE_MULTIPLY ),
  921. EmitOp( old[1][1], registers[1][0], OP_TYPE_MULTIPLY ), OP_TYPE_ADD );
  922. ts->matrix[1][1] = EmitOp(
  923. EmitOp( old[1][0], registers[0][1], OP_TYPE_MULTIPLY ),
  924. EmitOp( old[1][1], registers[1][1], OP_TYPE_MULTIPLY ), OP_TYPE_ADD );
  925. ts->matrix[1][2] = EmitOp(
  926. EmitOp(
  927. EmitOp( old[1][0], registers[0][2], OP_TYPE_MULTIPLY ),
  928. EmitOp( old[1][1], registers[1][2], OP_TYPE_MULTIPLY ), OP_TYPE_ADD ),
  929. old[1][2], OP_TYPE_ADD );
  930. }
  931. /*
  932. =================
  933. idMaterial::ParseStage
  934. An open brace has been parsed
  935. {
  936. if <expression>
  937. map <imageprogram>
  938. "nearest" "linear" "clamp" "zeroclamp" "uncompressed" "highquality" "nopicmip"
  939. scroll, scale, rotate
  940. }
  941. =================
  942. */
  943. void idMaterial::ParseStage( idLexer &src, const textureRepeat_t trpDefault ) {
  944. idToken token;
  945. const char *str;
  946. shaderStage_t *ss;
  947. textureStage_t *ts;
  948. textureFilter_t tf;
  949. textureRepeat_t trp;
  950. textureDepth_t td;
  951. cubeFiles_t cubeMap;
  952. bool allowPicmip;
  953. char imageName[MAX_IMAGE_NAME];
  954. int a, b;
  955. int matrix[2][3];
  956. newShaderStage_t newStage;
  957. if ( numStages >= MAX_SHADER_STAGES ) {
  958. SetMaterialFlag( MF_DEFAULTED );
  959. common->Warning( "material '%s' exceeded %i stages", GetName(), MAX_SHADER_STAGES );
  960. }
  961. tf = TF_DEFAULT;
  962. trp = trpDefault;
  963. td = TD_DEFAULT;
  964. allowPicmip = true;
  965. cubeMap = CF_2D;
  966. imageName[0] = 0;
  967. memset( &newStage, 0, sizeof( newStage ) );
  968. ss = &pd->parseStages[numStages];
  969. ts = &ss->texture;
  970. ClearStage( ss );
  971. while ( 1 ) {
  972. if ( TestMaterialFlag( MF_DEFAULTED ) ) { // we have a parse error
  973. return;
  974. }
  975. if ( !src.ExpectAnyToken( &token ) ) {
  976. SetMaterialFlag( MF_DEFAULTED );
  977. return;
  978. }
  979. // the close brace for the entire material ends the draw block
  980. if ( token == "}" ) {
  981. break;
  982. }
  983. //BSM Nerve: Added for stage naming in the material editor
  984. if( !token.Icmp( "name") ) {
  985. src.SkipRestOfLine();
  986. continue;
  987. }
  988. // image options
  989. if ( !token.Icmp( "blend" ) ) {
  990. ParseBlend( src, ss );
  991. continue;
  992. }
  993. if ( !token.Icmp( "map" ) ) {
  994. str = R_ParsePastImageProgram( src );
  995. idStr::Copynz( imageName, str, sizeof( imageName ) );
  996. continue;
  997. }
  998. if ( !token.Icmp( "remoteRenderMap" ) ) {
  999. ts->dynamic = DI_REMOTE_RENDER;
  1000. ts->width = src.ParseInt();
  1001. ts->height = src.ParseInt();
  1002. continue;
  1003. }
  1004. if ( !token.Icmp( "mirrorRenderMap" ) ) {
  1005. ts->dynamic = DI_MIRROR_RENDER;
  1006. ts->width = src.ParseInt();
  1007. ts->height = src.ParseInt();
  1008. ts->texgen = TG_SCREEN;
  1009. continue;
  1010. }
  1011. if ( !token.Icmp( "xrayRenderMap" ) ) {
  1012. ts->dynamic = DI_XRAY_RENDER;
  1013. ts->width = src.ParseInt();
  1014. ts->height = src.ParseInt();
  1015. ts->texgen = TG_SCREEN;
  1016. continue;
  1017. }
  1018. if ( !token.Icmp( "screen" ) ) {
  1019. ts->texgen = TG_SCREEN;
  1020. continue;
  1021. }
  1022. if ( !token.Icmp( "screen2" ) ) {
  1023. ts->texgen = TG_SCREEN2;
  1024. continue;
  1025. }
  1026. if ( !token.Icmp( "glassWarp" ) ) {
  1027. ts->texgen = TG_GLASSWARP;
  1028. continue;
  1029. }
  1030. if ( !token.Icmp( "videomap" ) ) {
  1031. // note that videomaps will always be in clamp mode, so texture
  1032. // coordinates had better be in the 0 to 1 range
  1033. if ( !src.ReadToken( &token ) ) {
  1034. common->Warning( "missing parameter for 'videoMap' keyword in material '%s'", GetName() );
  1035. continue;
  1036. }
  1037. bool loop = false;
  1038. if ( !token.Icmp( "loop" ) ) {
  1039. loop = true;
  1040. if ( !src.ReadToken( &token ) ) {
  1041. common->Warning( "missing parameter for 'videoMap' keyword in material '%s'", GetName() );
  1042. continue;
  1043. }
  1044. }
  1045. ts->cinematic = idCinematic::Alloc();
  1046. ts->cinematic->InitFromFile( token.c_str(), loop );
  1047. continue;
  1048. }
  1049. if ( !token.Icmp( "soundmap" ) ) {
  1050. if ( !src.ReadToken( &token ) ) {
  1051. common->Warning( "missing parameter for 'soundmap' keyword in material '%s'", GetName() );
  1052. continue;
  1053. }
  1054. ts->cinematic = new idSndWindow();
  1055. ts->cinematic->InitFromFile( token.c_str(), true );
  1056. continue;
  1057. }
  1058. if ( !token.Icmp( "cubeMap" ) ) {
  1059. str = R_ParsePastImageProgram( src );
  1060. idStr::Copynz( imageName, str, sizeof( imageName ) );
  1061. cubeMap = CF_NATIVE;
  1062. continue;
  1063. }
  1064. if ( !token.Icmp( "cameraCubeMap" ) ) {
  1065. str = R_ParsePastImageProgram( src );
  1066. idStr::Copynz( imageName, str, sizeof( imageName ) );
  1067. cubeMap = CF_CAMERA;
  1068. continue;
  1069. }
  1070. if ( !token.Icmp( "ignoreAlphaTest" ) ) {
  1071. ss->ignoreAlphaTest = true;
  1072. continue;
  1073. }
  1074. if ( !token.Icmp( "nearest" ) ) {
  1075. tf = TF_NEAREST;
  1076. continue;
  1077. }
  1078. if ( !token.Icmp( "linear" ) ) {
  1079. tf = TF_LINEAR;
  1080. continue;
  1081. }
  1082. if ( !token.Icmp( "clamp" ) ) {
  1083. trp = TR_CLAMP;
  1084. continue;
  1085. }
  1086. if ( !token.Icmp( "noclamp" ) ) {
  1087. trp = TR_REPEAT;
  1088. continue;
  1089. }
  1090. if ( !token.Icmp( "zeroclamp" ) ) {
  1091. trp = TR_CLAMP_TO_ZERO;
  1092. continue;
  1093. }
  1094. if ( !token.Icmp( "alphazeroclamp" ) ) {
  1095. trp = TR_CLAMP_TO_ZERO_ALPHA;
  1096. continue;
  1097. }
  1098. if ( !token.Icmp( "uncompressed" ) || !token.Icmp( "highquality" ) ) {
  1099. if ( !globalImages->image_ignoreHighQuality.GetInteger() ) {
  1100. td = TD_HIGH_QUALITY;
  1101. }
  1102. continue;
  1103. }
  1104. if ( !token.Icmp( "forceHighQuality" ) ) {
  1105. td = TD_HIGH_QUALITY;
  1106. continue;
  1107. }
  1108. if ( !token.Icmp( "nopicmip" ) ) {
  1109. allowPicmip = false;
  1110. continue;
  1111. }
  1112. if ( !token.Icmp( "vertexColor" ) ) {
  1113. ss->vertexColor = SVC_MODULATE;
  1114. continue;
  1115. }
  1116. if ( !token.Icmp( "inverseVertexColor" ) ) {
  1117. ss->vertexColor = SVC_INVERSE_MODULATE;
  1118. continue;
  1119. }
  1120. // privatePolygonOffset
  1121. else if ( !token.Icmp( "privatePolygonOffset" ) ) {
  1122. if ( !src.ReadTokenOnLine( &token ) ) {
  1123. ss->privatePolygonOffset = 1;
  1124. continue;
  1125. }
  1126. // explict larger (or negative) offset
  1127. src.UnreadToken( &token );
  1128. ss->privatePolygonOffset = src.ParseFloat();
  1129. continue;
  1130. }
  1131. // texture coordinate generation
  1132. if ( !token.Icmp( "texGen" ) ) {
  1133. src.ExpectAnyToken( &token );
  1134. if ( !token.Icmp( "normal" ) ) {
  1135. ts->texgen = TG_DIFFUSE_CUBE;
  1136. } else if ( !token.Icmp( "reflect" ) ) {
  1137. ts->texgen = TG_REFLECT_CUBE;
  1138. } else if ( !token.Icmp( "skybox" ) ) {
  1139. ts->texgen = TG_SKYBOX_CUBE;
  1140. } else if ( !token.Icmp( "wobbleSky" ) ) {
  1141. ts->texgen = TG_WOBBLESKY_CUBE;
  1142. texGenRegisters[0] = ParseExpression( src );
  1143. texGenRegisters[1] = ParseExpression( src );
  1144. texGenRegisters[2] = ParseExpression( src );
  1145. } else {
  1146. common->Warning( "bad texGen '%s' in material %s", token.c_str(), GetName() );
  1147. SetMaterialFlag( MF_DEFAULTED );
  1148. }
  1149. continue;
  1150. }
  1151. if ( !token.Icmp( "scroll" ) || !token.Icmp( "translate" ) ) {
  1152. a = ParseExpression( src );
  1153. MatchToken( src, "," );
  1154. b = ParseExpression( src );
  1155. matrix[0][0] = GetExpressionConstant( 1 );
  1156. matrix[0][1] = GetExpressionConstant( 0 );
  1157. matrix[0][2] = a;
  1158. matrix[1][0] = GetExpressionConstant( 0 );
  1159. matrix[1][1] = GetExpressionConstant( 1 );
  1160. matrix[1][2] = b;
  1161. MultiplyTextureMatrix( ts, matrix );
  1162. continue;
  1163. }
  1164. if ( !token.Icmp( "scale" ) ) {
  1165. a = ParseExpression( src );
  1166. MatchToken( src, "," );
  1167. b = ParseExpression( src );
  1168. // this just scales without a centering
  1169. matrix[0][0] = a;
  1170. matrix[0][1] = GetExpressionConstant( 0 );
  1171. matrix[0][2] = GetExpressionConstant( 0 );
  1172. matrix[1][0] = GetExpressionConstant( 0 );
  1173. matrix[1][1] = b;
  1174. matrix[1][2] = GetExpressionConstant( 0 );
  1175. MultiplyTextureMatrix( ts, matrix );
  1176. continue;
  1177. }
  1178. if ( !token.Icmp( "centerScale" ) ) {
  1179. a = ParseExpression( src );
  1180. MatchToken( src, "," );
  1181. b = ParseExpression( src );
  1182. // this subtracts 0.5, then scales, then adds 0.5
  1183. matrix[0][0] = a;
  1184. matrix[0][1] = GetExpressionConstant( 0 );
  1185. matrix[0][2] = EmitOp( GetExpressionConstant( 0.5 ), EmitOp( GetExpressionConstant( 0.5 ), a, OP_TYPE_MULTIPLY ), OP_TYPE_SUBTRACT );
  1186. matrix[1][0] = GetExpressionConstant( 0 );
  1187. matrix[1][1] = b;
  1188. matrix[1][2] = EmitOp( GetExpressionConstant( 0.5 ), EmitOp( GetExpressionConstant( 0.5 ), b, OP_TYPE_MULTIPLY ), OP_TYPE_SUBTRACT );
  1189. MultiplyTextureMatrix( ts, matrix );
  1190. continue;
  1191. }
  1192. if ( !token.Icmp( "shear" ) ) {
  1193. a = ParseExpression( src );
  1194. MatchToken( src, "," );
  1195. b = ParseExpression( src );
  1196. // this subtracts 0.5, then shears, then adds 0.5
  1197. matrix[0][0] = GetExpressionConstant( 1 );
  1198. matrix[0][1] = a;
  1199. matrix[0][2] = EmitOp( GetExpressionConstant( -0.5 ), a, OP_TYPE_MULTIPLY );
  1200. matrix[1][0] = b;
  1201. matrix[1][1] = GetExpressionConstant( 1 );
  1202. matrix[1][2] = EmitOp( GetExpressionConstant( -0.5 ), b, OP_TYPE_MULTIPLY );
  1203. MultiplyTextureMatrix( ts, matrix );
  1204. continue;
  1205. }
  1206. if ( !token.Icmp( "rotate" ) ) {
  1207. const idDeclTable *table;
  1208. int sinReg, cosReg;
  1209. // in cycles
  1210. a = ParseExpression( src );
  1211. table = static_cast<const idDeclTable *>( declManager->FindType( DECL_TABLE, "sinTable", false ) );
  1212. if ( !table ) {
  1213. common->Warning( "no sinTable for rotate defined" );
  1214. SetMaterialFlag( MF_DEFAULTED );
  1215. return;
  1216. }
  1217. sinReg = EmitOp( table->Index(), a, OP_TYPE_TABLE );
  1218. table = static_cast<const idDeclTable *>( declManager->FindType( DECL_TABLE, "cosTable", false ) );
  1219. if ( !table ) {
  1220. common->Warning( "no cosTable for rotate defined" );
  1221. SetMaterialFlag( MF_DEFAULTED );
  1222. return;
  1223. }
  1224. cosReg = EmitOp( table->Index(), a, OP_TYPE_TABLE );
  1225. // this subtracts 0.5, then rotates, then adds 0.5
  1226. matrix[0][0] = cosReg;
  1227. matrix[0][1] = EmitOp( GetExpressionConstant( 0 ), sinReg, OP_TYPE_SUBTRACT );
  1228. matrix[0][2] = EmitOp( EmitOp( EmitOp( GetExpressionConstant( -0.5 ), cosReg, OP_TYPE_MULTIPLY ),
  1229. EmitOp( GetExpressionConstant( 0.5 ), sinReg, OP_TYPE_MULTIPLY ), OP_TYPE_ADD ),
  1230. GetExpressionConstant( 0.5 ), OP_TYPE_ADD );
  1231. matrix[1][0] = sinReg;
  1232. matrix[1][1] = cosReg;
  1233. matrix[1][2] = EmitOp( EmitOp( EmitOp( GetExpressionConstant( -0.5 ), sinReg, OP_TYPE_MULTIPLY ),
  1234. EmitOp( GetExpressionConstant( -0.5 ), cosReg, OP_TYPE_MULTIPLY ), OP_TYPE_ADD ),
  1235. GetExpressionConstant( 0.5 ), OP_TYPE_ADD );
  1236. MultiplyTextureMatrix( ts, matrix );
  1237. continue;
  1238. }
  1239. // color mask options
  1240. if ( !token.Icmp( "maskRed" ) ) {
  1241. ss->drawStateBits |= GLS_REDMASK;
  1242. continue;
  1243. }
  1244. if ( !token.Icmp( "maskGreen" ) ) {
  1245. ss->drawStateBits |= GLS_GREENMASK;
  1246. continue;
  1247. }
  1248. if ( !token.Icmp( "maskBlue" ) ) {
  1249. ss->drawStateBits |= GLS_BLUEMASK;
  1250. continue;
  1251. }
  1252. if ( !token.Icmp( "maskAlpha" ) ) {
  1253. ss->drawStateBits |= GLS_ALPHAMASK;
  1254. continue;
  1255. }
  1256. if ( !token.Icmp( "maskColor" ) ) {
  1257. ss->drawStateBits |= GLS_COLORMASK;
  1258. continue;
  1259. }
  1260. if ( !token.Icmp( "maskDepth" ) ) {
  1261. ss->drawStateBits |= GLS_DEPTHMASK;
  1262. continue;
  1263. }
  1264. if ( !token.Icmp( "alphaTest" ) ) {
  1265. ss->hasAlphaTest = true;
  1266. ss->alphaTestRegister = ParseExpression( src );
  1267. coverage = MC_PERFORATED;
  1268. continue;
  1269. }
  1270. // shorthand for 2D modulated
  1271. if ( !token.Icmp( "colored" ) ) {
  1272. ss->color.registers[0] = EXP_REG_PARM0;
  1273. ss->color.registers[1] = EXP_REG_PARM1;
  1274. ss->color.registers[2] = EXP_REG_PARM2;
  1275. ss->color.registers[3] = EXP_REG_PARM3;
  1276. pd->registersAreConstant = false;
  1277. continue;
  1278. }
  1279. if ( !token.Icmp( "color" ) ) {
  1280. ss->color.registers[0] = ParseExpression( src );
  1281. MatchToken( src, "," );
  1282. ss->color.registers[1] = ParseExpression( src );
  1283. MatchToken( src, "," );
  1284. ss->color.registers[2] = ParseExpression( src );
  1285. MatchToken( src, "," );
  1286. ss->color.registers[3] = ParseExpression( src );
  1287. continue;
  1288. }
  1289. if ( !token.Icmp( "red" ) ) {
  1290. ss->color.registers[0] = ParseExpression( src );
  1291. continue;
  1292. }
  1293. if ( !token.Icmp( "green" ) ) {
  1294. ss->color.registers[1] = ParseExpression( src );
  1295. continue;
  1296. }
  1297. if ( !token.Icmp( "blue" ) ) {
  1298. ss->color.registers[2] = ParseExpression( src );
  1299. continue;
  1300. }
  1301. if ( !token.Icmp( "alpha" ) ) {
  1302. ss->color.registers[3] = ParseExpression( src );
  1303. continue;
  1304. }
  1305. if ( !token.Icmp( "rgb" ) ) {
  1306. ss->color.registers[0] = ss->color.registers[1] =
  1307. ss->color.registers[2] = ParseExpression( src );
  1308. continue;
  1309. }
  1310. if ( !token.Icmp( "rgba" ) ) {
  1311. ss->color.registers[0] = ss->color.registers[1] =
  1312. ss->color.registers[2] = ss->color.registers[3] = ParseExpression( src );
  1313. continue;
  1314. }
  1315. if ( !token.Icmp( "if" ) ) {
  1316. ss->conditionRegister = ParseExpression( src );
  1317. continue;
  1318. }
  1319. if ( !token.Icmp( "program" ) ) {
  1320. if ( src.ReadTokenOnLine( &token ) ) {
  1321. newStage.vertexProgram = R_FindARBProgram( GL_VERTEX_PROGRAM_ARB, token.c_str() );
  1322. newStage.fragmentProgram = R_FindARBProgram( GL_FRAGMENT_PROGRAM_ARB, token.c_str() );
  1323. }
  1324. continue;
  1325. }
  1326. if ( !token.Icmp( "fragmentProgram" ) ) {
  1327. if ( src.ReadTokenOnLine( &token ) ) {
  1328. newStage.fragmentProgram = R_FindARBProgram( GL_FRAGMENT_PROGRAM_ARB, token.c_str() );
  1329. }
  1330. continue;
  1331. }
  1332. if ( !token.Icmp( "vertexProgram" ) ) {
  1333. if ( src.ReadTokenOnLine( &token ) ) {
  1334. newStage.vertexProgram = R_FindARBProgram( GL_VERTEX_PROGRAM_ARB, token.c_str() );
  1335. }
  1336. continue;
  1337. }
  1338. if ( !token.Icmp( "megaTexture" ) ) {
  1339. if ( src.ReadTokenOnLine( &token ) ) {
  1340. newStage.megaTexture = new idMegaTexture;
  1341. if ( !newStage.megaTexture->InitFromMegaFile( token.c_str() ) ) {
  1342. delete newStage.megaTexture;
  1343. SetMaterialFlag( MF_DEFAULTED );
  1344. continue;
  1345. }
  1346. newStage.vertexProgram = R_FindARBProgram( GL_VERTEX_PROGRAM_ARB, "megaTexture.vfp" );
  1347. newStage.fragmentProgram = R_FindARBProgram( GL_FRAGMENT_PROGRAM_ARB, "megaTexture.vfp" );
  1348. continue;
  1349. }
  1350. }
  1351. if ( !token.Icmp( "vertexParm" ) ) {
  1352. ParseVertexParm( src, &newStage );
  1353. continue;
  1354. }
  1355. if ( !token.Icmp( "fragmentMap" ) ) {
  1356. ParseFragmentMap( src, &newStage );
  1357. continue;
  1358. }
  1359. common->Warning( "unknown token '%s' in material '%s'", token.c_str(), GetName() );
  1360. SetMaterialFlag( MF_DEFAULTED );
  1361. return;
  1362. }
  1363. // if we are using newStage, allocate a copy of it
  1364. if ( newStage.fragmentProgram || newStage.vertexProgram ) {
  1365. ss->newStage = (newShaderStage_t *)Mem_Alloc( sizeof( newStage ) );
  1366. *(ss->newStage) = newStage;
  1367. }
  1368. // successfully parsed a stage
  1369. numStages++;
  1370. // select a compressed depth based on what the stage is
  1371. if ( td == TD_DEFAULT ) {
  1372. switch( ss->lighting ) {
  1373. case SL_BUMP:
  1374. td = TD_BUMP;
  1375. break;
  1376. case SL_DIFFUSE:
  1377. td = TD_DIFFUSE;
  1378. break;
  1379. case SL_SPECULAR:
  1380. td = TD_SPECULAR;
  1381. break;
  1382. default:
  1383. break;
  1384. }
  1385. }
  1386. // now load the image with all the parms we parsed
  1387. if ( imageName[0] ) {
  1388. ts->image = globalImages->ImageFromFile( imageName, tf, allowPicmip, trp, td, cubeMap );
  1389. if ( !ts->image ) {
  1390. ts->image = globalImages->defaultImage;
  1391. }
  1392. } else if ( !ts->cinematic && !ts->dynamic && !ss->newStage ) {
  1393. common->Warning( "material '%s' had stage with no image", GetName() );
  1394. ts->image = globalImages->defaultImage;
  1395. }
  1396. }
  1397. /*
  1398. ===============
  1399. idMaterial::ParseDeform
  1400. ===============
  1401. */
  1402. void idMaterial::ParseDeform( idLexer &src ) {
  1403. idToken token;
  1404. if ( !src.ExpectAnyToken( &token ) ) {
  1405. return;
  1406. }
  1407. if ( !token.Icmp( "sprite" ) ) {
  1408. deform = DFRM_SPRITE;
  1409. cullType = CT_TWO_SIDED;
  1410. SetMaterialFlag( MF_NOSHADOWS );
  1411. return;
  1412. }
  1413. if ( !token.Icmp( "tube" ) ) {
  1414. deform = DFRM_TUBE;
  1415. cullType = CT_TWO_SIDED;
  1416. SetMaterialFlag( MF_NOSHADOWS );
  1417. return;
  1418. }
  1419. if ( !token.Icmp( "flare" ) ) {
  1420. deform = DFRM_FLARE;
  1421. cullType = CT_TWO_SIDED;
  1422. deformRegisters[0] = ParseExpression( src );
  1423. SetMaterialFlag( MF_NOSHADOWS );
  1424. return;
  1425. }
  1426. if ( !token.Icmp( "expand" ) ) {
  1427. deform = DFRM_EXPAND;
  1428. deformRegisters[0] = ParseExpression( src );
  1429. return;
  1430. }
  1431. if ( !token.Icmp( "move" ) ) {
  1432. deform = DFRM_MOVE;
  1433. deformRegisters[0] = ParseExpression( src );
  1434. return;
  1435. }
  1436. if ( !token.Icmp( "turbulent" ) ) {
  1437. deform = DFRM_TURB;
  1438. if ( !src.ExpectAnyToken( &token ) ) {
  1439. src.Warning( "deform particle missing particle name" );
  1440. SetMaterialFlag( MF_DEFAULTED );
  1441. return;
  1442. }
  1443. deformDecl = declManager->FindType( DECL_TABLE, token.c_str(), true );
  1444. deformRegisters[0] = ParseExpression( src );
  1445. deformRegisters[1] = ParseExpression( src );
  1446. deformRegisters[2] = ParseExpression( src );
  1447. return;
  1448. }
  1449. if ( !token.Icmp( "eyeBall" ) ) {
  1450. deform = DFRM_EYEBALL;
  1451. return;
  1452. }
  1453. if ( !token.Icmp( "particle" ) ) {
  1454. deform = DFRM_PARTICLE;
  1455. if ( !src.ExpectAnyToken( &token ) ) {
  1456. src.Warning( "deform particle missing particle name" );
  1457. SetMaterialFlag( MF_DEFAULTED );
  1458. return;
  1459. }
  1460. deformDecl = declManager->FindType( DECL_PARTICLE, token.c_str(), true );
  1461. return;
  1462. }
  1463. if ( !token.Icmp( "particle2" ) ) {
  1464. deform = DFRM_PARTICLE2;
  1465. if ( !src.ExpectAnyToken( &token ) ) {
  1466. src.Warning( "deform particle missing particle name" );
  1467. SetMaterialFlag( MF_DEFAULTED );
  1468. return;
  1469. }
  1470. deformDecl = declManager->FindType( DECL_PARTICLE, token.c_str(), true );
  1471. return;
  1472. }
  1473. src.Warning( "Bad deform type '%s'", token.c_str() );
  1474. SetMaterialFlag( MF_DEFAULTED );
  1475. }
  1476. /*
  1477. ==============
  1478. idMaterial::AddImplicitStages
  1479. If a material has diffuse or specular stages without any
  1480. bump stage, add an implicit _flat bumpmap stage.
  1481. If a material has a bump stage but no diffuse or specular
  1482. stage, add a _white diffuse stage.
  1483. It is valid to have either a diffuse or specular without the other.
  1484. It is valid to have a reflection map and a bump map for bumpy reflection
  1485. ==============
  1486. */
  1487. void idMaterial::AddImplicitStages( const textureRepeat_t trpDefault /* = TR_REPEAT */ ) {
  1488. char buffer[1024];
  1489. idLexer newSrc;
  1490. bool hasDiffuse = false;
  1491. bool hasSpecular = false;
  1492. bool hasBump = false;
  1493. bool hasReflection = false;
  1494. for ( int i = 0 ; i < numStages ; i++ ) {
  1495. if ( pd->parseStages[i].lighting == SL_BUMP ) {
  1496. hasBump = true;
  1497. }
  1498. if ( pd->parseStages[i].lighting == SL_DIFFUSE ) {
  1499. hasDiffuse = true;
  1500. }
  1501. if ( pd->parseStages[i].lighting == SL_SPECULAR ) {
  1502. hasSpecular = true;
  1503. }
  1504. if ( pd->parseStages[i].texture.texgen == TG_REFLECT_CUBE ) {
  1505. hasReflection = true;
  1506. }
  1507. }
  1508. // if it doesn't have an interaction at all, don't add anything
  1509. if ( !hasBump && !hasDiffuse && !hasSpecular ) {
  1510. return;
  1511. }
  1512. if ( numStages == MAX_SHADER_STAGES ) {
  1513. return;
  1514. }
  1515. if ( !hasBump ) {
  1516. idStr::snPrintf( buffer, sizeof( buffer ), "blend bumpmap\nmap _flat\n}\n" );
  1517. newSrc.LoadMemory( buffer, strlen(buffer), "bumpmap" );
  1518. newSrc.SetFlags( LEXFL_NOFATALERRORS | LEXFL_NOSTRINGCONCAT | LEXFL_NOSTRINGESCAPECHARS | LEXFL_ALLOWPATHNAMES );
  1519. ParseStage( newSrc, trpDefault );
  1520. newSrc.FreeSource();
  1521. }
  1522. if ( !hasDiffuse && !hasSpecular && !hasReflection ) {
  1523. idStr::snPrintf( buffer, sizeof( buffer ), "blend diffusemap\nmap _white\n}\n" );
  1524. newSrc.LoadMemory( buffer, strlen(buffer), "diffusemap" );
  1525. newSrc.SetFlags( LEXFL_NOFATALERRORS | LEXFL_NOSTRINGCONCAT | LEXFL_NOSTRINGESCAPECHARS | LEXFL_ALLOWPATHNAMES );
  1526. ParseStage( newSrc, trpDefault );
  1527. newSrc.FreeSource();
  1528. }
  1529. }
  1530. /*
  1531. ===============
  1532. idMaterial::SortInteractionStages
  1533. The renderer expects bump, then diffuse, then specular
  1534. There can be multiple bump maps, followed by additional
  1535. diffuse and specular stages, which allows cross-faded bump mapping.
  1536. Ambient stages can be interspersed anywhere, but they are
  1537. ignored during interactions, and all the interaction
  1538. stages are ignored during ambient drawing.
  1539. ===============
  1540. */
  1541. void idMaterial::SortInteractionStages() {
  1542. int j;
  1543. for ( int i = 0 ; i < numStages ; i = j ) {
  1544. // find the next bump map
  1545. for ( j = i + 1 ; j < numStages ; j++ ) {
  1546. if ( pd->parseStages[j].lighting == SL_BUMP ) {
  1547. // if the very first stage wasn't a bumpmap,
  1548. // this bumpmap is part of the first group
  1549. if ( pd->parseStages[i].lighting != SL_BUMP ) {
  1550. continue;
  1551. }
  1552. break;
  1553. }
  1554. }
  1555. // bubble sort everything bump / diffuse / specular
  1556. for ( int l = 1 ; l < j-i ; l++ ) {
  1557. for ( int k = i ; k < j-l ; k++ ) {
  1558. if ( pd->parseStages[k].lighting > pd->parseStages[k+1].lighting ) {
  1559. shaderStage_t temp;
  1560. temp = pd->parseStages[k];
  1561. pd->parseStages[k] = pd->parseStages[k+1];
  1562. pd->parseStages[k+1] = temp;
  1563. }
  1564. }
  1565. }
  1566. }
  1567. }
  1568. /*
  1569. =================
  1570. idMaterial::ParseMaterial
  1571. The current text pointer is at the explicit text definition of the
  1572. Parse it into the global material variable. Later functions will optimize it.
  1573. If there is any error during parsing, defaultShader will be set.
  1574. =================
  1575. */
  1576. void idMaterial::ParseMaterial( idLexer &src ) {
  1577. idToken token;
  1578. int s;
  1579. char buffer[1024];
  1580. const char *str;
  1581. idLexer newSrc;
  1582. int i;
  1583. s = 0;
  1584. numOps = 0;
  1585. numRegisters = EXP_REG_NUM_PREDEFINED; // leave space for the parms to be copied in
  1586. for ( i = 0 ; i < numRegisters ; i++ ) {
  1587. pd->registerIsTemporary[i] = true; // they aren't constants that can be folded
  1588. }
  1589. numStages = 0;
  1590. textureRepeat_t trpDefault = TR_REPEAT; // allow a global setting for repeat
  1591. while ( 1 ) {
  1592. if ( TestMaterialFlag( MF_DEFAULTED ) ) { // we have a parse error
  1593. return;
  1594. }
  1595. if ( !src.ExpectAnyToken( &token ) ) {
  1596. SetMaterialFlag( MF_DEFAULTED );
  1597. return;
  1598. }
  1599. // end of material definition
  1600. if ( token == "}" ) {
  1601. break;
  1602. }
  1603. else if ( !token.Icmp( "qer_editorimage") ) {
  1604. src.ReadTokenOnLine( &token );
  1605. editorImageName = token.c_str();
  1606. src.SkipRestOfLine();
  1607. continue;
  1608. }
  1609. // description
  1610. else if ( !token.Icmp( "description") ) {
  1611. src.ReadTokenOnLine( &token );
  1612. desc = token.c_str();
  1613. continue;
  1614. }
  1615. // check for the surface / content bit flags
  1616. else if ( CheckSurfaceParm( &token ) ) {
  1617. continue;
  1618. }
  1619. // polygonOffset
  1620. else if ( !token.Icmp( "polygonOffset" ) ) {
  1621. SetMaterialFlag( MF_POLYGONOFFSET );
  1622. if ( !src.ReadTokenOnLine( &token ) ) {
  1623. polygonOffset = 1;
  1624. continue;
  1625. }
  1626. // explict larger (or negative) offset
  1627. polygonOffset = token.GetFloatValue();
  1628. continue;
  1629. }
  1630. // noshadow
  1631. else if ( !token.Icmp( "noShadows" ) ) {
  1632. SetMaterialFlag( MF_NOSHADOWS );
  1633. continue;
  1634. }
  1635. else if ( !token.Icmp( "suppressInSubview" ) ) {
  1636. suppressInSubview = true;
  1637. continue;
  1638. }
  1639. else if ( !token.Icmp( "portalSky" ) ) {
  1640. portalSky = true;
  1641. continue;
  1642. }
  1643. // noSelfShadow
  1644. else if ( !token.Icmp( "noSelfShadow" ) ) {
  1645. SetMaterialFlag( MF_NOSELFSHADOW );
  1646. continue;
  1647. }
  1648. // noPortalFog
  1649. else if ( !token.Icmp( "noPortalFog" ) ) {
  1650. SetMaterialFlag( MF_NOPORTALFOG );
  1651. continue;
  1652. }
  1653. // forceShadows allows nodraw surfaces to cast shadows
  1654. else if ( !token.Icmp( "forceShadows" ) ) {
  1655. SetMaterialFlag( MF_FORCESHADOWS );
  1656. continue;
  1657. }
  1658. // overlay / decal suppression
  1659. else if ( !token.Icmp( "noOverlays" ) ) {
  1660. allowOverlays = false;
  1661. continue;
  1662. }
  1663. // moster blood overlay forcing for alpha tested or translucent surfaces
  1664. else if ( !token.Icmp( "forceOverlays" ) ) {
  1665. pd->forceOverlays = true;
  1666. continue;
  1667. }
  1668. // translucent
  1669. else if ( !token.Icmp( "translucent" ) ) {
  1670. coverage = MC_TRANSLUCENT;
  1671. continue;
  1672. }
  1673. // global zero clamp
  1674. else if ( !token.Icmp( "zeroclamp" ) ) {
  1675. trpDefault = TR_CLAMP_TO_ZERO;
  1676. continue;
  1677. }
  1678. // global clamp
  1679. else if ( !token.Icmp( "clamp" ) ) {
  1680. trpDefault = TR_CLAMP;
  1681. continue;
  1682. }
  1683. // global clamp
  1684. else if ( !token.Icmp( "alphazeroclamp" ) ) {
  1685. trpDefault = TR_CLAMP_TO_ZERO;
  1686. continue;
  1687. }
  1688. // forceOpaque is used for skies-behind-windows
  1689. else if ( !token.Icmp( "forceOpaque" ) ) {
  1690. coverage = MC_OPAQUE;
  1691. continue;
  1692. }
  1693. // twoSided
  1694. else if ( !token.Icmp( "twoSided" ) ) {
  1695. cullType = CT_TWO_SIDED;
  1696. // twoSided implies no-shadows, because the shadow
  1697. // volume would be coplanar with the surface, giving depth fighting
  1698. // we could make this no-self-shadows, but it may be more important
  1699. // to receive shadows from no-self-shadow monsters
  1700. SetMaterialFlag( MF_NOSHADOWS );
  1701. }
  1702. // backSided
  1703. else if ( !token.Icmp( "backSided" ) ) {
  1704. cullType = CT_BACK_SIDED;
  1705. // the shadow code doesn't handle this, so just disable shadows.
  1706. // We could fix this in the future if there was a need.
  1707. SetMaterialFlag( MF_NOSHADOWS );
  1708. }
  1709. // foglight
  1710. else if ( !token.Icmp( "fogLight" ) ) {
  1711. fogLight = true;
  1712. continue;
  1713. }
  1714. // blendlight
  1715. else if ( !token.Icmp( "blendLight" ) ) {
  1716. blendLight = true;
  1717. continue;
  1718. }
  1719. // ambientLight
  1720. else if ( !token.Icmp( "ambientLight" ) ) {
  1721. ambientLight = true;
  1722. continue;
  1723. }
  1724. // mirror
  1725. else if ( !token.Icmp( "mirror" ) ) {
  1726. sort = SS_SUBVIEW;
  1727. coverage = MC_OPAQUE;
  1728. continue;
  1729. }
  1730. // noFog
  1731. else if ( !token.Icmp( "noFog" ) ) {
  1732. noFog = true;
  1733. continue;
  1734. }
  1735. // unsmoothedTangents
  1736. else if ( !token.Icmp( "unsmoothedTangents" ) ) {
  1737. unsmoothedTangents = true;
  1738. continue;
  1739. }
  1740. // lightFallofImage <imageprogram>
  1741. // specifies the image to use for the third axis of projected
  1742. // light volumes
  1743. else if ( !token.Icmp( "lightFalloffImage" ) ) {
  1744. str = R_ParsePastImageProgram( src );
  1745. idStr copy;
  1746. copy = str; // so other things don't step on it
  1747. lightFalloffImage = globalImages->ImageFromFile( copy, TF_DEFAULT, false, TR_CLAMP /* TR_CLAMP_TO_ZERO */, TD_DEFAULT );
  1748. continue;
  1749. }
  1750. // guisurf <guifile> | guisurf entity
  1751. // an entity guisurf must have an idUserInterface
  1752. // specified in the renderEntity
  1753. else if ( !token.Icmp( "guisurf" ) ) {
  1754. src.ReadTokenOnLine( &token );
  1755. if ( !token.Icmp( "entity" ) ) {
  1756. entityGui = 1;
  1757. } else if ( !token.Icmp( "entity2" ) ) {
  1758. entityGui = 2;
  1759. } else if ( !token.Icmp( "entity3" ) ) {
  1760. entityGui = 3;
  1761. } else {
  1762. gui = uiManager->FindGui( token.c_str(), true );
  1763. }
  1764. continue;
  1765. }
  1766. // sort
  1767. else if ( !token.Icmp( "sort" ) ) {
  1768. ParseSort( src );
  1769. continue;
  1770. }
  1771. // spectrum <integer>
  1772. else if ( !token.Icmp( "spectrum" ) ) {
  1773. src.ReadTokenOnLine( &token );
  1774. spectrum = atoi( token.c_str() );
  1775. continue;
  1776. }
  1777. // deform < sprite | tube | flare >
  1778. else if ( !token.Icmp( "deform" ) ) {
  1779. ParseDeform( src );
  1780. continue;
  1781. }
  1782. // decalInfo <staySeconds> <fadeSeconds> ( <start rgb> ) ( <end rgb> )
  1783. else if ( !token.Icmp( "decalInfo" ) ) {
  1784. ParseDecalInfo( src );
  1785. continue;
  1786. }
  1787. // renderbump <args...>
  1788. else if ( !token.Icmp( "renderbump") ) {
  1789. src.ParseRestOfLine( renderBump );
  1790. continue;
  1791. }
  1792. // diffusemap for stage shortcut
  1793. else if ( !token.Icmp( "diffusemap" ) ) {
  1794. str = R_ParsePastImageProgram( src );
  1795. idStr::snPrintf( buffer, sizeof( buffer ), "blend diffusemap\nmap %s\n}\n", str );
  1796. newSrc.LoadMemory( buffer, strlen(buffer), "diffusemap" );
  1797. newSrc.SetFlags( LEXFL_NOFATALERRORS | LEXFL_NOSTRINGCONCAT | LEXFL_NOSTRINGESCAPECHARS | LEXFL_ALLOWPATHNAMES );
  1798. ParseStage( newSrc, trpDefault );
  1799. newSrc.FreeSource();
  1800. continue;
  1801. }
  1802. // specularmap for stage shortcut
  1803. else if ( !token.Icmp( "specularmap" ) ) {
  1804. str = R_ParsePastImageProgram( src );
  1805. idStr::snPrintf( buffer, sizeof( buffer ), "blend specularmap\nmap %s\n}\n", str );
  1806. newSrc.LoadMemory( buffer, strlen(buffer), "specularmap" );
  1807. newSrc.SetFlags( LEXFL_NOFATALERRORS | LEXFL_NOSTRINGCONCAT | LEXFL_NOSTRINGESCAPECHARS | LEXFL_ALLOWPATHNAMES );
  1808. ParseStage( newSrc, trpDefault );
  1809. newSrc.FreeSource();
  1810. continue;
  1811. }
  1812. // normalmap for stage shortcut
  1813. else if ( !token.Icmp( "bumpmap" ) ) {
  1814. str = R_ParsePastImageProgram( src );
  1815. idStr::snPrintf( buffer, sizeof( buffer ), "blend bumpmap\nmap %s\n}\n", str );
  1816. newSrc.LoadMemory( buffer, strlen(buffer), "bumpmap" );
  1817. newSrc.SetFlags( LEXFL_NOFATALERRORS | LEXFL_NOSTRINGCONCAT | LEXFL_NOSTRINGESCAPECHARS | LEXFL_ALLOWPATHNAMES );
  1818. ParseStage( newSrc, trpDefault );
  1819. newSrc.FreeSource();
  1820. continue;
  1821. }
  1822. // DECAL_MACRO for backwards compatibility with the preprocessor macros
  1823. else if ( !token.Icmp( "DECAL_MACRO" ) ) {
  1824. // polygonOffset
  1825. SetMaterialFlag( MF_POLYGONOFFSET );
  1826. polygonOffset = 1;
  1827. // discrete
  1828. surfaceFlags |= SURF_DISCRETE;
  1829. contentFlags &= ~CONTENTS_SOLID;
  1830. // sort decal
  1831. sort = SS_DECAL;
  1832. // noShadows
  1833. SetMaterialFlag( MF_NOSHADOWS );
  1834. continue;
  1835. }
  1836. else if ( token == "{" ) {
  1837. // create the new stage
  1838. ParseStage( src, trpDefault );
  1839. continue;
  1840. }
  1841. else {
  1842. common->Warning( "unknown general material parameter '%s' in '%s'", token.c_str(), GetName() );
  1843. SetMaterialFlag( MF_DEFAULTED );
  1844. return;
  1845. }
  1846. }
  1847. // add _flat or _white stages if needed
  1848. AddImplicitStages();
  1849. // order the diffuse / bump / specular stages properly
  1850. SortInteractionStages();
  1851. // if we need to do anything with normals (lighting or environment mapping)
  1852. // and two sided lighting was asked for, flag
  1853. // shouldCreateBackSides() and change culling back to single sided,
  1854. // so we get proper tangent vectors on both sides
  1855. // we can't just call ReceivesLighting(), because the stages are still
  1856. // in temporary form
  1857. if ( cullType == CT_TWO_SIDED ) {
  1858. for ( i = 0 ; i < numStages ; i++ ) {
  1859. if ( pd->parseStages[i].lighting != SL_AMBIENT || pd->parseStages[i].texture.texgen != TG_EXPLICIT ) {
  1860. if ( cullType == CT_TWO_SIDED ) {
  1861. cullType = CT_FRONT_SIDED;
  1862. shouldCreateBackSides = true;
  1863. }
  1864. break;
  1865. }
  1866. }
  1867. }
  1868. // currently a surface can only have one unique texgen for all the stages on old hardware
  1869. texgen_t firstGen = TG_EXPLICIT;
  1870. for ( i = 0; i < numStages; i++ ) {
  1871. if ( pd->parseStages[i].texture.texgen != TG_EXPLICIT ) {
  1872. if ( firstGen == TG_EXPLICIT ) {
  1873. firstGen = pd->parseStages[i].texture.texgen;
  1874. } else if ( firstGen != pd->parseStages[i].texture.texgen ) {
  1875. common->Warning( "material '%s' has multiple stages with a texgen", GetName() );
  1876. break;
  1877. }
  1878. }
  1879. }
  1880. }
  1881. /*
  1882. =========================
  1883. idMaterial::SetGui
  1884. =========================
  1885. */
  1886. void idMaterial::SetGui( const char *_gui ) const {
  1887. gui = uiManager->FindGui( _gui, true, false, true );
  1888. }
  1889. /*
  1890. =========================
  1891. idMaterial::Parse
  1892. Parses the current material definition and finds all necessary images.
  1893. =========================
  1894. */
  1895. bool idMaterial::Parse( const char *text, const int textLength ) {
  1896. idLexer src;
  1897. idToken token;
  1898. mtrParsingData_t parsingData;
  1899. src.LoadMemory( text, textLength, GetFileName(), GetLineNum() );
  1900. src.SetFlags( DECL_LEXER_FLAGS );
  1901. src.SkipUntilString( "{" );
  1902. // reset to the unparsed state
  1903. CommonInit();
  1904. memset( &parsingData, 0, sizeof( parsingData ) );
  1905. pd = &parsingData; // this is only valid during parse
  1906. // parse it
  1907. ParseMaterial( src );
  1908. // if we are doing an fs_copyfiles, also reference the editorImage
  1909. if ( cvarSystem->GetCVarInteger( "fs_copyFiles" ) ) {
  1910. GetEditorImage();
  1911. }
  1912. //
  1913. // count non-lit stages
  1914. numAmbientStages = 0;
  1915. int i;
  1916. for ( i = 0 ; i < numStages ; i++ ) {
  1917. if ( pd->parseStages[i].lighting == SL_AMBIENT ) {
  1918. numAmbientStages++;
  1919. }
  1920. }
  1921. // see if there is a subview stage
  1922. if ( sort == SS_SUBVIEW ) {
  1923. hasSubview = true;
  1924. } else {
  1925. hasSubview = false;
  1926. for ( i = 0 ; i < numStages ; i++ ) {
  1927. if ( pd->parseStages[i].texture.dynamic ) {
  1928. hasSubview = true;
  1929. }
  1930. }
  1931. }
  1932. // automatically determine coverage if not explicitly set
  1933. if ( coverage == MC_BAD ) {
  1934. // automatically set MC_TRANSLUCENT if we don't have any interaction stages and
  1935. // the first stage is blended and not an alpha test mask or a subview
  1936. if ( !numStages ) {
  1937. // non-visible
  1938. coverage = MC_TRANSLUCENT;
  1939. } else if ( numStages != numAmbientStages ) {
  1940. // we have an interaction draw
  1941. coverage = MC_OPAQUE;
  1942. } else if (
  1943. ( pd->parseStages[0].drawStateBits & GLS_DSTBLEND_BITS ) != GLS_DSTBLEND_ZERO ||
  1944. ( pd->parseStages[0].drawStateBits & GLS_SRCBLEND_BITS ) == GLS_SRCBLEND_DST_COLOR ||
  1945. ( pd->parseStages[0].drawStateBits & GLS_SRCBLEND_BITS ) == GLS_SRCBLEND_ONE_MINUS_DST_COLOR ||
  1946. ( pd->parseStages[0].drawStateBits & GLS_SRCBLEND_BITS ) == GLS_SRCBLEND_DST_ALPHA ||
  1947. ( pd->parseStages[0].drawStateBits & GLS_SRCBLEND_BITS ) == GLS_SRCBLEND_ONE_MINUS_DST_ALPHA
  1948. ) {
  1949. // blended with the destination
  1950. coverage = MC_TRANSLUCENT;
  1951. } else {
  1952. coverage = MC_OPAQUE;
  1953. }
  1954. }
  1955. // translucent automatically implies noshadows
  1956. if ( coverage == MC_TRANSLUCENT ) {
  1957. SetMaterialFlag( MF_NOSHADOWS );
  1958. } else {
  1959. // mark the contents as opaque
  1960. contentFlags |= CONTENTS_OPAQUE;
  1961. }
  1962. // if we are translucent, draw with an alpha in the editor
  1963. if ( coverage == MC_TRANSLUCENT ) {
  1964. editorAlpha = 0.5;
  1965. } else {
  1966. editorAlpha = 1.0;
  1967. }
  1968. // the sorts can make reasonable defaults
  1969. if ( sort == SS_BAD ) {
  1970. if ( TestMaterialFlag(MF_POLYGONOFFSET) ) {
  1971. sort = SS_DECAL;
  1972. } else if ( coverage == MC_TRANSLUCENT ) {
  1973. sort = SS_MEDIUM;
  1974. } else {
  1975. sort = SS_OPAQUE;
  1976. }
  1977. }
  1978. // anything that references _currentRender will automatically get sort = SS_POST_PROCESS
  1979. // and coverage = MC_TRANSLUCENT
  1980. for ( i = 0 ; i < numStages ; i++ ) {
  1981. shaderStage_t *pStage = &pd->parseStages[i];
  1982. if ( pStage->texture.image == globalImages->currentRenderImage ) {
  1983. if ( sort != SS_PORTAL_SKY ) {
  1984. sort = SS_POST_PROCESS;
  1985. coverage = MC_TRANSLUCENT;
  1986. }
  1987. break;
  1988. }
  1989. if ( pStage->newStage ) {
  1990. for ( int j = 0 ; j < pStage->newStage->numFragmentProgramImages ; j++ ) {
  1991. if ( pStage->newStage->fragmentProgramImages[j] == globalImages->currentRenderImage ) {
  1992. if ( sort != SS_PORTAL_SKY ) {
  1993. sort = SS_POST_PROCESS;
  1994. coverage = MC_TRANSLUCENT;
  1995. }
  1996. i = numStages;
  1997. break;
  1998. }
  1999. }
  2000. }
  2001. }
  2002. // set the drawStateBits depth flags
  2003. for ( i = 0 ; i < numStages ; i++ ) {
  2004. shaderStage_t *pStage = &pd->parseStages[i];
  2005. if ( sort == SS_POST_PROCESS ) {
  2006. // post-process effects fill the depth buffer as they draw, so only the
  2007. // topmost post-process effect is rendered
  2008. pStage->drawStateBits |= GLS_DEPTHFUNC_LESS;
  2009. } else if ( coverage == MC_TRANSLUCENT || pStage->ignoreAlphaTest ) {
  2010. // translucent surfaces can extend past the exactly marked depth buffer
  2011. pStage->drawStateBits |= GLS_DEPTHFUNC_LESS | GLS_DEPTHMASK;
  2012. } else {
  2013. // opaque and perforated surfaces must exactly match the depth buffer,
  2014. // which gets alpha test correct
  2015. pStage->drawStateBits |= GLS_DEPTHFUNC_EQUAL | GLS_DEPTHMASK;
  2016. }
  2017. }
  2018. // determine if this surface will accept overlays / decals
  2019. if ( pd->forceOverlays ) {
  2020. // explicitly flaged in material definition
  2021. allowOverlays = true;
  2022. } else {
  2023. if ( !IsDrawn() ) {
  2024. allowOverlays = false;
  2025. }
  2026. if ( Coverage() != MC_OPAQUE ) {
  2027. allowOverlays = false;
  2028. }
  2029. if ( GetSurfaceFlags() & SURF_NOIMPACT ) {
  2030. allowOverlays = false;
  2031. }
  2032. }
  2033. // add a tiny offset to the sort orders, so that different materials
  2034. // that have the same sort value will at least sort consistantly, instead
  2035. // of flickering back and forth
  2036. /* this messed up in-game guis
  2037. if ( sort != SS_SUBVIEW ) {
  2038. int hash, l;
  2039. l = name.Length();
  2040. hash = 0;
  2041. for ( int i = 0 ; i < l ; i++ ) {
  2042. hash ^= name[i];
  2043. }
  2044. sort += hash * 0.01;
  2045. }
  2046. */
  2047. if (numStages) {
  2048. stages = (shaderStage_t *)R_StaticAlloc( numStages * sizeof( stages[0] ) );
  2049. memcpy( stages, pd->parseStages, numStages * sizeof( stages[0] ) );
  2050. }
  2051. if ( numOps ) {
  2052. ops = (expOp_t *)R_StaticAlloc( numOps * sizeof( ops[0] ) );
  2053. memcpy( ops, pd->shaderOps, numOps * sizeof( ops[0] ) );
  2054. }
  2055. if ( numRegisters ) {
  2056. expressionRegisters = (float *)R_StaticAlloc( numRegisters * sizeof( expressionRegisters[0] ) );
  2057. memcpy( expressionRegisters, pd->shaderRegisters, numRegisters * sizeof( expressionRegisters[0] ) );
  2058. }
  2059. // see if the registers are completely constant, and don't need to be evaluated
  2060. // per-surface
  2061. CheckForConstantRegisters();
  2062. pd = NULL; // the pointer will be invalid after exiting this function
  2063. // finish things up
  2064. if ( TestMaterialFlag( MF_DEFAULTED ) ) {
  2065. MakeDefault();
  2066. return false;
  2067. }
  2068. return true;
  2069. }
  2070. /*
  2071. ===================
  2072. idMaterial::Print
  2073. ===================
  2074. */
  2075. char *opNames[] = {
  2076. "OP_TYPE_ADD",
  2077. "OP_TYPE_SUBTRACT",
  2078. "OP_TYPE_MULTIPLY",
  2079. "OP_TYPE_DIVIDE",
  2080. "OP_TYPE_MOD",
  2081. "OP_TYPE_TABLE",
  2082. "OP_TYPE_GT",
  2083. "OP_TYPE_GE",
  2084. "OP_TYPE_LT",
  2085. "OP_TYPE_LE",
  2086. "OP_TYPE_EQ",
  2087. "OP_TYPE_NE",
  2088. "OP_TYPE_AND",
  2089. "OP_TYPE_OR"
  2090. };
  2091. void idMaterial::Print() const {
  2092. int i;
  2093. for ( i = EXP_REG_NUM_PREDEFINED ; i < GetNumRegisters() ; i++ ) {
  2094. common->Printf( "register %i: %f\n", i, expressionRegisters[i] );
  2095. }
  2096. common->Printf( "\n" );
  2097. for ( i = 0 ; i < numOps ; i++ ) {
  2098. const expOp_t *op = &ops[i];
  2099. if ( op->opType == OP_TYPE_TABLE ) {
  2100. common->Printf( "%i = %s[ %i ]\n", op->c, declManager->DeclByIndex( DECL_TABLE, op->a )->GetName(), op->b );
  2101. } else {
  2102. common->Printf( "%i = %i %s %i\n", op->c, op->a, opNames[ op->opType ], op->b );
  2103. }
  2104. }
  2105. }
  2106. /*
  2107. ===============
  2108. idMaterial::Save
  2109. ===============
  2110. */
  2111. bool idMaterial::Save( const char *fileName ) {
  2112. return ReplaceSourceFileText();
  2113. }
  2114. /*
  2115. ===============
  2116. idMaterial::AddReference
  2117. ===============
  2118. */
  2119. void idMaterial::AddReference() {
  2120. refCount++;
  2121. for ( int i = 0; i < numStages; i++ ) {
  2122. shaderStage_t *s = &stages[i];
  2123. if ( s->texture.image ) {
  2124. s->texture.image->AddReference();
  2125. }
  2126. }
  2127. }
  2128. /*
  2129. ===============
  2130. idMaterial::EvaluateRegisters
  2131. Parameters are taken from the localSpace and the renderView,
  2132. then all expressions are evaluated, leaving the material registers
  2133. set to their apropriate values.
  2134. ===============
  2135. */
  2136. void idMaterial::EvaluateRegisters( float *registers, const float shaderParms[MAX_ENTITY_SHADER_PARMS],
  2137. const viewDef_t *view, idSoundEmitter *soundEmitter ) const {
  2138. int i, b;
  2139. expOp_t *op;
  2140. // copy the material constants
  2141. for ( i = EXP_REG_NUM_PREDEFINED ; i < numRegisters ; i++ ) {
  2142. registers[i] = expressionRegisters[i];
  2143. }
  2144. // copy the local and global parameters
  2145. registers[EXP_REG_TIME] = view->floatTime;
  2146. registers[EXP_REG_PARM0] = shaderParms[0];
  2147. registers[EXP_REG_PARM1] = shaderParms[1];
  2148. registers[EXP_REG_PARM2] = shaderParms[2];
  2149. registers[EXP_REG_PARM3] = shaderParms[3];
  2150. registers[EXP_REG_PARM4] = shaderParms[4];
  2151. registers[EXP_REG_PARM5] = shaderParms[5];
  2152. registers[EXP_REG_PARM6] = shaderParms[6];
  2153. registers[EXP_REG_PARM7] = shaderParms[7];
  2154. registers[EXP_REG_PARM8] = shaderParms[8];
  2155. registers[EXP_REG_PARM9] = shaderParms[9];
  2156. registers[EXP_REG_PARM10] = shaderParms[10];
  2157. registers[EXP_REG_PARM11] = shaderParms[11];
  2158. registers[EXP_REG_GLOBAL0] = view->renderView.shaderParms[0];
  2159. registers[EXP_REG_GLOBAL1] = view->renderView.shaderParms[1];
  2160. registers[EXP_REG_GLOBAL2] = view->renderView.shaderParms[2];
  2161. registers[EXP_REG_GLOBAL3] = view->renderView.shaderParms[3];
  2162. registers[EXP_REG_GLOBAL4] = view->renderView.shaderParms[4];
  2163. registers[EXP_REG_GLOBAL5] = view->renderView.shaderParms[5];
  2164. registers[EXP_REG_GLOBAL6] = view->renderView.shaderParms[6];
  2165. registers[EXP_REG_GLOBAL7] = view->renderView.shaderParms[7];
  2166. op = ops;
  2167. for ( i = 0 ; i < numOps ; i++, op++ ) {
  2168. switch( op->opType ) {
  2169. case OP_TYPE_ADD:
  2170. registers[op->c] = registers[op->a] + registers[op->b];
  2171. break;
  2172. case OP_TYPE_SUBTRACT:
  2173. registers[op->c] = registers[op->a] - registers[op->b];
  2174. break;
  2175. case OP_TYPE_MULTIPLY:
  2176. registers[op->c] = registers[op->a] * registers[op->b];
  2177. break;
  2178. case OP_TYPE_DIVIDE:
  2179. registers[op->c] = registers[op->a] / registers[op->b];
  2180. break;
  2181. case OP_TYPE_MOD:
  2182. b = (int)registers[op->b];
  2183. b = b != 0 ? b : 1;
  2184. registers[op->c] = (int)registers[op->a] % b;
  2185. break;
  2186. case OP_TYPE_TABLE:
  2187. {
  2188. const idDeclTable *table = static_cast<const idDeclTable *>( declManager->DeclByIndex( DECL_TABLE, op->a ) );
  2189. registers[op->c] = table->TableLookup( registers[op->b] );
  2190. }
  2191. break;
  2192. case OP_TYPE_SOUND:
  2193. if ( soundEmitter ) {
  2194. registers[op->c] = soundEmitter->CurrentAmplitude();
  2195. } else {
  2196. registers[op->c] = 0;
  2197. }
  2198. break;
  2199. case OP_TYPE_GT:
  2200. registers[op->c] = registers[ op->a ] > registers[op->b];
  2201. break;
  2202. case OP_TYPE_GE:
  2203. registers[op->c] = registers[ op->a ] >= registers[op->b];
  2204. break;
  2205. case OP_TYPE_LT:
  2206. registers[op->c] = registers[ op->a ] < registers[op->b];
  2207. break;
  2208. case OP_TYPE_LE:
  2209. registers[op->c] = registers[ op->a ] <= registers[op->b];
  2210. break;
  2211. case OP_TYPE_EQ:
  2212. registers[op->c] = registers[ op->a ] == registers[op->b];
  2213. break;
  2214. case OP_TYPE_NE:
  2215. registers[op->c] = registers[ op->a ] != registers[op->b];
  2216. break;
  2217. case OP_TYPE_AND:
  2218. registers[op->c] = registers[ op->a ] && registers[op->b];
  2219. break;
  2220. case OP_TYPE_OR:
  2221. registers[op->c] = registers[ op->a ] || registers[op->b];
  2222. break;
  2223. default:
  2224. common->FatalError( "R_EvaluateExpression: bad opcode" );
  2225. }
  2226. }
  2227. }
  2228. /*
  2229. =============
  2230. idMaterial::Texgen
  2231. =============
  2232. */
  2233. texgen_t idMaterial::Texgen() const {
  2234. if ( stages ) {
  2235. for ( int i = 0; i < numStages; i++ ) {
  2236. if ( stages[ i ].texture.texgen != TG_EXPLICIT ) {
  2237. return stages[ i ].texture.texgen;
  2238. }
  2239. }
  2240. }
  2241. return TG_EXPLICIT;
  2242. }
  2243. /*
  2244. =============
  2245. idMaterial::GetImageWidth
  2246. =============
  2247. */
  2248. int idMaterial::GetImageWidth( void ) const {
  2249. assert( GetStage(0) && GetStage(0)->texture.image );
  2250. return GetStage(0)->texture.image->uploadWidth;
  2251. }
  2252. /*
  2253. =============
  2254. idMaterial::GetImageHeight
  2255. =============
  2256. */
  2257. int idMaterial::GetImageHeight( void ) const {
  2258. assert( GetStage(0) && GetStage(0)->texture.image );
  2259. return GetStage(0)->texture.image->uploadHeight;
  2260. }
  2261. /*
  2262. =============
  2263. idMaterial::CinematicLength
  2264. =============
  2265. */
  2266. int idMaterial::CinematicLength() const {
  2267. if ( !stages || !stages[0].texture.cinematic ) {
  2268. return 0;
  2269. }
  2270. return stages[0].texture.cinematic->AnimationLength();
  2271. }
  2272. /*
  2273. =============
  2274. idMaterial::UpdateCinematic
  2275. =============
  2276. */
  2277. void idMaterial::UpdateCinematic( int time ) const {
  2278. if ( !stages || !stages[0].texture.cinematic || !backEnd.viewDef ) {
  2279. return;
  2280. }
  2281. stages[0].texture.cinematic->ImageForTime( tr.primaryRenderView.time );
  2282. }
  2283. /*
  2284. =============
  2285. idMaterial::CloseCinematic
  2286. =============
  2287. */
  2288. void idMaterial::CloseCinematic( void ) const {
  2289. for( int i = 0; i < numStages; i++ ) {
  2290. if ( stages[i].texture.cinematic ) {
  2291. stages[i].texture.cinematic->Close();
  2292. delete stages[i].texture.cinematic;
  2293. stages[i].texture.cinematic = NULL;
  2294. }
  2295. }
  2296. }
  2297. /*
  2298. =============
  2299. idMaterial::ResetCinematicTime
  2300. =============
  2301. */
  2302. void idMaterial::ResetCinematicTime( int time ) const {
  2303. for( int i = 0; i < numStages; i++ ) {
  2304. if ( stages[i].texture.cinematic ) {
  2305. stages[i].texture.cinematic->ResetTime( time );
  2306. }
  2307. }
  2308. }
  2309. /*
  2310. =============
  2311. idMaterial::ConstantRegisters
  2312. =============
  2313. */
  2314. const float *idMaterial::ConstantRegisters() const {
  2315. if ( !r_useConstantMaterials.GetBool() ) {
  2316. return NULL;
  2317. }
  2318. return constantRegisters;
  2319. }
  2320. /*
  2321. ==================
  2322. idMaterial::CheckForConstantRegisters
  2323. As of 5/2/03, about half of the unique materials loaded on typical
  2324. maps are constant, but 2/3 of the surface references are.
  2325. This is probably an optimization of dubious value.
  2326. ==================
  2327. */
  2328. static int c_constant, c_variable;
  2329. void idMaterial::CheckForConstantRegisters() {
  2330. if ( !pd->registersAreConstant ) {
  2331. return;
  2332. }
  2333. // evaluate the registers once, and save them
  2334. constantRegisters = (float *)R_ClearedStaticAlloc( GetNumRegisters() * sizeof( float ) );
  2335. float shaderParms[MAX_ENTITY_SHADER_PARMS];
  2336. memset( shaderParms, 0, sizeof( shaderParms ) );
  2337. viewDef_t viewDef;
  2338. memset( &viewDef, 0, sizeof( viewDef ) );
  2339. EvaluateRegisters( constantRegisters, shaderParms, &viewDef, 0 );
  2340. }
  2341. /*
  2342. ===================
  2343. idMaterial::ImageName
  2344. ===================
  2345. */
  2346. const char *idMaterial::ImageName( void ) const {
  2347. if ( numStages == 0 ) {
  2348. return "_scratch";
  2349. }
  2350. idImage *image = stages[0].texture.image;
  2351. if ( image ) {
  2352. return image->imgName;
  2353. }
  2354. return "_scratch";
  2355. }
  2356. /*
  2357. ===================
  2358. idMaterial::SetImageClassifications
  2359. Just for image resource tracking.
  2360. ===================
  2361. */
  2362. void idMaterial::SetImageClassifications( int tag ) const {
  2363. for ( int i = 0 ; i < numStages ; i++ ) {
  2364. idImage *image = stages[i].texture.image;
  2365. if ( image ) {
  2366. image->SetClassification( tag );
  2367. }
  2368. }
  2369. }
  2370. /*
  2371. =================
  2372. idMaterial::Size
  2373. =================
  2374. */
  2375. size_t idMaterial::Size( void ) const {
  2376. return sizeof( idMaterial );
  2377. }
  2378. /*
  2379. ===================
  2380. idMaterial::SetDefaultText
  2381. ===================
  2382. */
  2383. bool idMaterial::SetDefaultText( void ) {
  2384. // if there exists an image with the same name
  2385. if ( 1 ) { //fileSystem->ReadFile( GetName(), NULL ) != -1 ) {
  2386. char generated[2048];
  2387. idStr::snPrintf( generated, sizeof( generated ),
  2388. "material %s // IMPLICITLY GENERATED\n"
  2389. "{\n"
  2390. "{\n"
  2391. "blend blend\n"
  2392. "colored\n"
  2393. "map \"%s\"\n"
  2394. "clamp\n"
  2395. "}\n"
  2396. "}\n", GetName(), GetName() );
  2397. SetText( generated );
  2398. return true;
  2399. } else {
  2400. return false;
  2401. }
  2402. }
  2403. /*
  2404. ===================
  2405. idMaterial::DefaultDefinition
  2406. ===================
  2407. */
  2408. const char *idMaterial::DefaultDefinition() const {
  2409. return
  2410. "{\n"
  2411. "\t" "{\n"
  2412. "\t\t" "blend\tblend\n"
  2413. "\t\t" "map\t\t_default\n"
  2414. "\t" "}\n"
  2415. "}";
  2416. }
  2417. /*
  2418. ===================
  2419. idMaterial::GetBumpStage
  2420. ===================
  2421. */
  2422. const shaderStage_t *idMaterial::GetBumpStage( void ) const {
  2423. for ( int i = 0 ; i < numStages ; i++ ) {
  2424. if ( stages[i].lighting == SL_BUMP ) {
  2425. return &stages[i];
  2426. }
  2427. }
  2428. return NULL;
  2429. }
  2430. /*
  2431. ===================
  2432. idMaterial::ReloadImages
  2433. ===================
  2434. */
  2435. void idMaterial::ReloadImages( bool force ) const
  2436. {
  2437. for ( int i = 0 ; i < numStages ; i++ ) {
  2438. if ( stages[i].newStage ) {
  2439. for ( int j = 0 ; j < stages[i].newStage->numFragmentProgramImages ; j++ ) {
  2440. if ( stages[i].newStage->fragmentProgramImages[j] ) {
  2441. stages[i].newStage->fragmentProgramImages[j]->Reload( false, force );
  2442. }
  2443. }
  2444. } else if ( stages[i].texture.image ) {
  2445. stages[i].texture.image->Reload( false, force );
  2446. }
  2447. }
  2448. }