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.

280 lines
11 KiB

  1. /*==========================================================================;
  2. *
  3. * Copyright (C) 1998 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. // Functions to use when lighting is done in the camera space
  14. LIGHT_VERTEX_FUNC_TABLE lightVertexTable =
  15. {
  16. Directional7,
  17. PointSpot7,
  18. DirectionalFirst,
  19. DirectionalNext,
  20. PointSpotFirst,
  21. PointSpotNext
  22. };
  23. // Functions to use when lighting is done in the model space
  24. static LIGHT_VERTEX_FUNC_TABLE lightVertexTableModel =
  25. {
  26. Directional7Model,
  27. PointSpot7Model,
  28. DirectionalFirstModel,
  29. DirectionalNextModel,
  30. PointSpotFirstModel,
  31. PointSpotNextModel
  32. };
  33. //-------------------------------------------------------------------------
  34. SpecularTable* CreateSpecularTable(D3DVALUE power)
  35. {
  36. SpecularTable* spec;
  37. int i;
  38. float delta = 1.0f/255.0f;
  39. float v;
  40. D3DMalloc((void**)&spec, sizeof(SpecularTable));
  41. if (spec == NULL)
  42. return NULL;
  43. spec->power = power;
  44. v = 0.0;
  45. for (i = 0; i < 256; i++)
  46. {
  47. spec->table[i] = powf(v, power);
  48. v += delta;
  49. }
  50. for (; i < 260; i++)
  51. spec->table[i] = 1.0f;
  52. return spec;
  53. }
  54. //-------------------------------------------------------------------------
  55. static void inverseRotateVector(D3DVECTOR* d,
  56. D3DVECTOR* v, D3DMATRIXI* M)
  57. {
  58. D3DVALUE vx = v->x;
  59. D3DVALUE vy = v->y;
  60. D3DVALUE vz = v->z;
  61. d->x = RLDDIFMul16(vx, M->_11) + RLDDIFMul16(vy, M->_12) + RLDDIFMul16(vz, M->_13);
  62. d->y = RLDDIFMul16(vx, M->_21) + RLDDIFMul16(vy, M->_22) + RLDDIFMul16(vz, M->_23);
  63. d->z = RLDDIFMul16(vx, M->_31) + RLDDIFMul16(vy, M->_32) + RLDDIFMul16(vz, M->_33);
  64. }
  65. static void inverseTransformVector(D3DVECTOR* result,
  66. D3DVECTOR* v, D3DMATRIXI* M)
  67. {
  68. D3DVALUE vx = v->x;
  69. D3DVALUE vy = v->y;
  70. D3DVALUE vz = v->z;
  71. vx -= M->_41; vy -= M->_42; vz -= M->_43;
  72. result->x = RLDDIFMul16(vx, M->_11) + RLDDIFMul16(vy, M->_12) + RLDDIFMul16(vz, M->_13);
  73. result->y = RLDDIFMul16(vx, M->_21) + RLDDIFMul16(vy, M->_22) + RLDDIFMul16(vz, M->_23);
  74. result->z = RLDDIFMul16(vx, M->_31) + RLDDIFMul16(vy, M->_32) + RLDDIFMul16(vz, M->_33);
  75. }
  76. //-----------------------------------------------------------------------
  77. // Every time the world matrix is modified or lights data is changed the
  78. // lighting vectors have to change to match the model space of the new data
  79. // to be rendered.
  80. // Every time light data is changed or material data is changed or lighting
  81. // state is changed, some pre-computed lighting values sould be updated
  82. //
  83. void D3DFE_UpdateLights(LPDIRECT3DDEVICEI lpDevI)
  84. {
  85. D3DFE_LIGHTING& LIGHTING = lpDevI->lighting;
  86. D3DI_LIGHT *light = LIGHTING.activeLights;
  87. D3DVECTOR t;
  88. BOOL specular; // TRUE, if specular component sould be computed
  89. D3DMATERIAL7 *mat = &LIGHTING.material;
  90. if (lpDevI->dwFEFlags & (D3DFE_MATERIAL_DIRTY | D3DFE_LIGHTS_DIRTY))
  91. {
  92. if (lpDevI->lighting.material.power > D3DVAL(0.001))
  93. {
  94. if (lpDevI->lighting.material.power > D3DVAL(0.001))
  95. {
  96. SpecularTable* spec;
  97. for (spec = LIST_FIRST(&lpDevI->specular_tables);
  98. spec;
  99. spec = LIST_NEXT(spec,list))
  100. {
  101. if (spec->power == lpDevI->lighting.material.power)
  102. break;
  103. }
  104. if (spec == NULL)
  105. {
  106. spec = CreateSpecularTable(lpDevI->lighting.material.power);
  107. if (spec == NULL)
  108. {
  109. D3D_ERR("Failed tp create specular table");
  110. throw DDERR_OUTOFMEMORY;
  111. }
  112. LIST_INSERT_ROOT(&lpDevI->specular_tables, spec, list);
  113. }
  114. lpDevI->specular_table = spec;
  115. lpDevI->lighting.specThreshold = D3DVAL(pow(0.001, 1.0/lpDevI->lighting.material.power));
  116. }
  117. else
  118. lpDevI->specular_table = NULL;
  119. }
  120. if (lpDevI->specular_table && lpDevI->dwDeviceFlags & D3DDEV_SPECULARENABLE)
  121. specular = TRUE;
  122. else
  123. specular = FALSE;
  124. LIGHTING.materialAlpha = FTOI(D3DVAL(255) * mat->diffuse.a);
  125. if (LIGHTING.materialAlpha < 0)
  126. LIGHTING.materialAlpha = 0;
  127. else
  128. if (LIGHTING.materialAlpha > 255)
  129. LIGHTING.materialAlpha = 255 << 24;
  130. else LIGHTING.materialAlpha <<= 24;
  131. LIGHTING.materialAlphaS = FTOI(D3DVAL(255) * mat->specular.a);
  132. if (LIGHTING.materialAlphaS < 0)
  133. LIGHTING.materialAlphaS = 0;
  134. else
  135. if (LIGHTING.materialAlphaS > 255)
  136. LIGHTING.materialAlphaS = 255 << 24;
  137. else LIGHTING.materialAlphaS <<= 24;
  138. LIGHTING.currentSpecTable = lpDevI->specular_table->table;
  139. LIGHTING.diffuse0.r = LIGHTING.ambientSceneScaled.r * mat->ambient.r;
  140. LIGHTING.diffuse0.g = LIGHTING.ambientSceneScaled.g * mat->ambient.g;
  141. LIGHTING.diffuse0.b = LIGHTING.ambientSceneScaled.b * mat->ambient.b;
  142. LIGHTING.diffuse0.r += mat->emissive.r * D3DVAL(255);
  143. LIGHTING.diffuse0.g += mat->emissive.g * D3DVAL(255);
  144. LIGHTING.diffuse0.b += mat->emissive.b * D3DVAL(255);
  145. int r,g,b;
  146. r = (int)FTOI(LIGHTING.diffuse0.r);
  147. g = (int)FTOI(LIGHTING.diffuse0.g);
  148. b = (int)FTOI(LIGHTING.diffuse0.b);
  149. if (r < 0) r = 0; else if (r > 255) r = 255;
  150. if (g < 0) g = 0; else if (g > 255) g = 255;
  151. if (b < 0) b = 0; else if (b > 255) b = 255;
  152. LIGHTING.dwDiffuse0 = (r << 16) + (g << 8) + b;
  153. }
  154. lpDevI->lighting.model_eye.x = (D3DVALUE)0;
  155. lpDevI->lighting.model_eye.y = (D3DVALUE)0;
  156. lpDevI->lighting.model_eye.z = (D3DVALUE)0;
  157. lpDevI->lighting.directionToCamera.x = 0;
  158. lpDevI->lighting.directionToCamera.y = 0;
  159. lpDevI->lighting.directionToCamera.z = -1;
  160. if (lpDevI->dwDeviceFlags & D3DDEV_MODELSPACELIGHTING)
  161. {
  162. inverseTransformVector(&lpDevI->lighting.model_eye,
  163. &lpDevI->lighting.model_eye,
  164. &lpDevI->mWV);
  165. lpDevI->lightVertexFuncTable = &lightVertexTableModel;
  166. inverseRotateVector(&lpDevI->lighting.directionToCamera,
  167. &lpDevI->lighting.directionToCamera,
  168. &lpDevI->mWV);
  169. }
  170. else
  171. {
  172. lpDevI->lightVertexFuncTable = &lightVertexTable;
  173. }
  174. while (light)
  175. {
  176. // Whenever light type is changed the D3DFE_NEED_TRANSFORM_LIGHTS should be set
  177. if (lpDevI->dwFEFlags & D3DFE_NEED_TRANSFORM_LIGHTS)
  178. {
  179. if (light->type != D3DLIGHT_DIRECTIONAL)
  180. { // Point and Spot lights
  181. light->lightVertexFunc = lpDevI->lightVertexFuncTable->pfnPointSpot;
  182. light->pfnLightFirst = lpDevI->lightVertexFuncTable->pfnPointSpotFirst;
  183. light->pfnLightNext = lpDevI->lightVertexFuncTable->pfnPointSpotNext;
  184. if (!(lpDevI->dwDeviceFlags & D3DDEV_MODELSPACELIGHTING))
  185. {
  186. // Transform light position to the camera space
  187. VecMatMul(&light->position,
  188. (D3DMATRIX*)&lpDevI->transform.view,
  189. &light->model_position);
  190. }
  191. else
  192. {
  193. inverseTransformVector(&light->model_position, &light->position,
  194. &lpDevI->transform.world[0]);
  195. }
  196. }
  197. else
  198. { // Directional light
  199. light->lightVertexFunc = lpDevI->lightVertexFuncTable->pfnDirectional;
  200. light->pfnLightFirst = lpDevI->lightVertexFuncTable->pfnDirectionalFirst;
  201. light->pfnLightNext = lpDevI->lightVertexFuncTable->pfnDirectionalNext;
  202. }
  203. if (light->type != D3DLIGHT_POINT)
  204. {
  205. // Light direction is flipped to be the direction TO the light
  206. if (!(lpDevI->dwDeviceFlags & D3DDEV_MODELSPACELIGHTING))
  207. {
  208. // Transform light direction to the camera space
  209. VecMatMul3(&light->direction,
  210. (D3DMATRIX*)&lpDevI->transform.view,
  211. &light->model_direction);
  212. VecNormalizeFast(light->model_direction);
  213. }
  214. else
  215. {
  216. inverseRotateVector(&light->model_direction, &light->direction,
  217. &lpDevI->transform.world[0]);
  218. }
  219. VecNeg(light->model_direction, light->model_direction);
  220. // For the infinite viewer the half vector is constant
  221. if (!(lpDevI->dwDeviceFlags & D3DDEV_LOCALVIEWER))
  222. {
  223. VecAdd(light->model_direction, lpDevI->lighting.directionToCamera,
  224. light->halfway);
  225. VecNormalizeFast(light->halfway);
  226. }
  227. }
  228. }
  229. if (lpDevI->dwFEFlags & (D3DFE_MATERIAL_DIRTY | D3DFE_LIGHTS_DIRTY))
  230. {
  231. light->diffuseMat.r = D3DVAL(255) * mat->diffuse.r * light->diffuse.r;
  232. light->diffuseMat.g = D3DVAL(255) * mat->diffuse.g * light->diffuse.g;
  233. light->diffuseMat.b = D3DVAL(255) * mat->diffuse.b * light->diffuse.b;
  234. if (!(light->flags & D3DLIGHTI_AMBIENT_IS_ZERO))
  235. {
  236. light->ambientMat.r = D3DVAL(255) * mat->ambient.r * light->ambient.r;
  237. light->ambientMat.g = D3DVAL(255) * mat->ambient.g * light->ambient.g;
  238. light->ambientMat.b = D3DVAL(255) * mat->ambient.b * light->ambient.b;
  239. }
  240. if (specular && !(light->flags & D3DLIGHTI_SPECULAR_IS_ZERO))
  241. {
  242. light->flags |= D3DLIGHTI_COMPUTE_SPECULAR;
  243. light->specularMat.r = D3DVAL(255) * mat->specular.r * light->specular.r;
  244. light->specularMat.g = D3DVAL(255) * mat->specular.g * light->specular.g;
  245. light->specularMat.b = D3DVAL(255) * mat->specular.b * light->specular.b;
  246. }
  247. else
  248. light->flags &= ~D3DLIGHTI_COMPUTE_SPECULAR;
  249. }
  250. light = light->next;
  251. }
  252. lpDevI->dwFEFlags &= ~(D3DFE_MATERIAL_DIRTY |
  253. D3DFE_NEED_TRANSFORM_LIGHTS |
  254. D3DFE_LIGHTS_DIRTY);
  255. } // end of updateLights()