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.

947 lines
28 KiB

  1. #include "pch.cpp"
  2. #pragma hdrstop
  3. ///////////////////////////////////////////////////////////////////////////////
  4. // Vertex Lighting function implementations
  5. ///////////////////////////////////////////////////////////////////////////////
  6. //---------------------------------------------------------------------
  7. void
  8. RRLV_Directional(
  9. RRLIGHTING& LData,
  10. D3DLIGHT7 *pLight,
  11. RRLIGHTI *pLightI,
  12. D3DLIGHTINGELEMENT *in,
  13. DWORD dwFlags,
  14. DWORD dwFVFIn)
  15. {
  16. // ATTENTION: Need to heed the specular flag set per light here!!
  17. BOOL bDoSpecular = dwFlags & RRPV_DOSPECULAR;
  18. BOOL bDoLocalViewer = dwFlags & RRPV_LOCALVIEWER;
  19. BOOL bDoColVertexAmbient = dwFlags & RRPV_COLORVERTEXAMB;
  20. BOOL bDoColVertexDiffuse = dwFlags & RRPV_COLORVERTEXDIFF;
  21. BOOL bDoColVertexSpecular = dwFlags & RRPV_COLORVERTEXSPEC;
  22. //
  23. // Add the material's ambient component
  24. //
  25. if (!bDoColVertexAmbient)
  26. {
  27. LData.diffuse.r += pLightI->Ma_La.r;
  28. LData.diffuse.g += pLightI->Ma_La.g;
  29. LData.diffuse.b += pLightI->Ma_La.b;
  30. }
  31. else
  32. {
  33. //
  34. // Note:
  35. // In case ColorVertexAmbient is enabled, note that it uses
  36. // VertexSpecular instead of VertexDiffuse
  37. //
  38. LData.diffuse.r += pLightI->La.r * LData.pAmbientSrc->r;
  39. LData.diffuse.g += pLightI->La.g * LData.pAmbientSrc->g;
  40. LData.diffuse.b += pLightI->La.b * LData.pAmbientSrc->b;
  41. }
  42. //
  43. // If no normals are present, bail out since we cannot perform the
  44. // normal-dependent computations
  45. //
  46. if( (dwFVFIn & D3DFVF_NORMAL) == 0 )
  47. {
  48. return;
  49. }
  50. D3DVALUE dot = DotProduct( pLightI->direction_in_eye, in->dvNormal );
  51. if (FLOAT_GTZ(dot))
  52. {
  53. if (!bDoColVertexDiffuse)
  54. {
  55. LData.diffuse.r += pLightI->Md_Ld.r * dot;
  56. LData.diffuse.g += pLightI->Md_Ld.g * dot;
  57. LData.diffuse.b += pLightI->Md_Ld.b * dot;
  58. }
  59. else
  60. {
  61. LData.diffuse.r += pLightI->Ld.r * LData.pDiffuseSrc->r * dot;
  62. LData.diffuse.g += pLightI->Ld.g * LData.pDiffuseSrc->g * dot;
  63. LData.diffuse.b += pLightI->Ld.b * LData.pDiffuseSrc->b * dot;
  64. }
  65. if (bDoSpecular)
  66. {
  67. D3DVECTOR h; // halfway vector
  68. D3DVECTOR eye; // incident vector ie vector from eye
  69. if (bDoLocalViewer)
  70. {
  71. // calc vector from vertex to the eye
  72. SubtractVector( LData.eye_in_eye, in->dvPosition, eye );
  73. // normalize
  74. Normalize( eye );
  75. }
  76. else
  77. {
  78. eye.x = D3DVALUE( 0.0 );
  79. eye.y = D3DVALUE( 0.0 );
  80. eye.z = D3DVALUE(-1.0 );
  81. }
  82. // calc halfway vector
  83. AddVector( pLightI->direction_in_eye, eye, h );
  84. // normalize
  85. Normalize( h );
  86. dot = DotProduct( h, in->dvNormal );
  87. if (FLOAT_GTZ(dot))
  88. {
  89. if (FLOAT_CMP_POS(dot, >=, LData.specThreshold))
  90. {
  91. D3DVALUE coeff = pow( dot, LData.material.power );
  92. if (!bDoColVertexSpecular)
  93. {
  94. LData.specular.r += pLightI->Ms_Ls.r * coeff;
  95. LData.specular.g += pLightI->Ms_Ls.g * coeff;
  96. LData.specular.b += pLightI->Ms_Ls.b * coeff;
  97. }
  98. else
  99. {
  100. LData.specular.r += (pLightI->Ls.r *
  101. LData.pSpecularSrc->r * coeff);
  102. LData.specular.g += (pLightI->Ls.g *
  103. LData.pSpecularSrc->g * coeff);
  104. LData.specular.b += (pLightI->Ls.b *
  105. LData.pSpecularSrc->b * coeff);
  106. }
  107. }
  108. }
  109. }
  110. }
  111. return;
  112. }
  113. void
  114. RRLV_PointAndSpot(
  115. RRLIGHTING &LData,
  116. D3DLIGHT7 *pLight,
  117. RRLIGHTI *pLightI,
  118. D3DLIGHTINGELEMENT *in,
  119. DWORD dwFlags,
  120. DWORD dwFVFIn)
  121. {
  122. // ATTENTION: Need to heed the specular flag set per light here!!
  123. BOOL bDoSpecular = dwFlags & RRPV_DOSPECULAR;
  124. BOOL bDoLocalViewer = dwFlags & RRPV_LOCALVIEWER;
  125. BOOL bDoColVertexAmbient = dwFlags & RRPV_COLORVERTEXAMB;
  126. BOOL bDoColVertexDiffuse = dwFlags & RRPV_COLORVERTEXDIFF;
  127. BOOL bDoColVertexSpecular = dwFlags & RRPV_COLORVERTEXSPEC;
  128. D3DVECTOR d; // Direction to light
  129. D3DVALUE att;
  130. D3DVALUE dist;
  131. D3DVALUE dot;
  132. SubtractVector( pLightI->position_in_eye, in->dvPosition, d );
  133. // early out if out of range or exactly on the vertex
  134. D3DVALUE distSquared = SquareMagnitude( d );
  135. if (FLOAT_CMP_POS(distSquared, >=, pLightI->range_squared) ||
  136. FLOAT_EQZ(distSquared))
  137. {
  138. return;
  139. }
  140. //
  141. // Compute the attenuation
  142. //
  143. dist = SQRTF( distSquared );
  144. att = pLight->dvAttenuation0 + pLight->dvAttenuation1 * dist +
  145. pLight->dvAttenuation2 * distSquared;
  146. if (FLOAT_EQZ(att))
  147. att = FLT_MAX;
  148. else
  149. att = (D3DVALUE)1.0/att;
  150. dist = D3DVAL(1)/dist;
  151. //
  152. // If the light is a spotlight compute the spot-light factor
  153. //
  154. if (pLight->dltType == D3DLIGHT_SPOT)
  155. {
  156. // Calc dot product of direction to light with light direction to
  157. // be compared anganst the cone angles to see if we are in the
  158. // light.
  159. // Note that cone_dot is still scaled by dist
  160. D3DVALUE cone_dot = DotProduct(d, pLightI->direction_in_eye) * dist;
  161. if (FLOAT_CMP_POS(cone_dot, <=, pLightI->cos_phi_by_2))
  162. {
  163. return;
  164. }
  165. // modify att if in the region between phi and theta
  166. if (FLOAT_CMP_POS(cone_dot, <, pLightI->cos_theta_by_2))
  167. {
  168. D3DVALUE val = (cone_dot - pLightI->cos_phi_by_2) *
  169. pLightI->inv_theta_minus_phi;
  170. if (!FLOAT_EQZ( pLight->dvFalloff - 1.0 ))
  171. {
  172. val = POWF( val, pLight->dvFalloff );
  173. }
  174. att *= val;
  175. }
  176. }
  177. //
  178. // Add the material's ambient component
  179. //
  180. if (!bDoColVertexAmbient)
  181. {
  182. LData.diffuse.r += att*pLightI->Ma_La.r;
  183. LData.diffuse.g += att*pLightI->Ma_La.g;
  184. LData.diffuse.b += att*pLightI->Ma_La.b;
  185. }
  186. else
  187. {
  188. //
  189. // Note:
  190. // In case ColorVertexAmbient is enabled, note that it uses
  191. // VertexSpecular instead of VertexDiffuse
  192. //
  193. LData.diffuse.r += att*pLightI->La.r * LData.pAmbientSrc->r;
  194. LData.diffuse.g += att*pLightI->La.g * LData.pAmbientSrc->g;
  195. LData.diffuse.b += att*pLightI->La.b * LData.pAmbientSrc->b;
  196. }
  197. // Calc dot product of light dir with normal. Note that since we
  198. // didn't normalize the direction the result is scaled by the distance.
  199. if( (dwFVFIn & D3DFVF_NORMAL) == 0)
  200. {
  201. // If no normals are present, bail out since we cannot perform the
  202. // normal-dependent computations
  203. return;
  204. }
  205. else
  206. {
  207. dot = DotProduct( d, in->dvNormal );
  208. }
  209. if (FLOAT_GTZ( dot ))
  210. {
  211. dot *= dist*att;
  212. if (!bDoColVertexDiffuse)
  213. {
  214. LData.diffuse.r += pLightI->Md_Ld.r * dot;
  215. LData.diffuse.g += pLightI->Md_Ld.g * dot;
  216. LData.diffuse.b += pLightI->Md_Ld.b * dot;
  217. }
  218. else
  219. {
  220. LData.diffuse.r += pLightI->Ld.r * LData.pDiffuseSrc->r * dot;
  221. LData.diffuse.g += pLightI->Ld.g * LData.pDiffuseSrc->g * dot;
  222. LData.diffuse.b += pLightI->Ld.b * LData.pDiffuseSrc->b * dot;
  223. }
  224. if (bDoSpecular)
  225. {
  226. D3DVECTOR h; // halfway vector
  227. D3DVECTOR eye; // incident vector ie vector from eye
  228. // normalize light direction
  229. d.x *= dist;
  230. d.y *= dist;
  231. d.z *= dist;
  232. if (bDoLocalViewer)
  233. {
  234. // calc vector from vertex to the eye
  235. SubtractVector( LData.eye_in_eye, in->dvPosition, eye );
  236. // normalize
  237. Normalize( eye );
  238. }
  239. else
  240. {
  241. eye.x = D3DVALUE( 0.0 );
  242. eye.y = D3DVALUE( 0.0 );
  243. eye.z = D3DVALUE(-1.0 );
  244. }
  245. // calc halfway vector
  246. AddVector( d, eye, h );
  247. Normalize( h );
  248. dot = DotProduct( h, in->dvNormal );
  249. if (FLOAT_CMP_POS(dot, >=, LData.specThreshold))
  250. {
  251. D3DVALUE coeff = pow( dot, LData.material.power ) * att;
  252. if (!bDoColVertexSpecular)
  253. {
  254. LData.specular.r += pLightI->Ms_Ls.r * coeff;
  255. LData.specular.g += pLightI->Ms_Ls.g * coeff;
  256. LData.specular.b += pLightI->Ms_Ls.b * coeff;
  257. }
  258. else
  259. {
  260. LData.specular.r += (pLightI->Ls.r *
  261. LData.pSpecularSrc->r * coeff);
  262. LData.specular.g += (pLightI->Ls.g *
  263. LData.pSpecularSrc->g * coeff);
  264. LData.specular.b += (pLightI->Ls.b *
  265. LData.pSpecularSrc->b * coeff);
  266. }
  267. }
  268. }
  269. }
  270. return;
  271. }
  272. ///////////////////////////////////////////////////////////////////////////////
  273. // RRLight
  274. ///////////////////////////////////////////////////////////////////////////////
  275. RRLight::RRLight()
  276. {
  277. m_dwFlags = RRLIGHT_NEEDSPROCESSING;
  278. m_Next = NULL;
  279. ZeroMemory(&m_Light, sizeof(m_Light));
  280. ZeroMemory(&m_LightI, sizeof(m_LightI));
  281. // Initialize the light to some default values
  282. m_Light.dltType = D3DLIGHT_DIRECTIONAL;
  283. m_Light.dcvDiffuse.r = 1;
  284. m_Light.dcvDiffuse.g = 1;
  285. m_Light.dcvDiffuse.b = 1;
  286. m_Light.dcvDiffuse.a = 0;
  287. m_Light.dvDirection.x = 0;
  288. m_Light.dvDirection.y = 0;
  289. m_Light.dvDirection.z = 1;
  290. // m_Light.dcvSpecular = {0,0,0,0};
  291. // m_Light.dcvAmbient = {0,0,0,0};
  292. // m_Light.dvPosition = {0,0,0};
  293. // m_Light.dvRange = 0;
  294. // m_Light.dvFalloff = 0;
  295. // m_Light.dvAttenuation0 = 0;
  296. // m_Light.dvAttenuation1 = 0;
  297. // m_Light.dvAttenuation2 = 0;
  298. // m_Light.dvTheta = 0;
  299. // m_Light.dvPhi = 0;
  300. return;
  301. }
  302. HRESULT
  303. RRLight::SetLight(LPD3DLIGHT7 pLight)
  304. {
  305. // Validate the parameters passed
  306. switch (pLight->dltType)
  307. {
  308. case D3DLIGHT_POINT:
  309. case D3DLIGHT_SPOT:
  310. case D3DLIGHT_DIRECTIONAL:
  311. break;
  312. default:
  313. // No other light types are allowed
  314. DPFRR(0, "Invalid light type passed");
  315. return DDERR_INVALIDPARAMS;
  316. }
  317. if (pLight)
  318. m_Light = *pLight;
  319. // Mark it for processing later
  320. m_dwFlags |= RRLIGHT_NEEDSPROCESSING;
  321. return DD_OK;
  322. }
  323. HRESULT
  324. RRLight::GetLight(LPD3DLIGHT7 pLight)
  325. {
  326. if (pLight == NULL) return DDERR_GENERIC;
  327. *pLight = m_Light;
  328. return D3D_OK;
  329. }
  330. void
  331. RRLight::ProcessLight(D3DMATERIAL7 *mat, RRLIGHTVERTEX_FUNC_TABLE *pTbl)
  332. {
  333. //
  334. // If it is already processed, return
  335. //
  336. if (!NeedsProcessing()) return;
  337. //
  338. // Save the ambient light (0-1)
  339. //
  340. m_LightI.La.r = m_Light.dcvAmbient.r;
  341. m_LightI.La.g = m_Light.dcvAmbient.g;
  342. m_LightI.La.b = m_Light.dcvAmbient.b;
  343. //
  344. // Save the diffuse light (0-1)
  345. //
  346. m_LightI.Ld.r = m_Light.dcvDiffuse.r;
  347. m_LightI.Ld.g = m_Light.dcvDiffuse.g;
  348. m_LightI.Ld.b = m_Light.dcvDiffuse.b;
  349. //
  350. // Save the specular light (0-1)
  351. //
  352. m_LightI.Ls.r = m_Light.dcvSpecular.r;
  353. m_LightI.Ls.g = m_Light.dcvSpecular.g;
  354. m_LightI.Ls.b = m_Light.dcvSpecular.b;
  355. //
  356. // Material Ambient times Light Ambient
  357. //
  358. m_LightI.Ma_La.r = m_LightI.La.r * mat->ambient.r * D3DVALUE(255.0);
  359. m_LightI.Ma_La.g = m_LightI.La.g * mat->ambient.g * D3DVALUE(255.0);
  360. m_LightI.Ma_La.b = m_LightI.La.b * mat->ambient.b * D3DVALUE(255.0);
  361. //
  362. // Material Diffuse times Light Diffuse
  363. //
  364. m_LightI.Md_Ld.r = m_LightI.Ld.r * mat->diffuse.r * D3DVALUE(255.0);
  365. m_LightI.Md_Ld.g = m_LightI.Ld.g * mat->diffuse.g * D3DVALUE(255.0);
  366. m_LightI.Md_Ld.b = m_LightI.Ld.b * mat->diffuse.b * D3DVALUE(255.0);
  367. //
  368. // Material Specular times Light Specular
  369. //
  370. m_LightI.Ms_Ls.r = m_LightI.Ls.r * mat->specular.r * D3DVALUE(255.0);
  371. m_LightI.Ms_Ls.g = m_LightI.Ls.g * mat->specular.g * D3DVALUE(255.0);
  372. m_LightI.Ms_Ls.b = m_LightI.Ls.b * mat->specular.b * D3DVALUE(255.0);
  373. //
  374. // Assign the actual lighting function pointer, in addition to
  375. // performing some precomputation of light-type specific data
  376. //
  377. m_pfnLightVertex = NULL;
  378. switch (m_Light.dltType)
  379. {
  380. case D3DLIGHT_DIRECTIONAL:
  381. m_pfnLightVertex = pTbl->pfnDirectional;
  382. break;
  383. case D3DLIGHT_POINT:
  384. m_LightI.range_squared = m_Light.dvRange * m_Light.dvRange;
  385. m_LightI.inv_theta_minus_phi = 1.0f;
  386. m_pfnLightVertex = pTbl->pfnPoint;
  387. break;
  388. case D3DLIGHT_SPOT:
  389. m_LightI.range_squared = m_Light.dvRange * m_Light.dvRange;
  390. m_LightI.cos_theta_by_2 = (float)cos(m_Light.dvTheta / 2.0);
  391. m_LightI.cos_phi_by_2 = (float)cos(m_Light.dvPhi / 2.0);
  392. m_LightI.inv_theta_minus_phi = m_LightI.cos_theta_by_2 -
  393. m_LightI.cos_phi_by_2;
  394. if (m_LightI.inv_theta_minus_phi != 0.0)
  395. {
  396. m_LightI.inv_theta_minus_phi = 1.0f/m_LightI.inv_theta_minus_phi;
  397. }
  398. else
  399. {
  400. m_LightI.inv_theta_minus_phi = 1.0f;
  401. }
  402. m_pfnLightVertex = pTbl->pfnSpot;
  403. break;
  404. default:
  405. DPFRR( 0, "Cannot process light of unknown type" );
  406. break;
  407. }
  408. // Mark it as been processed
  409. m_dwFlags &= ~RRLIGHT_NEEDSPROCESSING;
  410. return;
  411. }
  412. void
  413. RRLight::Enable(RRLight **ppRoot)
  414. {
  415. // Assert that it is not already enabled
  416. if (IsEnabled()) return;
  417. // Assert that Root Ptr is not Null
  418. if (ppRoot == NULL) return;
  419. RRLight *pTmp = *ppRoot;
  420. *ppRoot = this;
  421. m_Next = pTmp;
  422. m_dwFlags |= RRLIGHT_ENABLED;
  423. return;
  424. }
  425. void
  426. RRLight::Disable(RRLight **ppRoot)
  427. {
  428. // Assert that the light is enabled
  429. if (!IsEnabled()) return;
  430. // Assert that Root Ptr is not Null
  431. if (ppRoot == NULL) return;
  432. RRLight *pLightPrev = *ppRoot;
  433. // If this is the first light in the active list
  434. if (pLightPrev == this)
  435. {
  436. *ppRoot = m_Next;
  437. m_dwFlags &= ~RRLIGHT_ENABLED;
  438. return;
  439. }
  440. while (pLightPrev->m_Next != this)
  441. {
  442. // Though this light was marked as enabled, it is not on
  443. // the active list. Assert this.
  444. if (pLightPrev->m_Next == NULL)
  445. {
  446. m_dwFlags &= ~RRLIGHT_ENABLED;
  447. return;
  448. }
  449. // Else get the next pointer
  450. pLightPrev = pLightPrev->m_Next;
  451. }
  452. pLightPrev->m_Next = m_Next;
  453. m_dwFlags &= ~RRLIGHT_ENABLED;
  454. return;
  455. }
  456. void
  457. RRLight::XformLight( RRMATRIX *mView )
  458. {
  459. // If the light is not a directional light,
  460. // tranform its position to camera space
  461. if (m_Light.dltType != D3DLIGHT_DIRECTIONAL)
  462. {
  463. XformBy4x3(&m_Light.dvPosition, mView, &m_LightI.position_in_eye);
  464. }
  465. if (m_Light.dltType != D3DLIGHT_POINT)
  466. {
  467. // Transform light direction to the eye space
  468. Xform3VecBy3x3( &m_Light.dvDirection, mView,
  469. &m_LightI.direction_in_eye );
  470. // Normalize it
  471. Normalize( m_LightI.direction_in_eye );
  472. // Reverse it such that the direction is to the light
  473. ReverseVector( m_LightI.direction_in_eye, m_LightI.direction_in_eye );
  474. }
  475. return;
  476. }
  477. //---------------------------------------------------------------------
  478. // ScaleRGBColorTo255: Scales colors from 0-1 range to 0-255 range
  479. //---------------------------------------------------------------------
  480. void
  481. ScaleRGBColorTo255( const D3DCOLORVALUE& src, RRCOLOR& dest )
  482. {
  483. dest.r = D3DVALUE(255.0) * src.r;
  484. dest.g = D3DVALUE(255.0) * src.g;
  485. dest.b = D3DVALUE(255.0) * src.b;
  486. }
  487. //---------------------------------------------------------------------
  488. // RRProcessVertices::UpdateLightingData
  489. // Updates lighting data used by ProcessVertices
  490. //---------------------------------------------------------------------
  491. HRESULT
  492. RRProcessVertices::UpdateLightingData()
  493. {
  494. HRESULT hr = D3D_OK;
  495. RRLIGHTING& LData = m_lighting;
  496. RRLight *pLight = m_lighting.pActiveLights;
  497. D3DVECTOR t;
  498. D3DMATERIAL7 *mat = &m_Material;
  499. //
  500. // Eye in eye space
  501. //
  502. LData.eye_in_eye.x = (D3DVALUE)0;
  503. LData.eye_in_eye.y = (D3DVALUE)0;
  504. LData.eye_in_eye.z = (D3DVALUE)0;
  505. // ATTENTION: Colorvertex may have changed the values of the
  506. // material alphas
  507. if (m_dwDirtyFlags & RRPV_DIRTY_MATERIAL)
  508. {
  509. //
  510. // Save the material to be used to light vertices
  511. //
  512. LData.material = *mat;
  513. ScaleRGBColorTo255( mat->ambient, LData.matAmb );
  514. ScaleRGBColorTo255( mat->diffuse, LData.matDiff );
  515. ScaleRGBColorTo255( mat->specular, LData.matSpec );
  516. ScaleRGBColorTo255( mat->emissive, LData.matEmis );
  517. //
  518. // Compute the Material Diffuse Alpha
  519. //
  520. LData.materialDiffAlpha = mat->diffuse.a * D3DVALUE(255);
  521. if (mat->diffuse.a < 0)
  522. LData.materialDiffAlpha = 0;
  523. else if (LData.materialDiffAlpha > 255)
  524. LData.materialDiffAlpha = 255 << 24;
  525. else LData.materialDiffAlpha <<= 24;
  526. //
  527. // Compute the Material Specular Alpha
  528. //
  529. LData.materialSpecAlpha = mat->specular.a * D3DVALUE(255);
  530. if (mat->specular.a < 0)
  531. LData.materialSpecAlpha = 0;
  532. else if (LData.materialSpecAlpha > 255)
  533. LData.materialSpecAlpha = 255 << 24;
  534. else LData.materialSpecAlpha <<= 24;
  535. //
  536. // Precompute the ambient and emissive components that are
  537. // not dependent on any contribution by the lights themselves
  538. //
  539. LData.ambEmiss.r = LData.ambient_red * LData.matAmb.r +
  540. LData.matEmis.r;
  541. LData.ambEmiss.g = LData.ambient_green * LData.matAmb.g +
  542. LData.matEmis.g;
  543. LData.ambEmiss.b = LData.ambient_blue * LData.matAmb.b +
  544. LData.matEmis.b;
  545. //
  546. // If the dot product is less than this
  547. // value, specular factor is zero
  548. //
  549. if (mat->power > D3DVAL(0.001))
  550. {
  551. LData.specThreshold = D3DVAL(pow(0.001, 1.0/mat->power));
  552. }
  553. }
  554. while (pLight)
  555. {
  556. if ((m_dwDirtyFlags & RRPV_DIRTY_MATERIAL) ||
  557. pLight->NeedsProcessing())
  558. {
  559. // If the material is dirty, light needs processing, regardless
  560. if (m_dwDirtyFlags & RRPV_DIRTY_MATERIAL)
  561. {
  562. pLight->m_dwFlags |= RRLIGHT_NEEDSPROCESSING;
  563. }
  564. // If the light has been set, or some material paramenters
  565. // changed, re-process the light.
  566. pLight->ProcessLight( &m_Material, &m_LightVertexTable );
  567. // Transform the light to Eye space
  568. // Lights are defined in world space, so simply apply the
  569. // Viewing transform
  570. pLight->XformLight( &m_xfmView );
  571. }
  572. else if (m_dwDirtyFlags & RRPV_DIRTY_NEEDXFMLIGHT)
  573. {
  574. pLight->XformLight( &m_xfmView );
  575. }
  576. pLight = pLight->m_Next;
  577. }
  578. // Clear Lighting dirty flags
  579. m_dwDirtyFlags &= ~RRPV_DIRTY_LIGHTING;
  580. return hr;
  581. }
  582. //---------------------------------------------------------------------
  583. // RRProcessVertices::UpdateFogData
  584. // Updates Fog data used by ProcessVertices
  585. //---------------------------------------------------------------------
  586. HRESULT
  587. RRProcessVertices::UpdateFogData()
  588. {
  589. HRESULT hr = D3D_OK;
  590. if (m_lighting.fog_end == m_lighting.fog_start)
  591. m_lighting.fog_factor = D3DVAL(0.0);
  592. else
  593. m_lighting.fog_factor = D3DVAL(255) / (m_lighting.fog_end -
  594. m_lighting.fog_start);
  595. // Clear Fog dirty flags
  596. m_dwDirtyFlags &= ~RRPV_DIRTY_FOG;
  597. return hr;
  598. }
  599. //---------------------------------------------------------------------
  600. // RRProcessVertices::LightVertex
  601. // Actual lighting computation takes place here
  602. //---------------------------------------------------------------------
  603. void
  604. RRProcessVertices::LightVertex(D3DLIGHTINGELEMENT *pLE)
  605. {
  606. RRLIGHTING &LData = m_lighting;
  607. RRLight *pLight;
  608. //
  609. // Initialize Diffuse color with the Ambient and Emissive component
  610. // independent of the light (Ma*La + Me)
  611. //
  612. if (m_dwTLState & (RRPV_COLORVERTEXEMIS | RRPV_COLORVERTEXAMB))
  613. {
  614. // If the material values need to be replaced, compute
  615. LData.diffuse.r = LData.ambient_red * LData.pAmbientSrc->r +
  616. LData.pEmissiveSrc->r;
  617. LData.diffuse.g = LData.ambient_green * LData.pAmbientSrc->g +
  618. LData.pEmissiveSrc->g;
  619. LData.diffuse.b = LData.ambient_blue * LData.pAmbientSrc->b +
  620. LData.pEmissiveSrc->b;
  621. }
  622. else
  623. {
  624. // If none of the material values needs to be replaced
  625. LData.diffuse = LData.ambEmiss;
  626. }
  627. //
  628. // Initialize the Specular to Zero
  629. //
  630. LData.specular.r = D3DVAL(0);
  631. LData.specular.g = D3DVAL(0);
  632. LData.specular.b = D3DVAL(0);
  633. //
  634. // In a loop accumulate color from the activated lights
  635. //
  636. pLight = LData.pActiveLights;
  637. while (pLight)
  638. {
  639. if (pLight->m_pfnLightVertex)
  640. (*pLight->m_pfnLightVertex)(m_lighting,
  641. &pLight->m_Light,
  642. &pLight->m_LightI,
  643. pLE,
  644. m_dwTLState,
  645. m_dwFVFIn);
  646. pLight = pLight->m_Next;
  647. }
  648. //
  649. // Compute the diffuse color of the vertex
  650. //
  651. int r = FTOI(LData.diffuse.r);
  652. int g = FTOI(LData.diffuse.g);
  653. int b = FTOI(LData.diffuse.b);
  654. DWORD a = *LData.pDiffuseAlphaSrc;
  655. //
  656. // Clamp the r, g, b, components
  657. //
  658. if (r < 0) r = 0; else if (r > 255) r = 255;
  659. if (g < 0) g = 0; else if (g > 255) g = 255;
  660. if (b < 0) b = 0; else if (b > 255) b = 255;
  661. LData.outDiffuse = a + (r<<16) + (g<<8) + b;
  662. //
  663. // Obtain the specular Alpha
  664. //
  665. a = *(LData.pSpecularAlphaSrc);
  666. //
  667. // Compute the RGB part of the specular color
  668. //
  669. if (m_dwTLState & RRPV_DOSPECULAR)
  670. {
  671. r = FTOI(LData.specular.r);
  672. g = FTOI(LData.specular.g);
  673. b = FTOI(LData.specular.b);
  674. //
  675. // Clamp the r, g, b, components
  676. //
  677. if (r < 0) r = 0; else if (r > 255) r = 255;
  678. if (g < 0) g = 0; else if (g > 255) g = 255;
  679. if (b < 0) b = 0; else if (b > 255) b = 255;
  680. }
  681. //
  682. // If SPECULAR is not enabled but the specular color
  683. // had been provided in the input vertex, simply copy.
  684. //
  685. else if ( m_qwFVFOut & D3DFVF_SPECULAR )
  686. {
  687. r = FTOI(LData.vertexSpecular.r);
  688. g = FTOI(LData.vertexSpecular.g);
  689. b = FTOI(LData.vertexSpecular.b);
  690. a = LData.vertexSpecAlpha;
  691. }
  692. //
  693. // If SpecularColor is not enabled
  694. //
  695. else
  696. {
  697. r = g = b = 0;
  698. }
  699. LData.outSpecular = a + (r<<16) + (g<<8) + b;
  700. return;
  701. }
  702. //---------------------------------------------------------------------
  703. // RRProcessVertices::FogVertex
  704. // Vertex Fog computation
  705. // Input:
  706. // v - input vertex in the model space
  707. // le - vertex, transformed to the camera space
  708. // Output:
  709. // Alpha component of pv->lighting.outSpecular is set
  710. //---------------------------------------------------------------------
  711. #define RRPV_SET_ALPHA(color, a) ((char*)&color)[3] = (unsigned char)a;
  712. void
  713. RRProcessVertices::FogVertex(D3DVECTOR &v,
  714. D3DLIGHTINGELEMENT *pLE,
  715. int numVertexBlends,
  716. float *pBlendFactors,
  717. BOOL bVertexInEyeSpace)
  718. {
  719. D3DVALUE dist = 0.0f;
  720. //
  721. // Calculate the distance
  722. //
  723. if (bVertexInEyeSpace)
  724. {
  725. // Vertex is already transformed to the camera space
  726. if (m_dwTLState & RRPV_RANGEFOG)
  727. {
  728. dist = SQRTF(pLE->dvPosition.x*pLE->dvPosition.x +
  729. pLE->dvPosition.y*pLE->dvPosition.y +
  730. pLE->dvPosition.z*pLE->dvPosition.z);
  731. }
  732. else
  733. {
  734. dist = pLE->dvPosition.z;
  735. }
  736. }
  737. else if (m_dwTLState & RRPV_RANGEFOG)
  738. {
  739. D3DVALUE x = 0, y = 0, z = 0;
  740. float cumulBlend = 0.0f;
  741. for( int j=0; j<=numVertexBlends; j++)
  742. {
  743. float blend;
  744. if( numVertexBlends == 0 )
  745. {
  746. blend = 1.0f;
  747. }
  748. else if( j == numVertexBlends )
  749. {
  750. blend = 1.0f - cumulBlend;
  751. }
  752. else
  753. {
  754. blend = pBlendFactors[j];
  755. }
  756. cumulBlend += pBlendFactors[j];
  757. x += (v.x*m_xfmToEye[j]._11 +
  758. v.y*m_xfmToEye[j]._21 +
  759. v.z*m_xfmToEye[j]._31 +
  760. m_xfmToEye[j]._41) * blend;
  761. y += (v.x*m_xfmToEye[j]._12 +
  762. v.y*m_xfmToEye[j]._22 +
  763. v.z*m_xfmToEye[j]._32 +
  764. m_xfmToEye[j]._42) * blend;
  765. z += (v.x*m_xfmToEye[j]._13 +
  766. v.y*m_xfmToEye[j]._23 +
  767. v.z*m_xfmToEye[j]._33 +
  768. m_xfmToEye[j]._43) * blend;
  769. }
  770. dist = SQRTF(x*x + y*y + z*z);
  771. }
  772. else
  773. {
  774. float cumulBlend = 0.0f;
  775. for( int j=0; j<=numVertexBlends; j++)
  776. {
  777. float blend;
  778. if( numVertexBlends == 0 )
  779. {
  780. blend = 1.0f;
  781. }
  782. else if( j == numVertexBlends )
  783. {
  784. blend = 1.0f - cumulBlend;
  785. }
  786. else
  787. {
  788. blend = pBlendFactors[j];
  789. }
  790. cumulBlend += pBlendFactors[j];
  791. dist += (v.x*m_xfmToEye[j]._13 +
  792. v.y*m_xfmToEye[j]._23 +
  793. v.z*m_xfmToEye[j]._33 +
  794. m_xfmToEye[j]._43) * blend;
  795. }
  796. }
  797. if (m_lighting.fog_mode == D3DFOG_LINEAR)
  798. {
  799. if (dist < m_lighting.fog_start)
  800. {
  801. RRPV_SET_ALPHA(m_lighting.outSpecular, 255);
  802. }
  803. else if (dist >= m_lighting.fog_end)
  804. {
  805. RRPV_SET_ALPHA(m_lighting.outSpecular, 0);
  806. }
  807. else
  808. {
  809. D3DVALUE v = (m_lighting.fog_end - dist) * m_lighting.fog_factor;
  810. int f = FTOI(v);
  811. RRPV_SET_ALPHA(m_lighting.outSpecular, f);
  812. }
  813. }
  814. else
  815. {
  816. D3DVALUE tmp = dist * m_lighting.fog_density;
  817. if (m_lighting.fog_mode == D3DFOG_EXP2)
  818. {
  819. tmp *= tmp;
  820. }
  821. tmp = (D3DVALUE)exp(-tmp) * 255.0f;
  822. int f = FTOI(tmp);
  823. RRPV_SET_ALPHA( m_lighting.outSpecular, f )
  824. }
  825. return;
  826. }