Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1232 lines
41 KiB

  1. /*==========================================================================;
  2. *
  3. * Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: rgblt.cpp
  6. * Content: Direct3D lighting
  7. *
  8. ***************************************************************************/
  9. #include "pch.cpp"
  10. #pragma hdrstop
  11. #include "light.h"
  12. #include "drawprim.hpp"
  13. extern "C"
  14. {
  15. void Directional2(LPD3DFE_PROCESSVERTICES pv,
  16. D3DI_LIGHT *light,
  17. D3DLIGHTINGELEMENT *in);
  18. void PointSpot2(LPD3DFE_PROCESSVERTICES pv,
  19. D3DI_LIGHT *light,
  20. D3DLIGHTINGELEMENT *in);
  21. void Directional1C(LPD3DFE_PROCESSVERTICES pv,
  22. D3DI_LIGHT *light,
  23. D3DLIGHTINGELEMENT *in);
  24. void PointSpot1C(LPD3DFE_PROCESSVERTICES pv,
  25. D3DI_LIGHT *light,
  26. D3DLIGHTINGELEMENT *in);
  27. void PointSpotXCRamp(LPD3DFE_PROCESSVERTICES pv,
  28. D3DI_LIGHT *light,
  29. D3DLIGHTINGELEMENT *in);
  30. //#define _USE_ASM_
  31. #ifdef _X86_
  32. #ifdef _USE_ASM_
  33. void Directional2P5S(LPD3DFE_PROCESSVERTICES pv,
  34. D3DI_LIGHT *light,
  35. D3DLIGHTINGELEMENT *in);
  36. void Directional2P5(LPD3DFE_PROCESSVERTICES pv,
  37. D3DI_LIGHT *light,
  38. D3DLIGHTINGELEMENT *in);
  39. #endif _X86_
  40. #endif _USE_ASM_
  41. }
  42. static LIGHT_VERTEX_FUNC_TABLE lightVertexTable =
  43. {
  44. Directional1C,
  45. Directional2,
  46. PointSpot1C,
  47. PointSpot2,
  48. PointSpot1C,
  49. PointSpot2
  50. };
  51. HRESULT D3DFE_InitRGBLighting(LPDIRECT3DDEVICEI lpDevI)
  52. {
  53. LIST_INITIALIZE(&lpDevI->specular_tables);
  54. lpDevI->specular_table = NULL;
  55. LIST_INITIALIZE(&lpDevI->materials);
  56. STATESET_INIT(lpDevI->lightstate_overrides);
  57. lpDevI->lightVertexFuncTable = &lightVertexTable;
  58. lpDevI->lighting.activeLights = NULL;
  59. return (D3D_OK);
  60. }
  61. void D3DFE_DestroyRGBLighting(LPDIRECT3DDEVICEI lpDevI)
  62. {
  63. SpecularTable *spec;
  64. SpecularTable *spec_next;
  65. for (spec = LIST_FIRST(&lpDevI->specular_tables); spec; spec = spec_next)
  66. {
  67. spec_next = LIST_NEXT(spec,list);
  68. D3DFree(spec);
  69. }
  70. while (LIST_FIRST(&lpDevI->materials))
  71. {
  72. LPD3DFE_MATERIAL lpMat;
  73. lpMat = LIST_FIRST(&lpDevI->materials);
  74. LIST_DELETE(lpMat, link);
  75. D3DFree(lpMat);
  76. }
  77. }
  78. HRESULT D3DHEL_ApplyFog(D3DFE_LIGHTING* driver, int count, D3DLIGHTDATA* data)
  79. {
  80. D3DTLVERTEX *v;
  81. size_t v_size;
  82. D3DVALUE fog_start = driver->fog_start;
  83. D3DVALUE fog_end = driver->fog_end;
  84. D3DVALUE fog_length = RLDDIFInvert16(fog_end - fog_start);
  85. int i;
  86. v = (D3DTLVERTEX*)data->lpOut;
  87. v_size = data->dwOutSize;
  88. for (i = count; i; i--)
  89. {
  90. D3DVALUE w;
  91. int f;
  92. if ((v->rhw < D3DVAL(1)) && (v->rhw > 0))
  93. w = RLDDIFInvert24(v->rhw);
  94. else
  95. w = v->rhw;
  96. if (w < fog_start)
  97. f = 255;
  98. else if (w >= fog_end)
  99. f = 0;
  100. else
  101. f = VALTOFXP(DECPREC(RLDDIFMul16(fog_end - w, fog_length), 8), 8);
  102. if (f > 255) f = 255;
  103. if (f < 0) f = 0;
  104. v->specular = RGBA_SETALPHA(v->specular, f);
  105. v = (D3DTLVERTEX*)((char*)v + v_size);
  106. }
  107. return D3D_OK;
  108. }
  109. static void inverseRotateVector(D3DVECTOR* d,
  110. D3DVECTOR* v, D3DMATRIXI* M)
  111. {
  112. D3DVALUE vx = v->x;
  113. D3DVALUE vy = v->y;
  114. D3DVALUE vz = v->z;
  115. d->x = RLDDIFMul16(vx, M->_11) + RLDDIFMul16(vy, M->_12) + RLDDIFMul16(vz, M->_13);
  116. d->y = RLDDIFMul16(vx, M->_21) + RLDDIFMul16(vy, M->_22) + RLDDIFMul16(vz, M->_23);
  117. d->z = RLDDIFMul16(vx, M->_31) + RLDDIFMul16(vy, M->_32) + RLDDIFMul16(vz, M->_33);
  118. }
  119. static void inverseTransformVector(D3DVECTOR* d,
  120. D3DVECTOR* v, D3DMATRIXI* M)
  121. {
  122. D3DVALUE vx = v->x;
  123. D3DVALUE vy = v->y;
  124. D3DVALUE vz = v->z;
  125. vx -= M->_41; vy -= M->_42; vz -= M->_43;
  126. d->x = RLDDIFMul16(vx, M->_11) + RLDDIFMul16(vy, M->_12) + RLDDIFMul16(vz, M->_13);
  127. d->y = RLDDIFMul16(vx, M->_21) + RLDDIFMul16(vy, M->_22) + RLDDIFMul16(vz, M->_23);
  128. d->z = RLDDIFMul16(vx, M->_31) + RLDDIFMul16(vy, M->_32) + RLDDIFMul16(vz, M->_33);
  129. }
  130. /*
  131. * Every time the world matrix is modified the lighting vectors have to
  132. * change to match the model space of the new data to be rendered
  133. */
  134. #define SMALLISH (1e-2)
  135. #define ONEISH(v) (fabs(v - 1.0f) < SMALLISH)
  136. static int getMatrixScale(D3DMATRIXI* m, D3DVECTOR* s)
  137. {
  138. s->x = (m->_11 * m->_11 + m->_12 * m->_12 + m->_13 * m->_13);
  139. s->y = (m->_21 * m->_21 + m->_22 * m->_22 + m->_23 * m->_23);
  140. s->z = (m->_31 * m->_31 + m->_32 * m->_32 + m->_33 * m->_33);
  141. if (ONEISH(s->x) && ONEISH(s->y) && ONEISH(s->z))
  142. return FALSE;
  143. else
  144. {
  145. s->x = (D3DVALUE)(1.0f / s->x);
  146. s->y = (D3DVALUE)(1.0f / s->y);
  147. s->z = (D3DVALUE)(1.0f / s->z);
  148. return TRUE;
  149. }
  150. }
  151. static int
  152. getMatrixScale2(D3DMATRIXI *m, D3DVECTOR *s)
  153. {
  154. float det;
  155. s->x = (float)sqrt(m->_11*m->_11 + m->_12*m->_12 + m->_13*m->_13);
  156. s->y = (float)sqrt(m->_21*m->_21 + m->_22*m->_22 + m->_23*m->_23);
  157. s->z = (float)sqrt(m->_31*m->_31 + m->_32*m->_32 + m->_33*m->_33);
  158. if (ONEISH(s->x) && ONEISH(s->y) && ONEISH(s->z))
  159. {
  160. return FALSE;
  161. }
  162. else
  163. {
  164. det = m->_11*(m->_22*m->_33 - m->_23*m->_32)
  165. - m->_12*(m->_21*m->_33 - m->_23*m->_31)
  166. + m->_13*(m->_21*m->_32 - m->_22*m->_31);
  167. if (det<0.0)
  168. {
  169. s->x = (-s->x);
  170. s->y = (-s->y);
  171. s->z = (-s->z);
  172. }
  173. // prevent 0 scales from sneaking through
  174. if (fabs(s->x) < 0.0001)
  175. s->x = 0.0001f;
  176. if (fabs(s->y) < 0.0001)
  177. s->y = 0.0001f;
  178. if (fabs(s->z) < 0.0001)
  179. s->z = 0.0001f;
  180. return TRUE;
  181. }
  182. } // end of getMatrixScale2()
  183. //-----------------------------------------------------------------------
  184. // Every time the world matrix is modified or lights data is changed the
  185. // lighting vectors have to change to match the model space of the new data
  186. // to be rendered.
  187. // Every time light data is changed or material data is changed or lighting
  188. // state is changed, some pre-computed lighting values sould be updated
  189. //
  190. void D3DFE_UpdateLights(LPDIRECT3DDEVICEI lpDevI)
  191. {
  192. D3DFE_LIGHTING& LIGHTING = lpDevI->lighting;
  193. D3DI_LIGHT *light = LIGHTING.activeLights;
  194. D3DVECTOR t;
  195. D3DMATRIXI *world;
  196. D3DMATRIXI *camera;
  197. D3DMATERIAL *mat;
  198. D3DVECTOR cameraModel;
  199. D3DVECTOR cameraWorld;
  200. D3DVECTOR cameraModelNorm; // Normalized
  201. D3DVECTOR scale1;
  202. D3DVECTOR scale2;
  203. D3DVECTOR oneOverScale;
  204. BOOL cameraModelNormComputed = FALSE;
  205. BOOL scale1Computed = FALSE; // For light 1
  206. BOOL scale2Computed = FALSE; // For light 2
  207. BOOL need_scale1;
  208. BOOL need_scale2;
  209. BOOL specular; // TRUE, if specular component sould be computed
  210. if (lpDevI->dwFEFlags & D3DFE_NEED_TRANSFORM_LIGHTS)
  211. {
  212. D3DVECTOR t;
  213. world = &lpDevI->transform.world;
  214. camera = &lpDevI->transform.view;
  215. t.x = -camera->_41;
  216. t.y = -camera->_42;
  217. t.z = -camera->_43;
  218. // transform the eye into world coords.
  219. inverseRotateVector(&cameraWorld, &t, camera);
  220. // now transform eye into model space
  221. inverseTransformVector(&cameraModel, &cameraWorld, world);
  222. }
  223. if (lpDevI->dwFEFlags & (D3DFE_MATERIAL_DIRTY | D3DFE_LIGHTS_DIRTY))
  224. {
  225. mat = &LIGHTING.material;
  226. if (lpDevI->specular_table &&
  227. lpDevI->rstates[D3DRENDERSTATE_SPECULARENABLE])
  228. {
  229. specular = TRUE;
  230. lpDevI->dwFEFlags |= D3DFE_COMPUTESPECULAR;
  231. }
  232. else
  233. {
  234. specular = FALSE;
  235. lpDevI->dwFEFlags &= ~D3DFE_COMPUTESPECULAR;
  236. }
  237. LIGHTING.materialAlpha = FTOI(D3DVAL(255) * mat->diffuse.a);
  238. if (LIGHTING.materialAlpha < 0)
  239. LIGHTING.materialAlpha = 0;
  240. else
  241. if (LIGHTING.materialAlpha > 255)
  242. LIGHTING.materialAlpha = 255 << 24;
  243. else LIGHTING.materialAlpha <<= 24;
  244. LIGHTING.currentSpecTable = lpDevI->specular_table->table;
  245. if (!(lpDevI->dwDeviceFlags & D3DDEV_RAMP))
  246. {
  247. LIGHTING.diffuse0.r = LIGHTING.ambient_red * mat->ambient.r +
  248. mat->emissive.r * D3DVAL(255);
  249. LIGHTING.diffuse0.g = LIGHTING.ambient_green * mat->ambient.g +
  250. mat->emissive.g * D3DVAL(255);
  251. LIGHTING.diffuse0.b = LIGHTING.ambient_blue * mat->ambient.b +
  252. mat->emissive.b * D3DVAL(255);
  253. }
  254. }
  255. while (light)
  256. {
  257. if (lpDevI->dwFEFlags & D3DFE_NEED_TRANSFORM_LIGHTS)
  258. {
  259. if (light->type != D3DLIGHT_DIRECTIONAL)
  260. {
  261. // Transform light position to the model space
  262. t.x = light->position.x - world->_41;
  263. t.y = light->position.y - world->_42;
  264. t.z = light->position.z - world->_43;
  265. inverseRotateVector(&light->model_position, &t, world);
  266. }
  267. if (light->version == 1)
  268. {
  269. if (!scale1Computed)
  270. {
  271. need_scale1 = getMatrixScale(world, &scale1);
  272. scale1Computed = TRUE;
  273. }
  274. if (!need_scale1)
  275. light->flags |= D3DLIGHTI_UNIT_SCALE;
  276. else
  277. {
  278. if (light->type != D3DLIGHT_DIRECTIONAL)
  279. {
  280. light->model_position.x *= scale1.x;
  281. light->model_position.y *= scale1.y;
  282. light->model_position.z *= scale1.z;
  283. }
  284. }
  285. }
  286. else
  287. {
  288. if (!scale2Computed)
  289. {
  290. need_scale2 = getMatrixScale2(world, &scale2);
  291. scale2Computed = TRUE;
  292. }
  293. if (!need_scale2)
  294. light->flags |= D3DLIGHTI_UNIT_SCALE;
  295. else
  296. {
  297. light->model_scale.x = scale2.x;
  298. light->model_scale.y = scale2.y;
  299. light->model_scale.z = scale2.z;
  300. oneOverScale.x = D3DVAL(1)/scale2.x;
  301. oneOverScale.y = D3DVAL(1)/scale2.y;
  302. oneOverScale.z = D3DVAL(1)/scale2.z;
  303. light->flags &= ~D3DLIGHTI_UNIT_SCALE;
  304. }
  305. }
  306. if (light->type != D3DLIGHT_POINT)
  307. {
  308. if (light->type == D3DLIGHT_PARALLELPOINT)
  309. {
  310. light->model_direction = light->model_position;
  311. }
  312. else
  313. {
  314. // Transform light direction to the model space
  315. inverseRotateVector(&light->model_direction,
  316. &light->direction, world);
  317. VecNeg(light->model_direction, light->model_direction);
  318. }
  319. if (light->version != 1 && need_scale2)
  320. {
  321. // apply scale here before normalizing
  322. light->model_direction.x *= oneOverScale.x;
  323. light->model_direction.y *= oneOverScale.y;
  324. light->model_direction.z *= oneOverScale.z;
  325. }
  326. if (need_scale1 || need_scale2 ||
  327. light->type == D3DLIGHT_PARALLELPOINT)
  328. VecNormalizeFast(light->model_direction);
  329. }
  330. if (light->version == 1)
  331. {
  332. if (!cameraModelNormComputed)
  333. {
  334. VecNormalizeFast2(cameraModel, cameraModelNorm);
  335. cameraModelNormComputed = TRUE;
  336. }
  337. if (light->type == D3DLIGHT_DIRECTIONAL)
  338. {
  339. t = light->model_direction;
  340. }
  341. else
  342. {
  343. t = light->model_position;
  344. }
  345. // calc halfway vector
  346. VecNormalizeFast(t);
  347. VecAdd(t, cameraModelNorm, light->halfway);
  348. VecNormalizeFast(light->halfway);
  349. }
  350. else
  351. {
  352. // We want to compare cameraWorld position with the light to
  353. // see if they match
  354. if (fabs(light->position.x-cameraWorld.x) < 0.0001 &&
  355. fabs(light->position.y-cameraWorld.y) < 0.0001 &&
  356. fabs(light->position.z-cameraWorld.z) < 0.0001)
  357. {
  358. light->flags |= D3DLIGHTI_LIGHT_AT_EYE;
  359. }
  360. else
  361. {
  362. light->flags &= ~D3DLIGHTI_LIGHT_AT_EYE;
  363. }
  364. // store location of eye in model space
  365. if (light->flags & D3DLIGHTI_UNIT_SCALE)
  366. {
  367. light->model_eye = cameraModel;
  368. }
  369. else
  370. {
  371. light->model_eye.x = cameraModel.x * oneOverScale.x;
  372. light->model_eye.y = cameraModel.y * oneOverScale.y;
  373. light->model_eye.z = cameraModel.z * oneOverScale.z;
  374. if (light->type == D3DLIGHT_POINT ||
  375. light->type == D3DLIGHT_SPOT)
  376. {
  377. light->model_position.x *= oneOverScale.x;
  378. light->model_position.y *= oneOverScale.y;
  379. light->model_position.z *= oneOverScale.z;
  380. }
  381. }
  382. }
  383. }
  384. if (lpDevI->dwFEFlags & (D3DFE_MATERIAL_DIRTY | D3DFE_LIGHTS_DIRTY))
  385. {
  386. if (!(lpDevI->dwDeviceFlags & D3DDEV_RAMP))
  387. {
  388. light->local_diffR = D3DVAL(255) * mat->diffuse.r * light->red;
  389. light->local_diffG = D3DVAL(255) * mat->diffuse.g * light->green;
  390. light->local_diffB = D3DVAL(255) * mat->diffuse.b * light->blue;
  391. light->local_specR = D3DVAL(255) * mat->specular.r * light->red;
  392. light->local_specG = D3DVAL(255) * mat->specular.g * light->green;
  393. light->local_specB = D3DVAL(255) * mat->specular.b * light->blue;
  394. }
  395. else
  396. {
  397. light->local_diffR = light->shade;
  398. light->local_specR = light->shade;
  399. }
  400. if (specular && !(light->flags & D3DLIGHT_NO_SPECULAR))
  401. light->flags |= D3DLIGHTI_COMPUTE_SPECULAR;
  402. else
  403. light->flags &= ~D3DLIGHTI_COMPUTE_SPECULAR;
  404. }
  405. if (lpDevI->dwFEFlags & D3DFE_LIGHTS_DIRTY)
  406. {
  407. light->lightVertexFunc = NULL;
  408. if (light->version == 1)
  409. {
  410. switch (light->type)
  411. {
  412. case D3DLIGHT_PARALLELPOINT:
  413. case D3DLIGHT_DIRECTIONAL:
  414. light->lightVertexFunc =
  415. lpDevI->lightVertexFuncTable->directional1;
  416. break;
  417. case D3DLIGHT_POINT:
  418. if (lpDevI->dwDeviceFlags & D3DDEV_RAMP)
  419. {
  420. light->lightVertexFunc = PointSpotXCRamp;
  421. }
  422. else
  423. {
  424. light->lightVertexFunc =
  425. lpDevI->lightVertexFuncTable->point1;
  426. }
  427. break;
  428. case D3DLIGHT_SPOT:
  429. if (lpDevI->dwDeviceFlags & D3DDEV_RAMP)
  430. {
  431. light->lightVertexFunc = PointSpotXCRamp;
  432. }
  433. else
  434. {
  435. light->lightVertexFunc =
  436. lpDevI->lightVertexFuncTable->spot1;
  437. }
  438. break;
  439. }
  440. }
  441. else
  442. {
  443. switch (light->type)
  444. {
  445. case D3DLIGHT_PARALLELPOINT:
  446. case D3DLIGHT_DIRECTIONAL:
  447. {
  448. #ifdef _X86_
  449. #ifdef _USE_ASM_
  450. if (light->flags & D3DLIGHTI_UNIT_SCALE &&
  451. !(lpDevI->dwDeviceFlags & D3DDEV_RAMP) &&
  452. !(lpDevI->dwFEFlags & D3DFE_COLORVERTEX))
  453. {
  454. if (light->flags & D3DLIGHTI_COMPUTE_SPECULAR)
  455. light->lightVertexFunc = Directional2P5S;
  456. else
  457. light->lightVertexFunc = Directional2P5;
  458. }
  459. else
  460. #endif _USE_ASM_
  461. #endif // _X86_
  462. light->lightVertexFunc =
  463. lpDevI->lightVertexFuncTable->directional2;
  464. break;
  465. }
  466. case D3DLIGHT_POINT:
  467. if (lpDevI->dwDeviceFlags & D3DDEV_RAMP)
  468. {
  469. light->lightVertexFunc = PointSpotXCRamp;
  470. }
  471. else
  472. {
  473. light->lightVertexFunc =
  474. lpDevI->lightVertexFuncTable->point2;
  475. }
  476. break;
  477. case D3DLIGHT_SPOT:
  478. if (lpDevI->dwDeviceFlags & D3DDEV_RAMP)
  479. {
  480. light->lightVertexFunc = PointSpotXCRamp;
  481. }
  482. else
  483. {
  484. light->lightVertexFunc =
  485. lpDevI->lightVertexFuncTable->spot2;
  486. }
  487. break;
  488. }
  489. }
  490. }
  491. light = light->next;
  492. }
  493. lpDevI->dwFEFlags &= ~(D3DFE_MATERIAL_DIRTY |
  494. D3DFE_NEED_TRANSFORM_LIGHTS |
  495. D3DFE_LIGHTS_DIRTY);
  496. } // end of updateLights()
  497. //---------------------------------------------------------------------
  498. inline D3DVALUE COMPUTE_DOT_POW(D3DFE_LIGHTING *ldrv, D3DVALUE dot)
  499. {
  500. ldrv->specularComputed = TRUE;
  501. if (dot < 1.0f)
  502. {
  503. int indx;
  504. float v;
  505. dot *= 255.0f;
  506. indx = (int)dot;
  507. dot -= indx;
  508. v = ldrv->currentSpecTable[indx];
  509. return v + (ldrv->currentSpecTable[indx+1] - v)*dot;
  510. }
  511. else
  512. return 1.0f;
  513. }
  514. //---------------------------------------------------------------------
  515. inline void COMPUTE_SPECULAR(LPD3DFE_PROCESSVERTICES pv,
  516. D3DVALUE dot,
  517. D3DI_LIGHT *light)
  518. {
  519. D3DFE_LIGHTING &ldrv = pv->lighting;
  520. if (FLOAT_CMP_POS(dot, >=, ldrv.specThreshold))
  521. {
  522. D3DVALUE power;
  523. power = COMPUTE_DOT_POW(&ldrv, dot);
  524. if (pv->dwDeviceFlags & D3DDEV_RAMP)
  525. {
  526. ldrv.specular.r += light->shade * power;
  527. }
  528. else
  529. if (!(pv->dwFlags & D3DPV_COLORVERTEXS))
  530. {
  531. ldrv.specular.r += light->local_specR * power;
  532. ldrv.specular.g += light->local_specG * power;
  533. ldrv.specular.b += light->local_specB * power;
  534. }
  535. else
  536. {
  537. ldrv.specular.r += light->red * ldrv.vertexSpecular.r * power;
  538. ldrv.specular.g += light->green * ldrv.vertexSpecular.g * power;
  539. ldrv.specular.b += light->blue * ldrv.vertexSpecular.b * power;
  540. }
  541. }
  542. }
  543. //---------------------------------------------------------------------
  544. inline void COMPUTE_SPECULAR_ATT(LPD3DFE_PROCESSVERTICES pv,
  545. D3DVALUE dot,
  546. D3DI_LIGHT *light,
  547. D3DVALUE att)
  548. {
  549. D3DFE_LIGHTING &ldrv = pv->lighting;
  550. if (FLOAT_CMP_POS(dot, >=, ldrv.specThreshold))
  551. {
  552. D3DVALUE power;
  553. power = COMPUTE_DOT_POW(&ldrv, dot);
  554. power *= att;
  555. if (pv->dwDeviceFlags & D3DDEV_RAMP)
  556. {
  557. ldrv.specular.r += light->shade * power;
  558. }
  559. else
  560. if (!(pv->dwFlags & D3DPV_COLORVERTEXS))
  561. {
  562. ldrv.specular.r += light->local_specR * power;
  563. ldrv.specular.g += light->local_specG * power;
  564. ldrv.specular.b += light->local_specB * power;
  565. }
  566. else
  567. {
  568. ldrv.specular.r += light->red * ldrv.vertexSpecular.r * power;
  569. ldrv.specular.g += light->green * ldrv.vertexSpecular.g * power;
  570. ldrv.specular.b += light->blue * ldrv.vertexSpecular.b * power;
  571. }
  572. }
  573. }
  574. //-------------------------------------------------------------------------
  575. void Directional2(LPD3DFE_PROCESSVERTICES pv,
  576. D3DI_LIGHT *light,
  577. D3DLIGHTINGELEMENT *in)
  578. {
  579. D3DFE_LIGHTING &ldrv = pv->lighting;
  580. D3DVALUE dot;
  581. dot = VecDot(light->model_direction, in->dvNormal);
  582. if (FLOAT_GTZ(dot))
  583. {
  584. if (pv->dwDeviceFlags & D3DDEV_RAMP)
  585. {
  586. ldrv.diffuse.r += light->shade * dot;
  587. }
  588. else
  589. if (!(pv->dwFlags & D3DPV_COLORVERTEX))
  590. {
  591. ldrv.diffuse.r += light->local_diffR * dot;
  592. ldrv.diffuse.g += light->local_diffG * dot;
  593. ldrv.diffuse.b += light->local_diffB * dot;
  594. }
  595. else
  596. {
  597. ldrv.diffuse.r += light->red * ldrv.vertexDiffuse.r * dot;
  598. ldrv.diffuse.g += light->green * ldrv.vertexDiffuse.g * dot;
  599. ldrv.diffuse.b += light->blue * ldrv.vertexDiffuse.b * dot;
  600. }
  601. if (light->flags & D3DLIGHTI_COMPUTE_SPECULAR)
  602. {
  603. D3DVECTOR h; // halfway vector
  604. D3DVECTOR eye; // incident vector ie vector from eye
  605. // calc incident vector
  606. if (light->flags & D3DLIGHTI_UNIT_SCALE)
  607. {
  608. VecSub(in->dvPosition, light->model_eye, eye);
  609. }
  610. else
  611. {
  612. // note that model_eye has already been divided by scale
  613. // in setup
  614. eye.x = in->dvPosition.x*light->model_scale.x -
  615. light->model_eye.x;
  616. eye.y = in->dvPosition.y*light->model_scale.y -
  617. light->model_eye.y;
  618. eye.z = in->dvPosition.z*light->model_scale.z -
  619. light->model_eye.z;
  620. }
  621. // normalize
  622. VecNormalizeFast(eye);
  623. // calc halfway vector
  624. VecSub(light->model_direction, eye, h);
  625. dot = VecDot(h, in->dvNormal);
  626. if (FLOAT_GTZ(dot))
  627. {
  628. dot *= ISQRTF(VecLenSq(h));
  629. COMPUTE_SPECULAR(pv, dot, light);
  630. }
  631. }
  632. }
  633. }
  634. //-------------------------------------------------------------------------
  635. void PointSpot2(LPD3DFE_PROCESSVERTICES pv,
  636. D3DI_LIGHT *light,
  637. D3DLIGHTINGELEMENT *in)
  638. {
  639. D3DFE_LIGHTING &ldrv = pv->lighting;
  640. D3DVALUE dot;
  641. D3DVALUE dist; // Distance from light to the vertex
  642. D3DVALUE dist2;
  643. D3DVECTOR d; // Direction to light
  644. D3DVALUE att;
  645. if (light->flags & D3DLIGHTI_UNIT_SCALE)
  646. {
  647. VecSub(light->model_position, in->dvPosition, d);
  648. }
  649. else
  650. {
  651. d.x = light->model_position.x - in->dvPosition.x * light->model_scale.x;
  652. d.y = light->model_position.y - in->dvPosition.y * light->model_scale.y;
  653. d.z = light->model_position.z - in->dvPosition.z * light->model_scale.z;
  654. }
  655. // early out if out of range or exactly on the vertex
  656. dist2 = d.x*d.x + d.y*d.y + d.z*d.z;
  657. if (FLOAT_CMP_POS(dist2, >=, light->range_squared) || FLOAT_EQZ(dist2))
  658. return;
  659. // Calc dot product of light dir with normal. Note that since we
  660. // didn't normalize the direction the result is scaled by the distance.
  661. dot = VecDot(d, in->dvNormal);
  662. if (FLOAT_GTZ(dot))
  663. {
  664. // ok, so now we actually need the real dist
  665. dist = SQRTF(dist2);
  666. // calc attenuation
  667. att = 0.0f;
  668. if (light->flags & D3DLIGHTI_ATT0_IS_NONZERO)
  669. {
  670. att += light->attenuation0;
  671. }
  672. if (light->flags & (D3DLIGHTI_ATT1_IS_NONZERO | D3DLIGHTI_ATT2_IS_NONZERO))
  673. {
  674. float att1 = (light->range - dist) / light->range;
  675. if (light->flags & D3DLIGHTI_ATT1_IS_NONZERO)
  676. {
  677. att += light->attenuation1 * att1;
  678. }
  679. if (light->flags & D3DLIGHTI_ATT2_IS_NONZERO)
  680. {
  681. att += light->attenuation2 * att1 * att1;
  682. }
  683. }
  684. dist = D3DVAL(1)/dist;
  685. if (light->type == D3DLIGHT_SPOT)
  686. {
  687. D3DVALUE cone_dot;
  688. // Calc dot product of direction to light with light direction to
  689. // be compared anganst the cone angles to see if we are in the light.
  690. // Note that cone_dot is still scaled by dist
  691. cone_dot = VecDot(d, light->model_direction);
  692. cone_dot*= dist; // Normalizing
  693. if (FLOAT_CMP_POS(cone_dot, <=, light->cos_phi_by_2))
  694. return;
  695. // modify att if in the region between phi and theta
  696. if (FLOAT_CMP_POS(cone_dot, <, light->cos_theta_by_2))
  697. {
  698. D3DVALUE val;
  699. val = (cone_dot - light->cos_phi_by_2) * light->inv_theta_minus_phi;
  700. if (!(light->flags & D3DLIGHTI_LINEAR_FALLOFF))
  701. {
  702. val = POWF(val, light->falloff);
  703. }
  704. att *= val;
  705. }
  706. }
  707. dot *= dist*att;
  708. if (pv->dwDeviceFlags & D3DDEV_RAMP)
  709. {
  710. ldrv.diffuse.r += light->shade * dot;
  711. }
  712. else
  713. if (!(pv->dwFlags & D3DPV_COLORVERTEX))
  714. {
  715. ldrv.diffuse.r += light->local_diffR * dot;
  716. ldrv.diffuse.g += light->local_diffG * dot;
  717. ldrv.diffuse.b += light->local_diffB * dot;
  718. }
  719. else
  720. {
  721. ldrv.diffuse.r += light->red * ldrv.vertexDiffuse.r * dot;
  722. ldrv.diffuse.g += light->green * ldrv.vertexDiffuse.g * dot;
  723. ldrv.diffuse.b += light->blue * ldrv.vertexDiffuse.b * dot;
  724. }
  725. if (light->flags & D3DLIGHTI_COMPUTE_SPECULAR)
  726. {
  727. D3DVECTOR eye;
  728. D3DVECTOR h;
  729. // normalize light direction
  730. d.x *= dist;
  731. d.y *= dist;
  732. d.z *= dist;
  733. if (light->flags & D3DLIGHTI_LIGHT_AT_EYE)
  734. {
  735. h = d;
  736. }
  737. else
  738. {
  739. // calc incident vector
  740. if (light->flags & D3DLIGHTI_UNIT_SCALE)
  741. {
  742. VecSub(in->dvPosition, light->model_eye, eye);
  743. }
  744. else
  745. {
  746. // note that model_eye has already been divided by scale in setup
  747. eye.x = in->dvPosition.x*light->model_scale.x -
  748. light->model_eye.x;
  749. eye.y = in->dvPosition.y*light->model_scale.y -
  750. light->model_eye.y;
  751. eye.z = in->dvPosition.z*light->model_scale.z -
  752. light->model_eye.z;
  753. }
  754. // normalize
  755. VecNormalizeFast(eye);
  756. // calc halfway vector
  757. VecSub(d, eye, h);
  758. VecNormalizeFast(h);
  759. }
  760. dot = VecDot(h, in->dvNormal);
  761. COMPUTE_SPECULAR_ATT(pv, dot, light, att);
  762. }
  763. }
  764. } // end of Point2()
  765. //-------------------------------------------------------------------------
  766. void Directional1C(LPD3DFE_PROCESSVERTICES pv,
  767. D3DI_LIGHT *light,
  768. D3DLIGHTINGELEMENT *in)
  769. {
  770. D3DFE_LIGHTING &ldrv = pv->lighting;
  771. D3DVALUE dot;
  772. dot = VecDot(light->model_direction, in->dvNormal);
  773. if (FLOAT_GTZ(dot))
  774. {
  775. if (pv->dwDeviceFlags & D3DDEV_RAMP)
  776. {
  777. ldrv.diffuse.r += light->shade * dot;
  778. }
  779. else
  780. {
  781. ldrv.diffuse.r += light->local_diffR * dot;
  782. ldrv.diffuse.g += light->local_diffG * dot;
  783. ldrv.diffuse.b += light->local_diffB * dot;
  784. }
  785. if (light->flags & D3DLIGHTI_COMPUTE_SPECULAR)
  786. {
  787. dot = VecDot(light->halfway, in->dvNormal);
  788. COMPUTE_SPECULAR(pv, dot, light);
  789. }
  790. }
  791. }
  792. //-------------------------------------------------------------------------
  793. void PointSpot1C(LPD3DFE_PROCESSVERTICES pv,
  794. D3DI_LIGHT *light,
  795. D3DLIGHTINGELEMENT *in)
  796. {
  797. D3DFE_LIGHTING &ldrv = pv->lighting;
  798. D3DVECTOR d;
  799. D3DVALUE dot;
  800. VecSub(light->model_position, in->dvPosition, d);
  801. dot = VecDot(d, in->dvNormal);
  802. if (FLOAT_GTZ(dot))
  803. {
  804. D3DVALUE dist2;
  805. D3DVALUE dist;
  806. D3DVALUE att;
  807. D3DVALUE big = D3DVAL(1000); // if 1/att < 0.001 do not compute color
  808. dist2 = VecDot(d, d);
  809. if (FLOAT_EQZ(dist2))
  810. return;
  811. dist = SQRTF(dist2);
  812. att = light->attenuation0 +
  813. light->attenuation1 * dist +
  814. light->attenuation2 * dist2;
  815. if (FLOAT_CMP_POS(att, >, big))
  816. return;
  817. if (FLOAT_CMP_PONE(att, >))
  818. att *= dist;
  819. else
  820. att = dist;
  821. att = D3DVAL(1) / att;
  822. if (light->type == D3DLIGHT_SPOT)
  823. {
  824. D3DVALUE cone_dot;
  825. // Calc dot product of direction to light with light direction to
  826. // be compared anganst the cone angles to see if we are in the light.
  827. // Note that cone_dot is still scaled by dist
  828. cone_dot = VecDot(d, light->model_direction);
  829. cone_dot /= dist;
  830. if (FLOAT_CMP_POS(cone_dot, <=, light->cos_phi_by_2))
  831. return;
  832. if (FLOAT_CMP_POS(cone_dot, <, light->cos_theta_by_2))
  833. {
  834. att *= D3DVAL(1)-(light->cos_theta_by_2-cone_dot)*light->falloff;
  835. }
  836. }
  837. dot *= att;
  838. if (pv->dwDeviceFlags & D3DDEV_RAMP)
  839. {
  840. ldrv.diffuse.r += light->shade * dot;
  841. }
  842. else
  843. {
  844. ldrv.diffuse.r += light->local_diffR * dot;
  845. ldrv.diffuse.g += light->local_diffG * dot;
  846. ldrv.diffuse.b += light->local_diffB * dot;
  847. }
  848. if (light->flags & D3DLIGHTI_COMPUTE_SPECULAR)
  849. {
  850. dot = VecDot(light->halfway, in->dvNormal);
  851. COMPUTE_SPECULAR_ATT(pv, dot, light, att);
  852. }
  853. }
  854. }
  855. //-------------------------------------------------------------------------
  856. void PointSpotXCRamp(LPD3DFE_PROCESSVERTICES pv,
  857. D3DI_LIGHT *light,
  858. D3DLIGHTINGELEMENT *in)
  859. {
  860. D3DFE_LIGHTING &ldrv = pv->lighting;
  861. D3DVECTOR d;
  862. D3DVALUE dot;
  863. VecSub(light->model_position, in->dvPosition, d);
  864. dot = VecDot(d, in->dvNormal);
  865. if (FLOAT_GTZ(dot))
  866. {
  867. D3DVALUE dist2;
  868. D3DVALUE dist;
  869. D3DVALUE att;
  870. D3DVALUE big = D3DVAL(1000); // if 1/att < 0.001 do not compute color
  871. dist2 = VecDot(d, d);
  872. if (FLOAT_EQZ(dist2))
  873. return;
  874. dist = SQRTF(dist2);
  875. if (light->version == 1)
  876. {
  877. att = light->attenuation0 +
  878. light->attenuation1 * dist +
  879. light->attenuation2 * dist2;
  880. if (FLOAT_CMP_PONE(att, >))
  881. att *= dist;
  882. else
  883. att = dist;
  884. att = D3DVAL(1) / att;
  885. }
  886. else
  887. {
  888. // dist is normalized to light range
  889. float att1 = (light->range-dist)/light->range;
  890. att = light->attenuation0 +
  891. light->attenuation1 * att1 +
  892. light->attenuation2 * att1*att1;
  893. }
  894. if (light->type == D3DLIGHT_SPOT)
  895. {
  896. D3DVALUE cone_dot;
  897. // Calc dot product of direction to light with light direction to
  898. // be compared anganst the cone angles to see if we are in the light.
  899. // Note that cone_dot is still scaled by dist
  900. cone_dot = VecDot(d, light->model_direction);
  901. cone_dot /= dist;
  902. if (FLOAT_CMP_POS(cone_dot, <=, light->cos_phi_by_2))
  903. return;
  904. if (FLOAT_CMP_POS(cone_dot, <, light->cos_theta_by_2))
  905. {
  906. att *= D3DVAL(1)-(light->cos_theta_by_2-cone_dot)*light->falloff;
  907. }
  908. }
  909. dot *= att;
  910. if (pv->dwDeviceFlags & D3DDEV_RAMP)
  911. {
  912. ldrv.diffuse.r += light->shade * dot;
  913. }
  914. else
  915. {
  916. ldrv.diffuse.r += light->local_diffR * dot;
  917. ldrv.diffuse.g += light->local_diffG * dot;
  918. ldrv.diffuse.b += light->local_diffB * dot;
  919. }
  920. if (light->version == 1)
  921. {
  922. // no attenuation of specular for ramp for version == 1
  923. att = 1.0F;
  924. }
  925. if (light->flags & D3DLIGHTI_COMPUTE_SPECULAR)
  926. {
  927. dot = VecDot(light->halfway, in->dvNormal);
  928. COMPUTE_SPECULAR_ATT(pv, dot, light, att);
  929. }
  930. }
  931. }
  932. //-------------------------------------------------------------------------
  933. SpecularTable* CreateSpecularTable(D3DVALUE power)
  934. {
  935. SpecularTable* spec;
  936. int i;
  937. float delta = 1.0f/255.0f;
  938. float v;
  939. D3DMalloc((void**)&spec, sizeof(SpecularTable));
  940. if (spec == NULL)
  941. return NULL;
  942. spec->power = power;
  943. v = 0.0f;
  944. for (i = 0; i < 256; i++)
  945. {
  946. spec->table[i] = powf(v, power);
  947. v += delta;
  948. }
  949. for (; i < 260; i++)
  950. spec->table[i] = 1.0f;
  951. return spec;
  952. }
  953. HRESULT SetMaterial(LPDIRECT3DDEVICEI lpDevI, D3DMATERIALHANDLE hMat)
  954. {
  955. LPD3DFE_MATERIAL lpMat;
  956. lpMat = (LPD3DFE_MATERIAL) ULongToPtr(hMat);
  957. if (!lpMat)
  958. {
  959. lpDevI->lighting.hMat = NULL;
  960. return D3D_OK;
  961. }
  962. #if DBG
  963. // check for non-null bogus material handle
  964. TRY
  965. {
  966. if (IsBadReadPtr(lpMat,sizeof(D3DFE_MATERIAL)) || (lpMat->mat.dwSize!=sizeof(D3DMATERIAL))) {
  967. D3D_ERR( "SetLightState: Invalid Material handle" );
  968. return DDERR_INVALIDPARAMS;
  969. }
  970. }
  971. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  972. {
  973. D3D_ERR( "Exception encountered validating SetLightState material handle" );
  974. return DDERR_INVALIDPARAMS;
  975. }
  976. #endif
  977. D3DFE_LIGHTING& LIGHTING = lpDevI->lighting;
  978. LIGHTING.material = lpMat->mat;
  979. LIGHTING.hMat = hMat;
  980. lpDevI->dwFEFlags |= D3DFE_MATERIAL_DIRTY;
  981. if (lpMat->mat.power > D3DVAL(0.001))
  982. {
  983. SpecularTable* spec;
  984. for (spec = LIST_FIRST(&lpDevI->specular_tables);
  985. spec;
  986. spec = LIST_NEXT(spec,list))
  987. {
  988. if (spec->power == lpMat->mat.power)
  989. break;
  990. }
  991. if (spec == NULL)
  992. {
  993. spec = CreateSpecularTable(lpMat->mat.power);
  994. if (spec == NULL)
  995. return DDERR_INVALIDPARAMS;
  996. LIST_INSERT_ROOT(&lpDevI->specular_tables, spec, list);
  997. }
  998. lpDevI->specular_table = spec;
  999. LIGHTING.specThreshold = D3DVAL(pow(0.001, 1.0/lpMat->mat.power));
  1000. }
  1001. else
  1002. lpDevI->specular_table = NULL;
  1003. return D3D_OK;
  1004. }
  1005. /*
  1006. * Instruction emulation.
  1007. */
  1008. HRESULT D3DHELInst_D3DOP_STATELIGHT(LPDIRECT3DDEVICEI lpDevI, DWORD dwCount,
  1009. LPD3DSTATE lpLset)
  1010. {
  1011. DWORD i;
  1012. for (i = 0; i < dwCount; i++)
  1013. {
  1014. DWORD type = (DWORD) lpLset[i].dlstLightStateType;
  1015. HRESULT hr = D3D_OK;
  1016. D3D_INFO(9, "HEL D3DOP_STATELIGHT: state = %d", type);
  1017. if (IS_OVERRIDE(type))
  1018. {
  1019. DWORD override = GET_OVERRIDE(type);
  1020. if (lpLset[i].dwArg[0])
  1021. {
  1022. D3D_INFO(9, "HEL D3DOP_STATELIGHT: setting override for state %d",
  1023. override);
  1024. STATESET_SET(lpDevI->lightstate_overrides, override);
  1025. }
  1026. else
  1027. {
  1028. D3D_INFO(9, "HEL D3DOP_STATELIGHT: clearing override for state %d",
  1029. override);
  1030. STATESET_CLEAR(lpDevI->lightstate_overrides, override);
  1031. }
  1032. continue;
  1033. }
  1034. if (STATESET_ISSET(lpDevI->lightstate_overrides, type))
  1035. {
  1036. D3D_INFO(9, "HEL D3DOP_STATELIGHT: state %d is overridden, ignoring",
  1037. type);
  1038. continue;
  1039. }
  1040. D3DFE_LIGHTING& LIGHTING = lpDevI->lighting;
  1041. switch (type)
  1042. {
  1043. case D3DLIGHTSTATE_MATERIAL:
  1044. {
  1045. D3D_INFO(6, "in HEL D3DOP_STATELIGHT. D3DLIGHTSTATE_MATERIAL found");
  1046. D3DMATERIALHANDLE hMat = (D3DMATERIALHANDLE)lpLset[i].dwArg[0];
  1047. if (hMat != lpDevI->lighting.hMat)
  1048. {
  1049. hr = SetMaterial(lpDevI, hMat);
  1050. if (hr != D3D_OK)
  1051. return hr;
  1052. // Update ramp rasterizer if necessary
  1053. if(lpDevI->pfnRampService != NULL)
  1054. {
  1055. hr = CallRampService(lpDevI, RAMP_SERVICE_SETLIGHTSTATE,
  1056. (DWORD)type, &(lpLset[i].dvArg[0]), TRUE);
  1057. if (hr != D3D_OK)
  1058. return hr;
  1059. }
  1060. }
  1061. continue;
  1062. }
  1063. case D3DLIGHTSTATE_AMBIENT:
  1064. {
  1065. DWORD color = lpLset[i].dwArg[0];
  1066. D3D_INFO(6, "in HEL D3DOP_STATELIGHT. D3DLIGHTSTATE_AMBIENT found");
  1067. LIGHTING.ambient_red = D3DVAL(RGBA_GETRED(color));
  1068. LIGHTING.ambient_green = D3DVAL(RGBA_GETGREEN(color));
  1069. LIGHTING.ambient_blue = D3DVAL(RGBA_GETBLUE(color));
  1070. LIGHTING.ambient_save = lpLset[i].dwArg[0];
  1071. lpDevI->dwFEFlags |= D3DFE_MATERIAL_DIRTY;
  1072. break;
  1073. }
  1074. case D3DLIGHTSTATE_FOGMODE:
  1075. D3D_INFO(6, "in HEL D3DOP_STATELIGHT. D3DLIGHTSTATE_FOG_MODE found");
  1076. LIGHTING.fog_mode = (D3DFOGMODE)lpLset[i].dwArg[0];
  1077. SetFogFlags(lpDevI);
  1078. break;
  1079. case D3DLIGHTSTATE_FOGSTART:
  1080. D3D_INFO(6, "in HEL D3DOP_STATELIGHT. D3DLIGHTSTATE_FOG_START found");
  1081. LIGHTING.fog_start = lpLset[i].dvArg[0];
  1082. if (lpDevI->dwFEFlags & D3DFE_FOGENABLED)
  1083. lpDevI->dwFEFlags |= D3DFE_FOG_DIRTY;
  1084. break;
  1085. case D3DLIGHTSTATE_FOGEND:
  1086. D3D_INFO(6, "in HEL D3DOP_STATELIGHT. D3DLIGHTSTATE_FOG_END found");
  1087. LIGHTING.fog_end = lpLset[i].dvArg[0];
  1088. if (lpDevI->dwFEFlags & D3DFE_FOGENABLED)
  1089. lpDevI->dwFEFlags |= D3DFE_FOG_DIRTY;
  1090. break;
  1091. case D3DLIGHTSTATE_FOGDENSITY:
  1092. D3D_INFO(6, "in HEL D3DOP_STATELIGHT. D3DLIGHTSTATE_FOG_DENSITY found");
  1093. LIGHTING.fog_density = lpLset[i].dvArg[0];
  1094. if (lpDevI->dwFEFlags & D3DFE_FOGENABLED)
  1095. lpDevI->dwFEFlags |= D3DFE_FOG_DIRTY;
  1096. break;
  1097. case D3DLIGHTSTATE_COLORMODEL:
  1098. D3D_INFO(6, "in HEL D3DOP_STATELIGHT. D3DLIGHTSTATE_COLORMODEL found");
  1099. LIGHTING.color_model = (D3DCOLORMODEL)lpLset[i].dwArg[0];
  1100. break;
  1101. case D3DLIGHTSTATE_COLORVERTEX:
  1102. D3D_INFO(6, "in HEL D3DOP_STATELIGHT. D3DLIGHTSTATE_COLORVERTEX found");
  1103. if (lpLset[i].dwArg[0])
  1104. lpDevI->dwFEFlags |= D3DFE_COLORVERTEX;
  1105. else
  1106. lpDevI->dwFEFlags &= ~D3DFE_COLORVERTEX;
  1107. break;
  1108. default:
  1109. D3D_WARN(1, "in HEL D3DOP_STATELIGHT. Invalid state type %d",
  1110. lpLset[i].dlstLightStateType);
  1111. return (DDERR_INVALIDPARAMS);
  1112. }
  1113. // Update ramp rasterizer if necessary
  1114. hr = CallRampService(lpDevI, RAMP_SERVICE_SETLIGHTSTATE,
  1115. (DWORD) type, &(lpLset[i].dvArg[0]));
  1116. if (hr != D3D_OK)
  1117. {
  1118. return hr;
  1119. }
  1120. }
  1121. return (D3D_OK);
  1122. }