shaders.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1999-2005 Id Software, Inc.
  4. This file is part of Quake III Arena source code.
  5. Quake III Arena source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake III Arena source code is distributed in the hope that it will be
  10. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Foobar; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. #include <string.h>
  19. #include <math.h>
  20. #include "cmdlib.h"
  21. #include "mathlib.h"
  22. #include "imagelib.h"
  23. #include "scriplib.h"
  24. #ifdef _TTIMOBUILD
  25. #include "../common/qfiles.h"
  26. #include "../common/surfaceflags.h"
  27. #else
  28. #include "../code/qcommon/qfiles.h"
  29. #include "../code/game/surfaceflags.h"
  30. #endif
  31. #include "shaders.h"
  32. #ifdef _WIN32
  33. #ifdef _TTIMOBUILD
  34. #include "pakstuff.h"
  35. #include "jpeglib.h"
  36. #else
  37. #include "../libs/pakstuff.h"
  38. #include "../libs/jpeglib.h"
  39. #endif
  40. #endif
  41. // 5% backsplash by default
  42. #define DEFAULT_BACKSPLASH_FRACTION 0.05
  43. #define DEFAULT_BACKSPLASH_DISTANCE 24
  44. #define MAX_SURFACE_INFO 4096
  45. shaderInfo_t defaultInfo;
  46. shaderInfo_t shaderInfo[MAX_SURFACE_INFO];
  47. int numShaderInfo;
  48. typedef struct {
  49. char *name;
  50. int clearSolid, surfaceFlags, contents;
  51. } infoParm_t;
  52. infoParm_t infoParms[] = {
  53. // server relevant contents
  54. {"water", 1, 0, CONTENTS_WATER },
  55. {"slime", 1, 0, CONTENTS_SLIME }, // mildly damaging
  56. {"lava", 1, 0, CONTENTS_LAVA }, // very damaging
  57. {"playerclip", 1, 0, CONTENTS_PLAYERCLIP },
  58. {"monsterclip", 1, 0, CONTENTS_MONSTERCLIP },
  59. {"nodrop", 1, 0, CONTENTS_NODROP }, // don't drop items or leave bodies (death fog, lava, etc)
  60. {"nonsolid", 1, SURF_NONSOLID, 0}, // clears the solid flag
  61. // utility relevant attributes
  62. {"origin", 1, 0, CONTENTS_ORIGIN }, // center of rotating brushes
  63. {"trans", 0, 0, CONTENTS_TRANSLUCENT }, // don't eat contained surfaces
  64. {"detail", 0, 0, CONTENTS_DETAIL }, // don't include in structural bsp
  65. {"structural", 0, 0, CONTENTS_STRUCTURAL }, // force into structural bsp even if trnas
  66. {"areaportal", 1, 0, CONTENTS_AREAPORTAL }, // divides areas
  67. {"clusterportal",1, 0, CONTENTS_CLUSTERPORTAL },// for bots
  68. {"donotenter", 1, 0, CONTENTS_DONOTENTER }, // for bots
  69. {"botclip", 1, 0, CONTENTS_BOTCLIP }, // for bots
  70. {"nobotclip", 0, 0, CONTENTS_NOBOTCLIP }, // don't use for bot clipping
  71. {"fog", 1, 0, CONTENTS_FOG}, // carves surfaces entering
  72. {"sky", 0, SURF_SKY, 0 }, // emit light from an environment map
  73. {"lightfilter", 0, SURF_LIGHTFILTER, 0 }, // filter light going through it
  74. {"alphashadow", 0, SURF_ALPHASHADOW, 0 }, // test light on a per-pixel basis
  75. {"hint", 0, SURF_HINT, 0 }, // use as a primary splitter
  76. // server attributes
  77. {"slick", 0, SURF_SLICK, 0 },
  78. {"noimpact", 0, SURF_NOIMPACT, 0 }, // don't make impact explosions or marks
  79. {"nomarks", 0, SURF_NOMARKS, 0 }, // don't make impact marks, but still explode
  80. {"ladder", 0, SURF_LADDER, 0 },
  81. {"nodamage", 0, SURF_NODAMAGE, 0 },
  82. {"metalsteps", 0, SURF_METALSTEPS,0 },
  83. {"flesh", 0, SURF_FLESH, 0 },
  84. {"nosteps", 0, SURF_NOSTEPS, 0 },
  85. // drawsurf attributes
  86. {"nodraw", 0, SURF_NODRAW, 0 }, // don't generate a drawsurface (or a lightmap)
  87. {"pointlight", 0, SURF_POINTLIGHT, 0 }, // sample lighting at vertexes
  88. {"nolightmap", 0, SURF_NOLIGHTMAP,0 }, // don't generate a lightmap
  89. {"nodlight", 0, SURF_NODLIGHT, 0 }, // don't ever add dynamic lights
  90. {"dust", 0, SURF_DUST, 0} // leave dust trail when walking on this surface
  91. };
  92. /*
  93. ===============
  94. LoadShaderImage
  95. ===============
  96. */
  97. byte* LoadImageFile(char *filename, qboolean *bTGA)
  98. {
  99. byte *buffer = NULL;
  100. int nLen = 0;
  101. *bTGA = qtrue;
  102. if (FileExists(filename))
  103. {
  104. LoadFileBlock(filename, &buffer);
  105. }
  106. #ifdef _WIN32
  107. else
  108. {
  109. PakLoadAnyFile(filename, &buffer);
  110. }
  111. #endif
  112. if ( buffer == NULL)
  113. {
  114. nLen = strlen(filename);
  115. filename[nLen-3] = 'j';
  116. filename[nLen-2] = 'p';
  117. filename[nLen-1] = 'g';
  118. if (FileExists(filename))
  119. {
  120. LoadFileBlock(filename, &buffer);
  121. }
  122. #ifdef _WIN32
  123. else
  124. {
  125. PakLoadAnyFile(filename, &buffer);
  126. }
  127. #endif
  128. if ( buffer )
  129. {
  130. *bTGA = qfalse;
  131. }
  132. }
  133. return buffer;
  134. }
  135. /*
  136. ===============
  137. LoadShaderImage
  138. ===============
  139. */
  140. static void LoadShaderImage( shaderInfo_t *si ) {
  141. char filename[1024];
  142. int i, count;
  143. float color[4];
  144. byte *buffer;
  145. qboolean bTGA = qtrue;
  146. // look for the lightimage if it is specified
  147. if ( si->lightimage[0] ) {
  148. sprintf( filename, "%s%s", gamedir, si->lightimage );
  149. DefaultExtension( filename, ".tga" );
  150. buffer = LoadImageFile(filename, &bTGA);
  151. if ( buffer != NULL) {
  152. goto loadTga;
  153. }
  154. }
  155. // look for the editorimage if it is specified
  156. if ( si->editorimage[0] ) {
  157. sprintf( filename, "%s%s", gamedir, si->editorimage );
  158. DefaultExtension( filename, ".tga" );
  159. buffer = LoadImageFile(filename, &bTGA);
  160. if ( buffer != NULL) {
  161. goto loadTga;
  162. }
  163. }
  164. // just try the shader name with a .tga
  165. // on unix, we have case sensitivity problems...
  166. sprintf( filename, "%s%s.tga", gamedir, si->shader );
  167. buffer = LoadImageFile(filename, &bTGA);
  168. if ( buffer != NULL) {
  169. goto loadTga;
  170. }
  171. sprintf( filename, "%s%s.TGA", gamedir, si->shader );
  172. buffer = LoadImageFile(filename, &bTGA);
  173. if ( buffer != NULL) {
  174. goto loadTga;
  175. }
  176. // couldn't load anything
  177. _printf("WARNING: Couldn't find image for shader %s\n", si->shader );
  178. si->color[0] = 1;
  179. si->color[1] = 1;
  180. si->color[2] = 1;
  181. si->width = 64;
  182. si->height = 64;
  183. si->pixels = malloc( si->width * si->height * 4 );
  184. memset ( si->pixels, 255, si->width * si->height * 4 );
  185. return;
  186. // load the image to get dimensions and color
  187. loadTga:
  188. if ( bTGA) {
  189. LoadTGABuffer( buffer, &si->pixels, &si->width, &si->height );
  190. }
  191. else {
  192. #ifdef _WIN32
  193. LoadJPGBuff(buffer, &si->pixels, &si->width, &si->height );
  194. #endif
  195. }
  196. free(buffer);
  197. count = si->width * si->height;
  198. VectorClear( color );
  199. color[ 3 ] = 0;
  200. for ( i = 0 ; i < count ; i++ ) {
  201. color[0] += si->pixels[ i * 4 + 0 ];
  202. color[1] += si->pixels[ i * 4 + 1 ];
  203. color[2] += si->pixels[ i * 4 + 2 ];
  204. color[3] += si->pixels[ i * 4 + 3 ];
  205. }
  206. ColorNormalize( color, si->color );
  207. VectorScale( color, 1.0/count, si->averageColor );
  208. }
  209. /*
  210. ===============
  211. AllocShaderInfo
  212. ===============
  213. */
  214. static shaderInfo_t *AllocShaderInfo( void ) {
  215. shaderInfo_t *si;
  216. if ( numShaderInfo == MAX_SURFACE_INFO ) {
  217. Error( "MAX_SURFACE_INFO" );
  218. }
  219. si = &shaderInfo[ numShaderInfo ];
  220. numShaderInfo++;
  221. // set defaults
  222. si->contents = CONTENTS_SOLID;
  223. si->backsplashFraction = DEFAULT_BACKSPLASH_FRACTION;
  224. si->backsplashDistance = DEFAULT_BACKSPLASH_DISTANCE;
  225. si->lightmapSampleSize = 0;
  226. si->forceTraceLight = qfalse;
  227. si->forceVLight = qfalse;
  228. si->patchShadows = qfalse;
  229. si->vertexShadows = qfalse;
  230. si->noVertexShadows = qfalse;
  231. si->forceSunLight = qfalse;
  232. si->vertexScale = 1.0;
  233. si->notjunc = qfalse;
  234. return si;
  235. }
  236. /*
  237. ===============
  238. ShaderInfoForShader
  239. ===============
  240. */
  241. shaderInfo_t *ShaderInfoForShader( const char *shaderName ) {
  242. int i;
  243. shaderInfo_t *si;
  244. char shader[MAX_QPATH];
  245. // strip off extension
  246. strcpy( shader, shaderName );
  247. StripExtension( shader );
  248. // search for it
  249. for ( i = 0 ; i < numShaderInfo ; i++ ) {
  250. si = &shaderInfo[ i ];
  251. if ( !Q_stricmp( shader, si->shader ) ) {
  252. if ( !si->width ) {
  253. LoadShaderImage( si );
  254. }
  255. return si;
  256. }
  257. }
  258. si = AllocShaderInfo();
  259. strcpy( si->shader, shader );
  260. LoadShaderImage( si );
  261. return si;
  262. }
  263. /*
  264. ===============
  265. ParseShaderFile
  266. ===============
  267. */
  268. static void ParseShaderFile( const char *filename ) {
  269. int i;
  270. int numInfoParms = sizeof(infoParms) / sizeof(infoParms[0]);
  271. shaderInfo_t *si;
  272. // qprintf( "shaderFile: %s\n", filename );
  273. LoadScriptFile( filename );
  274. while ( 1 ) {
  275. if ( !GetToken( qtrue ) ) {
  276. break;
  277. }
  278. si = AllocShaderInfo();
  279. strcpy( si->shader, token );
  280. MatchToken( "{" );
  281. while ( 1 ) {
  282. if ( !GetToken( qtrue ) ) {
  283. break;
  284. }
  285. if ( !strcmp( token, "}" ) ) {
  286. break;
  287. }
  288. // skip internal braced sections
  289. if ( !strcmp( token, "{" ) ) {
  290. si->hasPasses = qtrue;
  291. while ( 1 ) {
  292. if ( !GetToken( qtrue ) ) {
  293. break;
  294. }
  295. if ( !strcmp( token, "}" ) ) {
  296. break;
  297. }
  298. }
  299. continue;
  300. }
  301. if ( !Q_stricmp( token, "surfaceparm" ) ) {
  302. GetToken( qfalse );
  303. for ( i = 0 ; i < numInfoParms ; i++ ) {
  304. if ( !Q_stricmp( token, infoParms[i].name ) ) {
  305. si->surfaceFlags |= infoParms[i].surfaceFlags;
  306. si->contents |= infoParms[i].contents;
  307. if ( infoParms[i].clearSolid ) {
  308. si->contents &= ~CONTENTS_SOLID;
  309. }
  310. break;
  311. }
  312. }
  313. if ( i == numInfoParms ) {
  314. // we will silently ignore all tokens beginning with qer,
  315. // which are QuakeEdRadient parameters
  316. if ( Q_strncasecmp( token, "qer", 3 ) ) {
  317. _printf( "Unknown surfaceparm: \"%s\"\n", token );
  318. }
  319. }
  320. continue;
  321. }
  322. // qer_editorimage <image>
  323. if ( !Q_stricmp( token, "qer_editorimage" ) ) {
  324. GetToken( qfalse );
  325. strcpy( si->editorimage, token );
  326. DefaultExtension( si->editorimage, ".tga" );
  327. continue;
  328. }
  329. // q3map_lightimage <image>
  330. if ( !Q_stricmp( token, "q3map_lightimage" ) ) {
  331. GetToken( qfalse );
  332. strcpy( si->lightimage, token );
  333. DefaultExtension( si->lightimage, ".tga" );
  334. continue;
  335. }
  336. // q3map_surfacelight <value>
  337. if ( !Q_stricmp( token, "q3map_surfacelight" ) ) {
  338. GetToken( qfalse );
  339. si->value = atoi( token );
  340. continue;
  341. }
  342. // q3map_lightsubdivide <value>
  343. if ( !Q_stricmp( token, "q3map_lightsubdivide" ) ) {
  344. GetToken( qfalse );
  345. si->lightSubdivide = atoi( token );
  346. continue;
  347. }
  348. // q3map_lightmapsamplesize <value>
  349. if ( !Q_stricmp( token, "q3map_lightmapsamplesize" ) ) {
  350. GetToken( qfalse );
  351. si->lightmapSampleSize = atoi( token );
  352. continue;
  353. }
  354. // q3map_tracelight
  355. if ( !Q_stricmp( token, "q3map_tracelight" ) ) {
  356. si->forceTraceLight = qtrue;
  357. continue;
  358. }
  359. // q3map_vlight
  360. if ( !Q_stricmp( token, "q3map_vlight" ) ) {
  361. si->forceVLight = qtrue;
  362. continue;
  363. }
  364. // q3map_patchshadows
  365. if ( !Q_stricmp( token, "q3map_patchshadows" ) ) {
  366. si->patchShadows = qtrue;
  367. continue;
  368. }
  369. // q3map_vertexshadows
  370. if ( !Q_stricmp( token, "q3map_vertexshadows" ) ) {
  371. si->vertexShadows = qtrue;
  372. continue;
  373. }
  374. // q3map_novertexshadows
  375. if ( !Q_stricmp( token, "q3map_novertexshadows" ) ) {
  376. si->noVertexShadows = qtrue;
  377. continue;
  378. }
  379. // q3map_forcesunlight
  380. if ( !Q_stricmp( token, "q3map_forcesunlight" ) ) {
  381. si->forceSunLight = qtrue;
  382. continue;
  383. }
  384. // q3map_vertexscale
  385. if ( !Q_stricmp( token, "q3map_vertexscale" ) ) {
  386. GetToken( qfalse );
  387. si->vertexScale = atof(token);
  388. continue;
  389. }
  390. // q3map_notjunc
  391. if ( !Q_stricmp( token, "q3map_notjunc" ) ) {
  392. si->notjunc = qtrue;
  393. continue;
  394. }
  395. // q3map_globaltexture
  396. if ( !Q_stricmp( token, "q3map_globaltexture" ) ) {
  397. si->globalTexture = qtrue;
  398. continue;
  399. }
  400. // q3map_backsplash <percent> <distance>
  401. if ( !Q_stricmp( token, "q3map_backsplash" ) ) {
  402. GetToken( qfalse );
  403. si->backsplashFraction = atof( token ) * 0.01;
  404. GetToken( qfalse );
  405. si->backsplashDistance = atof( token );
  406. continue;
  407. }
  408. // q3map_backshader <shader>
  409. if ( !Q_stricmp( token, "q3map_backshader" ) ) {
  410. GetToken( qfalse );
  411. strcpy( si->backShader, token );
  412. continue;
  413. }
  414. // q3map_flare <shader>
  415. if ( !Q_stricmp( token, "q3map_flare" ) ) {
  416. GetToken( qfalse );
  417. strcpy( si->flareShader, token );
  418. continue;
  419. }
  420. // light <value>
  421. // old style flare specification
  422. if ( !Q_stricmp( token, "light" ) ) {
  423. GetToken( qfalse );
  424. strcpy( si->flareShader, "flareshader" );
  425. continue;
  426. }
  427. // q3map_sun <red> <green> <blue> <intensity> <degrees> <elivation>
  428. // color will be normalized, so it doesn't matter what range you use
  429. // intensity falls off with angle but not distance 100 is a fairly bright sun
  430. // degree of 0 = from the east, 90 = north, etc. altitude of 0 = sunrise/set, 90 = noon
  431. if ( !Q_stricmp( token, "q3map_sun" ) ) {
  432. float a, b;
  433. GetToken( qfalse );
  434. si->sunLight[0] = atof( token );
  435. GetToken( qfalse );
  436. si->sunLight[1] = atof( token );
  437. GetToken( qfalse );
  438. si->sunLight[2] = atof( token );
  439. VectorNormalize( si->sunLight, si->sunLight);
  440. GetToken( qfalse );
  441. a = atof( token );
  442. VectorScale( si->sunLight, a, si->sunLight);
  443. GetToken( qfalse );
  444. a = atof( token );
  445. a = a / 180 * Q_PI;
  446. GetToken( qfalse );
  447. b = atof( token );
  448. b = b / 180 * Q_PI;
  449. si->sunDirection[0] = cos( a ) * cos( b );
  450. si->sunDirection[1] = sin( a ) * cos( b );
  451. si->sunDirection[2] = sin( b );
  452. si->surfaceFlags |= SURF_SKY;
  453. continue;
  454. }
  455. // tesssize is used to force liquid surfaces to subdivide
  456. if ( !Q_stricmp( token, "tesssize" ) ) {
  457. GetToken( qfalse );
  458. si->subdivisions = atof( token );
  459. continue;
  460. }
  461. // cull none will set twoSided
  462. if ( !Q_stricmp( token, "cull" ) ) {
  463. GetToken( qfalse );
  464. if ( !Q_stricmp( token, "none" ) ) {
  465. si->twoSided = qtrue;
  466. }
  467. continue;
  468. }
  469. // deformVertexes autosprite[2]
  470. // we catch this so autosprited surfaces become point
  471. // lights instead of area lights
  472. if ( !Q_stricmp( token, "deformVertexes" ) ) {
  473. GetToken( qfalse );
  474. if ( !Q_strncasecmp( token, "autosprite", 10 ) ) {
  475. si->autosprite = qtrue;
  476. si->contents = CONTENTS_DETAIL;
  477. }
  478. continue;
  479. }
  480. // ignore all other tokens on the line
  481. while ( TokenAvailable() ) {
  482. GetToken( qfalse );
  483. }
  484. }
  485. }
  486. }
  487. /*
  488. ===============
  489. LoadShaderInfo
  490. ===============
  491. */
  492. #define MAX_SHADER_FILES 64
  493. void LoadShaderInfo( void ) {
  494. char filename[1024];
  495. int i;
  496. char *shaderFiles[MAX_SHADER_FILES];
  497. int numShaderFiles;
  498. sprintf( filename, "%sscripts/shaderlist.txt", gamedir );
  499. LoadScriptFile( filename );
  500. numShaderFiles = 0;
  501. while ( 1 ) {
  502. if ( !GetToken( qtrue ) ) {
  503. break;
  504. }
  505. shaderFiles[numShaderFiles] = malloc(MAX_OS_PATH);
  506. strcpy( shaderFiles[ numShaderFiles ], token );
  507. numShaderFiles++;
  508. }
  509. for ( i = 0 ; i < numShaderFiles ; i++ ) {
  510. sprintf( filename, "%sscripts/%s.shader", gamedir, shaderFiles[i] );
  511. ParseShaderFile( filename );
  512. free(shaderFiles[i]);
  513. }
  514. qprintf( "%5i shaderInfo\n", numShaderInfo);
  515. }