r_light.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. /*
  2. Copyright (C) 1997-2001 Id Software, Inc.
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. // r_light.c
  16. #include "r_local.h"
  17. int r_dlightframecount;
  18. /*
  19. =============================================================================
  20. DYNAMIC LIGHTS
  21. =============================================================================
  22. */
  23. /*
  24. =============
  25. R_MarkLights
  26. =============
  27. */
  28. void R_MarkLights (dlight_t *light, int bit, mnode_t *node)
  29. {
  30. mplane_t *splitplane;
  31. float dist;
  32. msurface_t *surf;
  33. int i;
  34. if (node->contents != -1)
  35. return;
  36. splitplane = node->plane;
  37. dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist;
  38. //=====
  39. //PGM
  40. i=light->intensity;
  41. if(i<0)
  42. i=-i;
  43. //PGM
  44. //=====
  45. if (dist > i) // PGM (dist > light->intensity)
  46. {
  47. R_MarkLights (light, bit, node->children[0]);
  48. return;
  49. }
  50. if (dist < -i) // PGM (dist < -light->intensity)
  51. {
  52. R_MarkLights (light, bit, node->children[1]);
  53. return;
  54. }
  55. // mark the polygons
  56. surf = r_worldmodel->surfaces + node->firstsurface;
  57. for (i=0 ; i<node->numsurfaces ; i++, surf++)
  58. {
  59. if (surf->dlightframe != r_dlightframecount)
  60. {
  61. surf->dlightbits = 0;
  62. surf->dlightframe = r_dlightframecount;
  63. }
  64. surf->dlightbits |= bit;
  65. }
  66. R_MarkLights (light, bit, node->children[0]);
  67. R_MarkLights (light, bit, node->children[1]);
  68. }
  69. /*
  70. =============
  71. R_PushDlights
  72. =============
  73. */
  74. void R_PushDlights (model_t *model)
  75. {
  76. int i;
  77. dlight_t *l;
  78. r_dlightframecount = r_framecount;
  79. for (i=0, l = r_newrefdef.dlights ; i<r_newrefdef.num_dlights ; i++, l++)
  80. {
  81. R_MarkLights ( l, 1<<i,
  82. model->nodes + model->firstnode);
  83. }
  84. }
  85. /*
  86. =============================================================================
  87. LIGHT SAMPLING
  88. =============================================================================
  89. */
  90. vec3_t pointcolor;
  91. mplane_t *lightplane; // used as shadow plane
  92. vec3_t lightspot;
  93. int RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end)
  94. {
  95. float front, back, frac;
  96. int side;
  97. mplane_t *plane;
  98. vec3_t mid;
  99. msurface_t *surf;
  100. int s, t, ds, dt;
  101. int i;
  102. mtexinfo_t *tex;
  103. byte *lightmap;
  104. float *scales;
  105. int maps;
  106. float samp;
  107. int r;
  108. if (node->contents != -1)
  109. return -1; // didn't hit anything
  110. // calculate mid point
  111. // FIXME: optimize for axial
  112. plane = node->plane;
  113. front = DotProduct (start, plane->normal) - plane->dist;
  114. back = DotProduct (end, plane->normal) - plane->dist;
  115. side = front < 0;
  116. if ( (back < 0) == side)
  117. return RecursiveLightPoint (node->children[side], start, end);
  118. frac = front / (front-back);
  119. mid[0] = start[0] + (end[0] - start[0])*frac;
  120. mid[1] = start[1] + (end[1] - start[1])*frac;
  121. mid[2] = start[2] + (end[2] - start[2])*frac;
  122. if (plane->type < 3) // axial planes
  123. mid[plane->type] = plane->dist;
  124. // go down front side
  125. r = RecursiveLightPoint (node->children[side], start, mid);
  126. if (r >= 0)
  127. return r; // hit something
  128. if ( (back < 0) == side )
  129. return -1; // didn't hit anuthing
  130. // check for impact on this node
  131. VectorCopy (mid, lightspot);
  132. lightplane = plane;
  133. surf = r_worldmodel->surfaces + node->firstsurface;
  134. for (i=0 ; i<node->numsurfaces ; i++, surf++)
  135. {
  136. if (surf->flags&(SURF_DRAWTURB|SURF_DRAWSKY))
  137. continue; // no lightmaps
  138. tex = surf->texinfo;
  139. s = DotProduct (mid, tex->vecs[0]) + tex->vecs[0][3];
  140. t = DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3];
  141. if (s < surf->texturemins[0] ||
  142. t < surf->texturemins[1])
  143. continue;
  144. ds = s - surf->texturemins[0];
  145. dt = t - surf->texturemins[1];
  146. if ( ds > surf->extents[0] || dt > surf->extents[1] )
  147. continue;
  148. if (!surf->samples)
  149. return 0;
  150. ds >>= 4;
  151. dt >>= 4;
  152. lightmap = surf->samples;
  153. VectorCopy (vec3_origin, pointcolor);
  154. if (lightmap)
  155. {
  156. lightmap += dt * ((surf->extents[0]>>4)+1) + ds;
  157. for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
  158. maps++)
  159. {
  160. samp = *lightmap * /* 0.5 * */ (1.0/255); // adjust for gl scale
  161. scales = r_newrefdef.lightstyles[surf->styles[maps]].rgb;
  162. VectorMA (pointcolor, samp, scales, pointcolor);
  163. lightmap += ((surf->extents[0]>>4)+1) *
  164. ((surf->extents[1]>>4)+1);
  165. }
  166. }
  167. return 1;
  168. }
  169. // go down back side
  170. return RecursiveLightPoint (node->children[!side], mid, end);
  171. }
  172. /*
  173. ===============
  174. R_LightPoint
  175. ===============
  176. */
  177. void R_LightPoint (vec3_t p, vec3_t color)
  178. {
  179. vec3_t end;
  180. float r;
  181. int lnum;
  182. dlight_t *dl;
  183. float light;
  184. vec3_t dist;
  185. float add;
  186. if (!r_worldmodel->lightdata)
  187. {
  188. color[0] = color[1] = color[2] = 1.0;
  189. return;
  190. }
  191. end[0] = p[0];
  192. end[1] = p[1];
  193. end[2] = p[2] - 2048;
  194. r = RecursiveLightPoint (r_worldmodel->nodes, p, end);
  195. if (r == -1)
  196. {
  197. VectorCopy (vec3_origin, color);
  198. }
  199. else
  200. {
  201. VectorCopy (pointcolor, color);
  202. }
  203. //
  204. // add dynamic lights
  205. //
  206. light = 0;
  207. for (lnum=0 ; lnum<r_newrefdef.num_dlights ; lnum++)
  208. {
  209. dl = &r_newrefdef.dlights[lnum];
  210. VectorSubtract (currententity->origin,
  211. dl->origin,
  212. dist);
  213. add = dl->intensity - VectorLength(dist);
  214. add *= (1.0/256);
  215. if (add > 0)
  216. {
  217. VectorMA (color, add, dl->color, color);
  218. }
  219. }
  220. }
  221. //===================================================================
  222. unsigned blocklights[1024]; // allow some very large lightmaps
  223. /*
  224. ===============
  225. R_AddDynamicLights
  226. ===============
  227. */
  228. void R_AddDynamicLights (void)
  229. {
  230. msurface_t *surf;
  231. int lnum;
  232. int sd, td;
  233. float dist, rad, minlight;
  234. vec3_t impact, local;
  235. int s, t;
  236. int i;
  237. int smax, tmax;
  238. mtexinfo_t *tex;
  239. dlight_t *dl;
  240. int negativeLight; //PGM
  241. surf = r_drawsurf.surf;
  242. smax = (surf->extents[0]>>4)+1;
  243. tmax = (surf->extents[1]>>4)+1;
  244. tex = surf->texinfo;
  245. for (lnum=0 ; lnum<r_newrefdef.num_dlights ; lnum++)
  246. {
  247. if ( !(surf->dlightbits & (1<<lnum) ) )
  248. continue; // not lit by this light
  249. dl = &r_newrefdef.dlights[lnum];
  250. rad = dl->intensity;
  251. //=====
  252. //PGM
  253. negativeLight = 0;
  254. if(rad < 0)
  255. {
  256. negativeLight = 1;
  257. rad = -rad;
  258. }
  259. //PGM
  260. //=====
  261. dist = DotProduct (dl->origin, surf->plane->normal) -
  262. surf->plane->dist;
  263. rad -= fabs(dist);
  264. minlight = 32; // dl->minlight;
  265. if (rad < minlight)
  266. continue;
  267. minlight = rad - minlight;
  268. for (i=0 ; i<3 ; i++)
  269. {
  270. impact[i] = dl->origin[i] -
  271. surf->plane->normal[i]*dist;
  272. }
  273. local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3];
  274. local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3];
  275. local[0] -= surf->texturemins[0];
  276. local[1] -= surf->texturemins[1];
  277. for (t = 0 ; t<tmax ; t++)
  278. {
  279. td = local[1] - t*16;
  280. if (td < 0)
  281. td = -td;
  282. for (s=0 ; s<smax ; s++)
  283. {
  284. sd = local[0] - s*16;
  285. if (sd < 0)
  286. sd = -sd;
  287. if (sd > td)
  288. dist = sd + (td>>1);
  289. else
  290. dist = td + (sd>>1);
  291. //====
  292. //PGM
  293. if(!negativeLight)
  294. {
  295. if (dist < minlight)
  296. blocklights[t*smax + s] += (rad - dist)*256;
  297. }
  298. else
  299. {
  300. if (dist < minlight)
  301. blocklights[t*smax + s] -= (rad - dist)*256;
  302. if(blocklights[t*smax + s] < minlight)
  303. blocklights[t*smax + s] = minlight;
  304. }
  305. //PGM
  306. //====
  307. }
  308. }
  309. }
  310. }
  311. /*
  312. ===============
  313. R_BuildLightMap
  314. Combine and scale multiple lightmaps into the 8.8 format in blocklights
  315. ===============
  316. */
  317. void R_BuildLightMap (void)
  318. {
  319. int smax, tmax;
  320. int t;
  321. int i, size;
  322. byte *lightmap;
  323. unsigned scale;
  324. int maps;
  325. msurface_t *surf;
  326. surf = r_drawsurf.surf;
  327. smax = (surf->extents[0]>>4)+1;
  328. tmax = (surf->extents[1]>>4)+1;
  329. size = smax*tmax;
  330. if (r_fullbright->value || !r_worldmodel->lightdata)
  331. {
  332. for (i=0 ; i<size ; i++)
  333. blocklights[i] = 0;
  334. return;
  335. }
  336. // clear to no light
  337. for (i=0 ; i<size ; i++)
  338. blocklights[i] = 0;
  339. // add all the lightmaps
  340. lightmap = surf->samples;
  341. if (lightmap)
  342. for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
  343. maps++)
  344. {
  345. scale = r_drawsurf.lightadj[maps]; // 8.8 fraction
  346. for (i=0 ; i<size ; i++)
  347. blocklights[i] += lightmap[i] * scale;
  348. lightmap += size; // skip to next lightmap
  349. }
  350. // add all the dynamic lights
  351. if (surf->dlightframe == r_framecount)
  352. R_AddDynamicLights ();
  353. // bound, invert, and shift
  354. for (i=0 ; i<size ; i++)
  355. {
  356. t = (int)blocklights[i];
  357. if (t < 0)
  358. t = 0;
  359. t = (255*256 - t) >> (8 - VID_CBITS);
  360. if (t < (1 << 6))
  361. t = (1 << 6);
  362. blocklights[i] = t;
  363. }
  364. }