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.

1229 lines
50 KiB

  1. /*==========================================================================;
  2. *
  3. * Copyright (C) 1998 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: loops.mcp
  6. * Content: Generates code for multiple loop geometry pipeline
  7. *
  8. ***************************************************************************/
  9. #include "pch.cpp"
  10. #pragma hdrstop
  11. #include "light.h"
  12. #include "clipper.h"
  13. #include "drawprim.hpp"
  14. #include "pvvid.h"
  15. include(`pvvid.mh') dnl
  16. dnl//------------------------------------------------------------------
  17. dnl// d_ComputeSpecular
  18. dnl//
  19. dnl// Generates code to compute specular component based on a dot product
  20. dnl//
  21. dnl// Arguments:
  22. dnl// $1 - margin count
  23. dnl// $2 - if present, equal to the attenuation factor
  24. dnl// dot - dot product
  25. dnl// pv - process vertices structure
  26. dnl// d_Op - operation "=" or "+="
  27. dnl// d_LightingFlags - DWORD
  28. dnl// d_SPECULARCOMPUTED - bit
  29. dnl// d_pInpSpecular - vertex specular color (DWORD*)
  30. dnl// d_OutSpecular - output specular color, (D3DFE_COLOR)
  31. dnl//
  32. define(`d_ComputeSpecular',`dnl
  33. d_empty_($1)if (FLOAT_CMP_POS(dot, >=, pv->lighting.specThreshold))
  34. d_margin($1){
  35. d_margin($1) d_LightingFlags |= __LIGHT_SPECULARCOMPUTED;
  36. d_margin($1) // Compute power = dot**SpecularExponent;
  37. d_margin($1) D3DVALUE power;
  38. d_margin($1) if (FLOAT_CMP_PONE(dot, <))
  39. d_margin($1) {
  40. d_margin($1) int indx;
  41. d_margin($1) float v;
  42. d_margin($1) dot *= 255.0f;
  43. d_margin($1) indx = FTOI(dot);
  44. d_margin($1) dot -= indx;
  45. d_margin($1) v = pv->lighting.currentSpecTable[indx];
  46. d_margin($1) power = v + (pv->lighting.currentSpecTable[indx+1] - v)*dot;
  47. d_margin($1) }
  48. d_margin($1) else
  49. d_margin($1) power = pv->lighting.currentSpecTable[255];
  50. dnl
  51. ifelse($#,2,`d_margin($1+1)power*= $2;')dnl// If parameter 2 (attenuation) is present, use it
  52. d_margin($1) // Update specular component
  53. d_margin($1) if (!(dwFlags & D3DPV_COLORVERTEX_S))
  54. d_margin($1) {
  55. d_margin($1) d_OutSpecular.r d_Op light->specularMat.r * power;
  56. d_margin($1) d_OutSpecular.g d_Op light->specularMat.g * power;
  57. d_margin($1) d_OutSpecular.b d_Op light->specularMat.b * power;
  58. d_margin($1) }
  59. d_margin($1) else
  60. d_margin($1) {
  61. d_margin($1) const D3DVALUE r = (D3DVALUE)RGBA_GETRED(*d_pInpSpecular);
  62. d_margin($1) const D3DVALUE g = (D3DVALUE)RGBA_GETGREEN(*d_pInpSpecular);
  63. d_margin($1) const D3DVALUE b = (D3DVALUE)RGBA_GETBLUE(*d_pInpSpecular);
  64. d_margin($1) d_OutSpecular.r d_Op light->specular.r * r * power;
  65. d_margin($1) d_OutSpecular.g d_Op light->specular.g * g * power;
  66. d_margin($1) d_OutSpecular.b d_Op light->specular.b * b * power;
  67. d_margin($1) }
  68. d_margin($1)}')dnl
  69. dnl//------------------------------------------------------------------
  70. dnl// d_UpdateDiffuseColor
  71. dnl//
  72. dnl// Generates code to compute diffuse component, based on a dot product
  73. dnl//
  74. dnl// Arguments:
  75. dnl// $1 - margin count
  76. dnl// $2 - operation "=" or "+="
  77. dnl// dot - dot product
  78. dnl// d_LightingFlags - DWORD
  79. dnl// d_pInpDiffuse - vertex specular color (DWORD*)
  80. dnl// d_OutDiffuse - output specular color, (D3DFE_COLOR)
  81. dnl//
  82. define(`d_UpdateDiffuseColor',`dnl
  83. d_empty_($1)if (!(dwFlags & D3DPV_COLORVERTEX_D))
  84. d_margin($1){
  85. d_margin($1) d_OutDiffuse.r $2 light->diffuseMat.r * dot;
  86. d_margin($1) d_OutDiffuse.g $2 light->diffuseMat.g * dot;
  87. d_margin($1) d_OutDiffuse.b $2 light->diffuseMat.b * dot;
  88. d_margin($1)}
  89. d_margin($1)else
  90. d_margin($1){
  91. d_margin($1) const D3DVALUE r = (D3DVALUE)RGBA_GETRED(*d_pInpDiffuse);
  92. d_margin($1) const D3DVALUE g = (D3DVALUE)RGBA_GETGREEN(*d_pInpDiffuse);
  93. d_margin($1) const D3DVALUE b = (D3DVALUE)RGBA_GETBLUE(*d_pInpDiffuse);
  94. d_margin($1) d_OutDiffuse.r $2 light->diffuse.r * r * dot;
  95. d_margin($1) d_OutDiffuse.g $2 light->diffuse.g * g * dot;
  96. d_margin($1) d_OutDiffuse.b $2 light->diffuse.b * b * dot;
  97. d_margin($1)}
  98. d_margin($1)d_LightingFlags |= __LIGHT_DIFFUSECOMPUTED;')dnl
  99. dnl//------------------------------------------------------------------
  100. dnl// d_UpdateAmbientColor
  101. dnl//
  102. dnl// Generates code to compute ambient component
  103. dnl//
  104. dnl// Arguments:
  105. dnl// $1 - margin count
  106. dnl// $2 - "* att" or empty
  107. dnl// dot - dot product
  108. dnl// d_Op - operation "=" or "+="
  109. dnl// d_LightingFlags - DWORD
  110. dnl// d_OutDiffuse - output specular color, (D3DFE_COLOR)
  111. dnl//
  112. define(`d_UpdateAmbientColor',`dnl
  113. d_empty_($1)if (!(light->flags & D3DLIGHTI_AMBIENT_IS_ZERO))
  114. d_margin($1){
  115. d_margin($1) if (!(dwFlags & D3DPV_COLORVERTEX_A))
  116. d_margin($1) {
  117. d_margin($1) d_OutDiffuse.r d_Op light->ambientMat.r $2;
  118. d_margin($1) d_OutDiffuse.g d_Op light->ambientMat.g $2;
  119. d_margin($1) d_OutDiffuse.b d_Op light->ambientMat.b $2;
  120. d_margin($1) }
  121. d_margin($1) else
  122. d_margin($1) {
  123. d_margin($1) const D3DVALUE r = (D3DVALUE)RGBA_GETRED(*d_pInpAmbient);
  124. d_margin($1) const D3DVALUE g = (D3DVALUE)RGBA_GETGREEN(*d_pInpAmbient);
  125. d_margin($1) const D3DVALUE b = (D3DVALUE)RGBA_GETBLUE(*d_pInpAmbient);
  126. d_margin($1) d_OutDiffuse.r d_Op light->ambient.r * r $2;
  127. d_margin($1) d_OutDiffuse.g d_Op light->ambient.g * g $2;
  128. d_margin($1) d_OutDiffuse.b d_Op light->ambient.b * b $2;
  129. d_margin($1) }
  130. d_margin($1) d_LightingFlags |= __LIGHT_DIFFUSECOMPUTED;
  131. d_margin($1)}')dnl
  132. dnl//------------------------------------------------------------------
  133. dnl// d_Directional7
  134. dnl//
  135. dnl// Generate code to light a vertex using directional or parallel point light.
  136. dnl// Model space and camera space lighting are handled
  137. dnl//
  138. dnl// Arguments:
  139. dnl/ $1 - margin count
  140. dnl// d_pInpPosition - input normal pointer (D3DVERTEX*)
  141. dnl// d_TmpPosition - temporary position buffer (D3DVECTOR).
  142. dnl// Used in camera space lighting
  143. dnl// d_pInpNormal - input normal pointer (D3DVECTOR*)
  144. dnl// d_TmpNormal - temporary normal buffer (D3DVECTOR)
  145. dnl// Used in camera space lighting
  146. dnl// d_Space - Defines the coordinate system: modelSpace or cameraSpace
  147. dnl// d_LightingFlags - DWORD where __LIGHT_ bits are defined
  148. dnl//
  149. define(`d_Directional7',`dnl
  150. d_empty_($1)D3DVALUE dot;
  151. d_margin($1)d_UpdateAmbientColor($1)
  152. d_margin($1)if (!(pv->dwVIDIn & D3DFVF_NORMAL))
  153. d_margin($1) goto l_exit;
  154. d_margin($1)
  155. ifelse(d_Space,modelSpace,`
  156. d_margin($1)dot = VecDot(light->model_direction, (*d_pInpNormal));',`
  157. ifelse(d_Op,+=,`
  158. d_margin($1)if (!(d_LightingFlags & __LIGHT_NORMALTRANSFORMED))')
  159. d_margin($1){
  160. d_margin($1) d_TransformNormalToCameraSpace($1+1, d_pInpNormal, (&d_TmpNormal), d_pInpPosition)
  161. d_margin($1) d_LightingFlags |= __LIGHT_NORMALTRANSFORMED;
  162. d_margin($1)}
  163. d_margin($1)dot = VecDot(light->model_direction, d_TmpNormal);')
  164. dnl// endif
  165. d_margin($1)
  166. d_margin($1)if (FLOAT_GTZ(dot))
  167. d_margin($1){
  168. ifelse(d_Op,+=,`dnl
  169. d_margin($1) d_UpdateDiffuseColor($1+1,+=)',`
  170. d_margin($1) if (!(d_LightingFlags & __LIGHT_DIFFUSECOMPUTED))
  171. d_margin($1) {
  172. d_margin($1) d_UpdateDiffuseColor($1+2, d_Op)
  173. d_margin($1) }
  174. d_margin($1) else
  175. d_margin($1) {
  176. d_margin($1) d_UpdateDiffuseColor($1+2,+=)
  177. d_margin($1) }')
  178. d_margin($1) if (light->flags & D3DLIGHTI_COMPUTE_SPECULAR)
  179. d_margin($1) {
  180. d_margin($1) D3DVECTOR h; // halfway vector
  181. d_margin($1) D3DVECTOR eye; // incident vector ie vector from eye
  182. d_margin($1)ifelse(d_Space,modelSpace,`
  183. d_margin($1) if (pv->dwDeviceFlags & D3DDEV_LOCALVIEWER)
  184. d_margin($1) {
  185. d_margin($1) // calc vector from vertex to the camera
  186. d_margin($1) VecSub(pv->lighting.model_eye, (*(D3DVECTOR*)d_pInpPosition), eye);
  187. d_margin($1) VecNormalizeFast(eye);
  188. d_margin($1) VecAdd(light->model_direction, eye, h); // calc halfway vector
  189. d_margin($1) dot = VecDot(h, (*d_pInpNormal));
  190. d_margin($1) }
  191. d_margin($1) else
  192. d_margin($1) {
  193. d_margin($1) dot = VecDot(light->halfway, (*d_pInpNormal));
  194. d_margin($1) }',`
  195. dnl// else
  196. d_margin($1)ifelse(d_Op,+=,`
  197. d_margin($1) if (!(d_LightingFlags & __LIGHT_VERTEXTRANSFORMED))')
  198. dnl// endif
  199. d_margin($1) {
  200. d_margin($1) d_TransformVertexToCameraSpace($1+3, d_pInpPosition, (&d_TmpPosition))
  201. d_margin($1) d_LightingFlags |= __LIGHT_VERTEXTRANSFORMED;
  202. d_margin($1) }
  203. d_margin($1) if (pv->dwDeviceFlags & D3DDEV_LOCALVIEWER)
  204. d_margin($1) {
  205. d_margin($1) // calc vector from vertex to the camera
  206. d_margin($1) VecSub(pv->lighting.model_eye, d_TmpPosition, eye);
  207. d_margin($1) VecNormalizeFast(eye);
  208. d_margin($1) VecAdd(light->model_direction, eye, h); // calc halfway vector
  209. d_margin($1) dot = VecDot(h, d_TmpNormal);
  210. d_margin($1) }
  211. d_margin($1) else
  212. d_margin($1) {
  213. d_margin($1) dot = VecDot(light->halfway, d_TmpNormal);
  214. d_margin($1) }')
  215. dnl// endif
  216. d_margin($1) if (FLOAT_GTZ(dot))
  217. d_margin($1) {
  218. d_margin($1) if (pv->dwDeviceFlags & D3DDEV_LOCALVIEWER)
  219. d_margin($1) dot *= ISQRTF(VecLenSq(h));
  220. d_margin($1) d_ComputeSpecular($1+3);
  221. d_margin($1) }
  222. d_margin($1) }
  223. d_margin($1)}
  224. d_margin($1)l_exit:;
  225. d_margin($1)')dnl
  226. dnl//------------------------------------------------------------------
  227. dnl// d_PointSpot7
  228. dnl//
  229. dnl// Generate code to light a vertex using point spot light.
  230. dnl// Model space and camera space lighting are handled
  231. dnl//
  232. dnl// Arguments:
  233. dnl/ $1 - margin count
  234. dnl// d_pInpPosition - input normal pointer (D3DVERTEX*)
  235. dnl// d_TmpPosition - temporary position buffer (D3DVECTOR).
  236. dnl// Used in camera space lighting
  237. dnl// d_pInpNormal - input normal pointer (D3DVECTOR*)
  238. dnl// d_TmpNormal - temporary normal buffer (D3DVECTOR)
  239. dnl// Used in camera space lighting
  240. dnl// d_Space - Defines the coordinate system: modelSpace or cameraSpace
  241. dnl// d_LightingFlags - DWORD where __LIGHT_ bits are defined
  242. dnl//
  243. define(`d_PointSpot7',`dnl
  244. d_margin($1)D3DVALUE dot; // dot product
  245. d_margin($1)D3DVALUE dist; // Distance from light to the vertex
  246. d_margin($1)D3DVALUE dist2; // Square of the dist
  247. d_margin($1)D3DVECTOR d; // Direction to light
  248. d_margin($1)D3DVALUE att; // attenuation
  249. ifelse(d_Space,modelSpace,`dnl
  250. d_margin($1)VecSub(light->model_position, (*(D3DVECTOR*)d_pInpPosition), d);',`dnl
  251. ifelse(d_Op,+=,`dnl
  252. d_margin($1)if (!(d_LightingFlags & __LIGHT_VERTEXTRANSFORMED))')
  253. dnl// endif
  254. d_margin($1){
  255. d_margin($1) d_TransformVertexToCameraSpace($1+1, d_pInpPosition, (&d_TmpPosition))
  256. d_margin($1) d_LightingFlags |= __LIGHT_VERTEXTRANSFORMED;
  257. d_margin($1)}
  258. d_margin($1)VecSub(light->model_position, d_TmpPosition, d);')dnl
  259. dnl// endif
  260. d_margin($1)// early out if out of range or exactly on the vertex
  261. d_margin($1)dist2 = d.x*d.x + d.y*d.y + d.z*d.z;
  262. d_margin($1)if (FLOAT_CMP_POS(dist2, >=, light->range_squared) || FLOAT_EQZ(dist2))
  263. d_margin($1) goto l_exit;
  264. d_margin($1)dot = 0; // It is possible not to have normals (ambient component only)
  265. d_margin($1) // So we set dot to zero for this case
  266. d_margin($1)// Calc dot product of light dir with normal. Note that since we
  267. d_margin($1)// did not normalize the direction the result is scaled by the distance.
  268. ifelse(d_Space,modelSpace,`dnl
  269. d_margin($1)if (pv->dwVIDIn & D3DFVF_NORMAL)
  270. d_margin($1){
  271. d_margin($1) dot = VecDot(d, (*d_pInpNormal));
  272. d_margin($1)}',`
  273. d_margin($1)if (pv->dwVIDIn & D3DFVF_NORMAL)
  274. d_margin($1){
  275. ifelse(d_Op,+=,`dnl Normal should be transformed by the first light. So do not check.
  276. d_margin($1) if (!(d_LightingFlags & __LIGHT_NORMALTRANSFORMED))')
  277. d_margin($1) {
  278. d_margin($1) d_TransformNormalToCameraSpace($1+1, d_pInpNormal, (&d_TmpNormal), d_pInpPosition)
  279. d_margin($1) d_LightingFlags |= __LIGHT_NORMALTRANSFORMED;
  280. d_margin($1) }
  281. d_margin($1) dot = VecDot(d, d_TmpNormal);
  282. d_margin($1)}')dnl
  283. d_margin($1)if (!(light->flags & D3DLIGHTI_AMBIENT_IS_ZERO) || FLOAT_GTZ(dot))
  284. d_margin($1){
  285. d_margin($1) dist = SQRTF(dist2);
  286. d_margin($1) att = light->attenuation0 +
  287. d_margin($1) light->attenuation1 * dist +
  288. d_margin($1) light->attenuation2 * dist2;
  289. d_margin($1) if (!FLOAT_EQZ(att))
  290. d_margin($1) att = (D3DVALUE)1.0/att;
  291. d_margin($1) else
  292. d_margin($1) att = (D3DVALUE)FLT_MAX;
  293. d_margin($1) dist = D3DVAL(1)/dist;
  294. d_margin($1) if (light->type == D3DLIGHT_SPOT)
  295. d_margin($1) {
  296. d_margin($1) D3DVALUE cone_dot;
  297. d_margin($1) // Calc dot product of direction to light with light direction to
  298. d_margin($1) // be compared anganst the cone angles to see if we are in the light.
  299. d_margin($1) // Note that cone_dot is still scaled by dist
  300. d_margin($1) cone_dot = VecDot(d, light->model_direction)*dist;
  301. d_margin($1) if (FLOAT_CMP_POS(cone_dot, <=, light->cos_phi_by_2))
  302. d_margin($1) goto l_exit;
  303. d_margin($1) // modify att if in the region between phi and theta
  304. d_margin($1) if (FLOAT_CMP_POS(cone_dot, <, light->cos_theta_by_2))
  305. d_margin($1) {
  306. d_margin($1) D3DVALUE val;
  307. d_margin($1) val = (cone_dot - light->cos_phi_by_2) * light->inv_theta_minus_phi;
  308. d_margin($1) if (!(light->flags & D3DLIGHTI_LINEAR_FALLOFF))
  309. d_margin($1) {
  310. d_margin($1) val = POWF(val, light->falloff);
  311. d_margin($1) }
  312. d_margin($1) att *= val;
  313. d_margin($1) }
  314. d_margin($1) }
  315. d_margin($1) d_UpdateAmbientColor($1+1,* att)
  316. d_margin($1) if (FLOAT_LEZ(dot))
  317. d_margin($1) goto l_exit;
  318. d_margin($1) dot *= dist*att;
  319. ifelse(d_Op,+=,`dnl
  320. d_margin($1) d_UpdateDiffuseColor($1+1,+=)',`
  321. d_margin($1) if (!(d_LightingFlags & __LIGHT_DIFFUSECOMPUTED))
  322. d_margin($1) {
  323. d_margin($1) d_UpdateDiffuseColor($1+2, d_Op)
  324. d_margin($1) }
  325. d_margin($1) else
  326. d_margin($1) {
  327. d_margin($1) d_UpdateDiffuseColor($1+2,+=)
  328. d_margin($1) }')
  329. d_margin($1) if (light->flags & D3DLIGHTI_COMPUTE_SPECULAR)
  330. d_margin($1) {
  331. d_margin($1) D3DVECTOR eye;
  332. d_margin($1) D3DVECTOR h;
  333. d_margin($1) // normalize light direction
  334. d_margin($1) d.x *= dist;
  335. d_margin($1) d.y *= dist;
  336. d_margin($1) d.z *= dist;
  337. d_margin($1) // calc vector from vertex to the camera
  338. dnl
  339. ifelse(d_Space,modelSpace,`dnl
  340. dnl
  341. d_margin($1) if (pv->dwDeviceFlags & D3DDEV_LOCALVIEWER)
  342. d_margin($1) {
  343. d_margin($1) VecSub(pv->lighting.model_eye, (*(D3DVECTOR*)d_pInpPosition), eye);
  344. d_margin($1) VecNormalizeFast(eye);
  345. d_margin($1) VecAdd(d, eye, h); // halfway vector
  346. d_margin($1) }
  347. d_margin($1) else
  348. d_margin($1) {
  349. d_margin($1) VecAdd(d, pv->lighting.directionToCamera, h);
  350. d_margin($1) }
  351. d_margin($1) VecNormalizeFast(h);
  352. d_margin($1) dot = VecDot(h, *d_pInpNormal);',`dnl
  353. dnl
  354. dnl// else
  355. dnl
  356. d_margin($1) if (pv->dwDeviceFlags & D3DDEV_LOCALVIEWER)
  357. d_margin($1) {
  358. d_margin($1) VecSub(pv->lighting.model_eye, d_TmpPosition, eye);
  359. d_margin($1) VecNormalizeFast(eye);
  360. d_margin($1) VecAdd(d, eye, h); // halfway vector
  361. d_margin($1) }
  362. d_margin($1) else
  363. d_margin($1) {
  364. d_margin($1) h.x = d.x;
  365. d_margin($1) h.y = d.y;
  366. d_margin($1) h.z = d.z - 1.0f;
  367. d_margin($1) }
  368. d_margin($1) VecNormalizeFast(h);
  369. d_margin($1) dot = VecDot(h, d_TmpNormal);')dnl
  370. dnl
  371. dnl// endif
  372. d_margin($1) d_ComputeSpecular($1+2,att)
  373. d_margin($1) }
  374. d_margin($1)l_exit:;
  375. d_margin($1)}')dnl
  376. dnl//------------------------------------------------------------------
  377. dnl// d_LightVertices
  378. dnl//
  379. dnl// Generate code to light vertices in a small batch using directional or
  380. dnl// parallel point light.
  381. dnl// Handles strided and non-strided cases
  382. dnl//
  383. dnl// Arguments:
  384. dnl// $1 - function name
  385. dnl// $2 - Light type: d_Directional7 or d_PointSpot7
  386. dnl//
  387. define(`d_LightVertices',`dnl
  388. //---------------------------------------------------------------------
  389. void $1(LPD3DFE_PROCESSVERTICES pv,
  390. DWORD dwVerCount,
  391. BATCHBUFFER *pBatchBuffer,
  392. D3DI_LIGHT *light,
  393. D3DVERTEX *pCoord,
  394. D3DVECTOR *pNormal,
  395. DWORD *pDiffuse,
  396. DWORD *pSpecular)
  397. {
  398. // Setup vertex data pointers
  399. DWORD dwPositionStride = pv->position.dwStride;
  400. DWORD dwNormalStride;
  401. DWORD dwDiffuseStride;
  402. DWORD dwSpecularStride;
  403. DWORD dwFlags = pv->dwFlags;
  404. DWORD *pColor[2];
  405. pColor[0] = pDiffuse;
  406. pColor[1] = pSpecular;
  407. DWORD **ppEmissiveSource = &pColor[pv->lighting.dwEmissiveSrcIndex];
  408. DWORD **ppAmbientSource = &pColor[pv->lighting.dwAmbientSrcIndex];
  409. DWORD **ppSpecularSource = &pColor[pv->lighting.dwSpecularSrcIndex];
  410. DWORD **ppDiffuseSource = &pColor[pv->lighting.dwDiffuseSrcIndex];
  411. dwPositionStride = pv->position.dwStride;
  412. if (pv->dwDeviceFlags & D3DDEV_STRIDE)
  413. {
  414. dwNormalStride = pv->normal.dwStride;
  415. dwDiffuseStride = pv->diffuse.dwStride;
  416. dwSpecularStride = pv->specular.dwStride;
  417. }
  418. else
  419. {
  420. dwNormalStride = dwPositionStride;
  421. dwDiffuseStride = dwPositionStride;
  422. dwSpecularStride = dwPositionStride;
  423. }
  424. for (DWORD i = dwVerCount; i; i--)
  425. {
  426. $2(2)
  427. NEXT(pCoord, dwPositionStride, D3DVERTEX);
  428. NEXT(pNormal, dwNormalStride, D3DVECTOR);
  429. if (dwFlags & D3DPV_DOCOLORVERTEX)
  430. {
  431. NEXT(pColor[0], dwDiffuseStride, DWORD);
  432. NEXT(pColor[1], dwSpecularStride, DWORD);
  433. }
  434. pBatchBuffer++;
  435. }
  436. }') dnl
  437. //--------------------------------------------------------------------------
  438. // This batch buffer used to hold temporary vertex data for every small loop
  439. //
  440. const DWORD BATCH_SIZE = 10; // Number of vertices in the batch
  441. struct BATCHBUFFER
  442. {
  443. D3DVALUE sx,sy,sz,rhw; // Screen coordinates
  444. D3DFE_COLOR diffuse;
  445. D3DFE_COLOR specular;
  446. D3DVECTOR position; // Vertex position in the camera space
  447. D3DVECTOR normal; // Vertex normal in the camera space
  448. DWORD dwFlags; // 8 low bits are the same as lighting
  449. // flags from D3DFE
  450. };
  451. dnl//======================================================================
  452. dnl// Generate light functions for batch processing
  453. dnl//
  454. dnl
  455. define(`d_LightingFlags',pBatchBuffer->dwFlags)dnl
  456. define(`d_pInpAmbient',*ppAmbientSource)dnl
  457. define(`d_pInpDiffuse',*ppDiffuseSource)dnl
  458. define(`d_pInpSpecular',*ppSpecularSource)dnl
  459. define(`d_OutDiffuse',pBatchBuffer->diffuse)dnl
  460. define(`d_OutSpecular',pBatchBuffer->specular)dnl
  461. define(`d_pInpPosition',`pCoord')dnl
  462. define(`d_TmpPosition',`'pBatchBuffer->position)dnl
  463. define(`d_pInpNormal',`pNormal')dnl
  464. define(`d_TmpNormal',`pBatchBuffer->normal')dnl
  465. dnl
  466. define(`d_Op',=)dnl
  467. define(`d_Space',cameraSpace)dnl
  468. d_LightVertices(DirectionalFirst,`d_Directional7')
  469. d_LightVertices(PointSpotFirst,`d_PointSpot7')
  470. dnl
  471. define(`d_Space',modelSpace)dnl
  472. d_LightVertices(DirectionalFirstModel,`d_Directional7')
  473. d_LightVertices(PointSpotFirstModel,`d_PointSpot7')
  474. dnl
  475. define(`d_Op',+=)dnl
  476. dnl
  477. define(`d_Space',cameraSpace)dnl
  478. d_LightVertices(DirectionalNext,`d_Directional7')
  479. d_LightVertices(PointSpotNext,`d_PointSpot7')
  480. dnl
  481. define(`d_Space',modelSpace)dnl
  482. d_LightVertices(DirectionalNextModel,`d_Directional7')
  483. d_LightVertices(PointSpotNextModel,`d_PointSpot7')
  484. dnl//======================================================================
  485. dnl// Generate light functions for one vertex processing
  486. //-------------------------------------------------------------------------
  487. // Directional light, computed in the camera space
  488. //
  489. define(`d_LightingFlags',pv->lighting.dwLightingFlags)dnl
  490. define(`d_pInpAmbient',(&pv->lighting.vertexAmbient))dnl
  491. define(`d_pInpDiffuse',(&pv->lighting.vertexDiffuse))dnl
  492. define(`d_pInpSpecular',(&pv->lighting.vertexSpecular))dnl
  493. define(`d_OutDiffuse',pv->lighting.diffuse)dnl
  494. define(`d_OutSpecular',pv->lighting.specular)dnl
  495. define(`d_pInpPosition',`(pInpCoord)')dnl
  496. define(`d_TmpPosition',`'*(D3DVERTEX*)pEyeSpaceData)dnl
  497. define(`d_pInpNormal',`(pInpNormal)')dnl
  498. define(`d_TmpNormal',`pEyeSpaceData->dvNormal')dnl
  499. define(`d_Space',cameraSpace)dnl
  500. dnl
  501. void Directional7(LPD3DFE_PROCESSVERTICES pv,
  502. D3DI_LIGHT *light,
  503. D3DVERTEX *pInpCoord,
  504. D3DVECTOR *pInpNormal,
  505. D3DLIGHTINGELEMENT *pEyeSpaceData)
  506. {
  507. DWORD dwFlags = pv->dwFlags;
  508. d_Directional7(1)
  509. }
  510. //---------------------------------------------------------------------
  511. // Directional light, computed in the model space
  512. //
  513. define(`d_Space',modelSpace)dnl
  514. dnl
  515. void Directional7Model(LPD3DFE_PROCESSVERTICES pv,
  516. D3DI_LIGHT *light,
  517. D3DVERTEX *pInpCoord,
  518. D3DVECTOR *pInpNormal,
  519. D3DLIGHTINGELEMENT *pEyeSpaceData)
  520. {
  521. DWORD dwFlags = pv->dwFlags;
  522. d_Directional7(1)
  523. }
  524. //---------------------------------------------------------------------
  525. // Point-spot light, computed in the camera space
  526. //
  527. define(`d_Space',cameraSpace)dnl
  528. void PointSpot7(LPD3DFE_PROCESSVERTICES pv,
  529. D3DI_LIGHT *light,
  530. D3DVERTEX *pInpCoord,
  531. D3DVECTOR *pInpNormal,
  532. D3DLIGHTINGELEMENT *pEyeSpaceData)
  533. {
  534. DWORD dwFlags = pv->dwFlags;
  535. d_PointSpot7(1)
  536. }
  537. //---------------------------------------------------------------------
  538. // Point-spot light, computed in the model space
  539. //
  540. define(`d_Space',modelSpace)dnl
  541. void PointSpot7Model(LPD3DFE_PROCESSVERTICES pv,
  542. D3DI_LIGHT *light,
  543. D3DVERTEX *pInpCoord,
  544. D3DVECTOR *pInpNormal,
  545. D3DLIGHTINGELEMENT *pEyeSpaceData)
  546. {
  547. DWORD dwFlags = pv->dwFlags;
  548. d_PointSpot7(1)
  549. }
  550. //--------------------------------------------------------------------------
  551. // Prototype to transform vertices in batches
  552. //
  553. typedef DWORD (*PFN_TRANSFORMLOOP)(LPD3DFE_PROCESSVERTICES pv,
  554. DWORD dwVerCount,
  555. D3DVERTEX *in,
  556. D3DTLVERTEX **ppOut,
  557. D3DFE_CLIPCODE **ppClipCodes);
  558. //---------------------------------------------------------------------
  559. // Transform vertices in a batch with clipping
  560. //
  561. // Arguments:
  562. // dwVerCount - number of vertices in the batch
  563. // in - pointer to the input coordinates
  564. // ppOut - pointer to the output vertices
  565. // ppClipVodes - pointer to the clip code buffer
  566. // Returns:
  567. // Number of processed vertices
  568. // Notes:
  569. // ppOut and ppClipCodes will be set to the next vertex after the batch
  570. //
  571. DWORD TransformClip(LPD3DFE_PROCESSVERTICES pv,
  572. DWORD dwVerCount,
  573. D3DVERTEX *in,
  574. D3DTLVERTEX **ppOut,
  575. D3DFE_CLIPCODE **ppClipCodes)
  576. {
  577. float x, y, z, w;
  578. D3DMATRIX *m = (D3DMATRIX*)&pv->mCTM;
  579. DWORD dwInpVerSize = pv->position.dwStride;
  580. DWORD dwOutVerSize = pv->dwOutputSize;
  581. D3DFE_CLIPCODE *pClipCodes = *ppClipCodes;
  582. D3DTLVERTEX *out = *ppOut;
  583. DWORD dwDeviceFlags = pv->dwDeviceFlags;
  584. for (DWORD i = dwVerCount; i; i--)
  585. {
  586. // Transform vertex to the clipping space
  587. d_TransformVertex(2, in, m, x, y, z, w)
  588. DWORD clip;
  589. // Compute clip code
  590. d_ComputeClipCode(4)
  591. if (clip == 0)
  592. {
  593. pv->dwClipIntersection = 0;
  594. *pClipCodes++ = 0;
  595. w = D3DVAL(1)/w;
  596. }
  597. else
  598. {
  599. if (dwDeviceFlags & D3DDEV_GUARDBAND)
  600. {
  601. // We do guardband check in the projection space, so
  602. // we transform X and Y of the vertex there
  603. d_ComputeClipCodeGB(5)
  604. if ((clip & ~__D3DCLIP_INGUARDBAND) == 0)
  605. {
  606. // If vertex is inside the guardband we have to compute
  607. // screen coordinates
  608. w = D3DVAL(1)/w;
  609. *pClipCodes++ = (D3DFE_CLIPCODE)clip;
  610. pv->dwClipIntersection &= clip;
  611. pv->dwClipUnion |= clip;
  612. goto l_DoScreenCoord;
  613. }
  614. }
  615. if (pv->dwFlags & D3DPV_ONEPASSCLIPPING)
  616. {
  617. return dwVerCount - i;
  618. }
  619. pv->dwClipIntersection &= clip;
  620. pv->dwClipUnion |= clip;
  621. *pClipCodes++ = (D3DFE_CLIPCODE)clip;
  622. // If vertex is outside the frustum we can not compute screen
  623. // coordinates
  624. out->sx = x;
  625. out->sy = y;
  626. out->sz = z;
  627. out->rhw = w;
  628. goto l_Continue;
  629. }
  630. l_DoScreenCoord:
  631. d_ComputeScreenCoordinates(2, x, y, z, w, out)
  632. l_Continue:
  633. NEXT(in, dwInpVerSize, D3DVERTEX);
  634. NEXT(out, dwOutVerSize, D3DTLVERTEX);
  635. }
  636. *ppClipCodes = pClipCodes;
  637. *ppOut = out;
  638. return dwVerCount;
  639. }
  640. //---------------------------------------------------------------------
  641. // Transform vertices in a batch without clipping
  642. //
  643. // Arguments:
  644. // dwVerCount - number of vertices in the batch
  645. // in - pointer to the input coordinates
  646. // ppOut - pointer to the output vertices
  647. // ppClipVodes - pointer to the clip code buffer
  648. // Returns:
  649. // Number of processed vertices
  650. // Notes:
  651. // ppOut and ppClipCodes will be set to the next vertex after the batch
  652. //
  653. DWORD TransformNoClip(LPD3DFE_PROCESSVERTICES pv,
  654. DWORD dwVerCount,
  655. D3DVERTEX *in,
  656. D3DTLVERTEX **ppOut,
  657. D3DFE_CLIPCODE **pClipCodes)
  658. {
  659. float x, y, z, w;
  660. D3DMATRIX *m = (D3DMATRIX*)&pv->mCTM;
  661. DWORD dwInpVerSize = pv->position.dwStride;
  662. DWORD dwOutVerSize = pv->dwOutputSize;
  663. D3DTLVERTEX *out = *ppOut;
  664. for (DWORD i = dwVerCount; i; i--)
  665. {
  666. // Transform vertex to the clipping space
  667. d_TransformVertex(2, in, m, x, y, z, w)
  668. // We have to check this only for DONOTCLIP case, because otherwise
  669. // the vertex with "we = 0" will be clipped and screen coordinates
  670. // will not be computed
  671. // "clip" is not zero, if "w" is zero.
  672. if (!FLOAT_EQZ(w))
  673. w = D3DVAL(1)/w;
  674. else
  675. w = __HUGE_PWR2;
  676. d_ComputeScreenCoordinates(2, x, y, z, w, out)
  677. NEXT(in, dwInpVerSize, D3DVERTEX);
  678. NEXT(out, dwOutVerSize, D3DTLVERTEX);
  679. }
  680. *ppOut = out;
  681. return dwVerCount;
  682. }
  683. //---------------------------------------------------------------------
  684. // Transforms, lights vertices, computes clip codes
  685. // Processing is done in small batches (BATCH_SIZE).
  686. //
  687. // The following fields from pv are used:
  688. // dwFlags
  689. // dwNumVertices
  690. // all pointer and strides
  691. // position.lpvStrides
  692. // dwVIDIn
  693. // dwVIDOut
  694. // lpvOut
  695. // lpClipFlags
  696. // nTexCoord
  697. // Returns:
  698. // returns dwClipIntersection or 0 (if D3DDEV_DONOTCLIP is set)
  699. // Side effects:
  700. // dwClipUnion, dwClipIntersection are set only if D3DDEV_DONOTCLIP is not set
  701. // rExtents is updated if D3DDEV_DONOTUPDATEEXTENTS is not set
  702. //
  703. #undef DPF_MODNAME
  704. #define DPF_MODNAME "ProcessVerticesLoops"
  705. DWORD ProcessVerticesLoop(LPD3DFE_PROCESSVERTICES pv)
  706. {
  707. D3DFE_CLIPCODE *hout = pv->lpClipFlags;
  708. D3DTLVERTEX *out = (D3DTLVERTEX*)pv->lpvOut;
  709. D3DMATRIXI *m = &pv->mCTM;
  710. DWORD dwNumVertices = pv->dwNumVertices;
  711. D3DVALUE *pOutTexture = (D3DVALUE*)((char*)out + pv->texOffsetOut);
  712. DWORD *pOutDiffuse = (DWORD*)((char*)out + pv->diffuseOffsetOut);
  713. DWORD *pOutSpecular = (DWORD*)((char*)out + pv->specularOffsetOut);
  714. DWORD dwNormalStrideBatch;
  715. DWORD dwNormalStride;
  716. DWORD dwDiffuseStride;
  717. DWORD dwSpecularStride;
  718. DWORD dwTextureStride[D3DDP_MAXTEXCOORD];
  719. DWORD dwNumTexCoord = pv->nOutTexCoord;
  720. DWORD *pOutFogFactor = pOutSpecular;
  721. PFN_TRANSFORMLOOP pfnTransform;
  722. d_Setup()
  723. if (pv->dwFlags & D3DPV_DONOTCOPYTEXTURE)
  724. dwNumTexCoord = 0;
  725. BATCHBUFFER batchBuffer[BATCH_SIZE];
  726. DWORD dwInpVerSizeBatch = dwInpVerSize * BATCH_SIZE;
  727. DWORD dwOutVerSizeBatch = dwOutVerSize * BATCH_SIZE;
  728. if (pv->dwDeviceFlags & D3DDEV_STRIDE)
  729. {
  730. dwNormalStrideBatch = pv->normal.dwStride * BATCH_SIZE;
  731. dwNormalStride = pv->normal.dwStride;
  732. dwDiffuseStride = pv->diffuse.dwStride;
  733. dwSpecularStride = pv->specular.dwStride;
  734. for (DWORD i=0; i < pv->nTexCoord; i++)
  735. dwTextureStride[i] = pv->textures[i].dwStride;
  736. }
  737. else
  738. {
  739. dwNormalStride = dwInpVerSize;
  740. dwDiffuseStride = dwInpVerSize;
  741. dwSpecularStride = dwInpVerSize;
  742. dwNormalStrideBatch = dwInpVerSizeBatch;
  743. }
  744. if (!(dwDeviceFlags & D3DDEV_DONOTCLIP))
  745. {
  746. pfnTransform = TransformClip;
  747. pv->dwClipIntersection = ~0;
  748. pv->dwClipUnion = 0;
  749. }
  750. else
  751. {
  752. pfnTransform = TransformNoClip;
  753. pv->dwClipIntersection = 0;
  754. pv->dwClipUnion = 0;
  755. }
  756. do
  757. {
  758. DWORD count1 = min(dwNumVertices, BATCH_SIZE);
  759. DWORD count = (*pfnTransform)(pv, count1, (D3DVERTEX*)in, &out, &hout);
  760. if (pv->dwFlags & (D3DPV_FOG | D3DPV_LIGHTING) ||
  761. pv->dwDeviceFlags & (D3DDEV_POSITIONINCAMERASPACE | D3DDEV_NORMALINCAMERASPACE))
  762. {
  763. memset(batchBuffer, 0, sizeof(batchBuffer));
  764. }
  765. // Compute camera space position if needed
  766. if (pv->dwDeviceFlags & (D3DDEV_POSITIONINCAMERASPACE | D3DDEV_NORMALINCAMERASPACE))
  767. {
  768. BATCHBUFFER *buf = batchBuffer;
  769. D3DVECTOR *pVertex = in;
  770. D3DVECTOR *pNormal = inNormal;
  771. for (DWORD i=count; i; i--)
  772. {
  773. if (pv->dwDeviceFlags & D3DDEV_POSITIONINCAMERASPACE)
  774. {
  775. d_TransformVertexToCameraSpace(5, pVertex, ((D3DVERTEX*)&buf->position))
  776. buf->dwFlags |= __LIGHT_VERTEXTRANSFORMED;
  777. }
  778. if (pv->dwDeviceFlags & D3DDEV_NORMALINCAMERASPACE)
  779. {
  780. d_TransformNormalToCameraSpace(5, pNormal, ((D3DVERTEX*)&buf->normal), pVertex)
  781. buf->dwFlags |= __LIGHT_NORMALTRANSFORMED;
  782. NEXT(pNormal, dwNormalStride, D3DVECTOR);
  783. }
  784. NEXT(pVertex, pv->position.dwStride, D3DVECTOR);
  785. buf++;
  786. }
  787. }
  788. if (pv->dwFlags & D3DPV_LIGHTING)
  789. {
  790. // Light vertices. Output goes to the batch buffer
  791. D3DI_LIGHT *light = pv->lighting.activeLights;
  792. if (light)
  793. {
  794. light->pfnLightFirst(pv, count, batchBuffer, light, (D3DVERTEX*)in,
  795. inNormal, inDiffuse, inSpecular);
  796. while(light = light->next)
  797. {
  798. light->pfnLightNext(pv, count, batchBuffer, light, (D3DVERTEX*)in,
  799. inNormal, inDiffuse, inSpecular);
  800. }
  801. }
  802. // Copy vertices from the batch buffer to the output
  803. BATCHBUFFER *buf = batchBuffer;
  804. dnl
  805. define(`d_OutDiffuse',buf->diffuse)dnl
  806. define(`d_OutSpecular',buf->specular)dnl
  807. define(`d_dwOutSpecular',*pOutSpecular)dnl
  808. define(`d_dwOutDiffuse',*pOutDiffuse)dnl
  809. define(`d_LightingFlags',buf->dwFlags)dnl
  810. dnl
  811. if (pv->dwFlags & D3DPV_DOCOLORVERTEX)
  812. {
  813. for (DWORD i = count; i; i--)
  814. {
  815. d_MakeOutputColors(5)
  816. buf++;
  817. NEXT(pOutSpecular, dwOutVerSize, DWORD);
  818. NEXT(pOutDiffuse, dwOutVerSize, DWORD);
  819. NEXT(inDiffuse, dwDiffuseStride, DWORD);
  820. NEXT(inSpecular, dwSpecularStride, DWORD);
  821. }
  822. }
  823. else
  824. {
  825. for (DWORD i = count; i; i--)
  826. {
  827. d_MakeOutputColorsNoColorVertex(5)
  828. buf++;
  829. NEXT(pOutSpecular, dwOutVerSize, DWORD);
  830. NEXT(pOutDiffuse, dwOutVerSize, DWORD);
  831. NEXT(inDiffuse, dwDiffuseStride, DWORD);
  832. NEXT(inSpecular, dwSpecularStride, DWORD);
  833. }
  834. }
  835. }
  836. else
  837. {
  838. // If there is no lighting, we have to copy vertex color or
  839. // default color to the output
  840. if (!(pv->dwFlags & D3DPV_DONOTCOPYDIFFUSE))
  841. {
  842. if (pv->dwVIDIn & D3DFVF_DIFFUSE)
  843. {
  844. for (DWORD i = count; i; i--)
  845. {
  846. *pOutDiffuse = *inDiffuse;
  847. NEXT(pOutDiffuse, dwOutVerSize, DWORD);
  848. NEXT(inDiffuse, dwDiffuseStride, DWORD);
  849. }
  850. }
  851. else
  852. {
  853. for (DWORD i = count; i; i--)
  854. {
  855. *pOutDiffuse = __DEFAULT_DIFFUSE;
  856. NEXT(pOutDiffuse, dwOutVerSize, DWORD);
  857. }
  858. }
  859. }
  860. if (!(pv->dwFlags & D3DPV_DONOTCOPYSPECULAR))
  861. {
  862. if (pv->dwVIDIn & D3DFVF_SPECULAR)
  863. {
  864. for (DWORD i = count; i; i--)
  865. {
  866. *pOutSpecular = *inSpecular;
  867. NEXT(pOutSpecular, dwOutVerSize, DWORD);
  868. NEXT(inSpecular, dwSpecularStride, DWORD);
  869. }
  870. }
  871. else
  872. {
  873. for (DWORD i = count; i; i--)
  874. {
  875. *pOutSpecular = __DEFAULT_SPECULAR;
  876. NEXT(pOutSpecular, dwOutVerSize, DWORD);
  877. }
  878. }
  879. }
  880. }
  881. if (pv->dwFlags & D3DPV_FOG)
  882. {
  883. BATCHBUFFER *buf = batchBuffer;
  884. D3DVECTOR *pVertex = in;
  885. for (DWORD i = count; i; i--)
  886. {
  887. D3DVALUE dist;
  888. if (buf->dwFlags & __LIGHT_VERTEXTRANSFORMED)
  889. {
  890. // Vertex is already transformed to the camera space
  891. if (dwDeviceFlags & D3DDEV_RANGEBASEDFOG)
  892. dist = SQRTF(buf->position.x*buf->position.x +
  893. buf->position.y*buf->position.y +
  894. buf->position.z*buf->position.z);
  895. else
  896. dist = buf->position.z;
  897. }
  898. else
  899. if (dwDeviceFlags & D3DDEV_RANGEBASEDFOG)
  900. {
  901. D3DVECTOR veye;
  902. d_TransformVertexToCameraSpace(5, pVertex, (&veye));
  903. dist = SQRTF(veye.x*veye.x + veye.y*veye.y + veye.z*veye.z);
  904. }
  905. else
  906. {
  907. if (pv->dwNumVerBlends == 0)
  908. {
  909. dist = pVertex->x*pv->mWV._13 + pVertex->y*pv->mWV._23 +
  910. pVertex->z*pv->mWV._33 + pv->mWV._43;
  911. }
  912. else
  913. {
  914. D3DVECTOR veye;
  915. d_TransformVertexToCameraSpace(6, pVertex, (&veye));
  916. dist = veye.z;
  917. }
  918. }
  919. ComputeFogFactor(pv, dist, pOutFogFactor);
  920. NEXT(pVertex, pv->position.dwStride, D3DVECTOR);
  921. NEXT(pOutFogFactor, dwOutVerSize, DWORD);
  922. buf++;
  923. }
  924. }
  925. // Process texture coordinates
  926. if (dwNumTexCoord != 0)
  927. {
  928. if (dwDeviceFlags & D3DDEV_NOFVFANDNOTEXTURE)
  929. {
  930. for (DWORD i = count; i; i--)
  931. {
  932. pOutTexture[0] = 0;
  933. pOutTexture[1] = 0;
  934. NEXT(pOutTexture, dwOutVerSize, D3DVALUE);
  935. }
  936. }
  937. else
  938. if (pv->dwDeviceFlags & D3DDEV_STRIDE)
  939. {
  940. if (!(pv->dwDeviceFlags & (D3DDEV_TEXTURETRANSFORM | D3DDEV_REMAPTEXTUREINDICES)))
  941. {
  942. for (DWORD i=count; i; i--)
  943. {
  944. D3DVALUE *pTexture = pOutTexture;
  945. for (DWORD k=0; k < dwNumTexCoord; k++)
  946. {
  947. const DWORD dwSize = pv->dwTextureCoordSize[k];
  948. memcpy(pTexture, inTexture[k], dwSize);
  949. pTexture = (D3DVALUE*)((char*)pTexture + dwSize);
  950. NEXT(inTexture[k], dwTextureStride[k], D3DVALUE);
  951. }
  952. NEXT(pOutTexture, dwOutVerSize, D3DVALUE);
  953. }
  954. }
  955. else
  956. {
  957. if (!(pv->dwDeviceFlags & D3DDEV_REMAPTEXTUREINDICES))
  958. {
  959. D3DVALUE *pOut = pOutTexture;
  960. for (DWORD k=0; k < dwNumTexCoord; k++)
  961. {
  962. const DWORD dwSize = pv->dwTextureCoordSize[k];
  963. const DWORD dwInpSize = pv->dwInpTextureCoordSize[k];
  964. const DWORD dwStride = dwTextureStride[k];
  965. D3DVALUE *pInpTexture = inTexture[k];
  966. if (pv->pmTexture[k] == NULL)
  967. {
  968. D3DVALUE *pOutTmp = pOut;
  969. for (DWORD i=count; i; i--)
  970. {
  971. memcpy(pOutTmp, pInpTexture, dwSize);
  972. NEXT(pInpTexture, dwStride, D3DVALUE);
  973. NEXT(pOutTmp, dwOutVerSize, D3DVALUE);
  974. }
  975. }
  976. else
  977. {
  978. const DWORD n = dwSize >> 2; // Number of input tex. coord.
  979. const DWORD m = dwInpSize >> 2; // Number of input tex. coord.
  980. (*(g_pfnTextureTransformLoop[MakeTexTransformFuncIndex(m, n)]))
  981. (pInpTexture, pOut, pv->pmTexture[k], count,
  982. dwStride, dwOutVerSize);
  983. }
  984. NEXT(pOut, dwSize, D3DVALUE);
  985. NEXT(inTexture[k], dwStride*BATCH_SIZE, D3DVALUE);
  986. }
  987. NEXT(pOutTexture, dwOutVerSizeBatch, D3DVALUE);
  988. }
  989. else
  990. {
  991. D3DVALUE *pOut = pOutTexture;
  992. for (DWORD k=0; k < pv->dwNumTextureStages; k++)
  993. {
  994. const LPD3DFE_TEXTURESTAGE pStage = &pv->textureStage[k];
  995. const DWORD dwOutTexSize = pv->dwTextureCoordSize[k];
  996. DWORD dwStride;
  997. D3DVALUE *pIn;
  998. D3DVECTOR reflectionVector[BATCH_SIZE];
  999. if (pStage->dwTexGenMode == 0)
  1000. {
  1001. const DWORD dwInpIndex = pStage->dwInpCoordIndex;
  1002. pIn = inTexture[dwInpIndex];
  1003. dwStride = dwTextureStride[dwInpIndex];
  1004. }
  1005. else
  1006. if (pStage->dwTexGenMode == D3DTSS_TCI_CAMERASPACEPOSITION)
  1007. {
  1008. pIn = (D3DVALUE*)&batchBuffer[0].position;
  1009. dwStride = sizeof(BATCHBUFFER);
  1010. }
  1011. else
  1012. if (pStage->dwTexGenMode == D3DTSS_TCI_CAMERASPACENORMAL)
  1013. {
  1014. pIn = (D3DVALUE*)&batchBuffer[0].normal;
  1015. dwStride = sizeof(BATCHBUFFER);
  1016. }
  1017. else // D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR
  1018. {
  1019. if (pv->dwDeviceFlags & D3DDEV_LOCALVIEWER)
  1020. {
  1021. for (DWORD i=0; i < count; i++)
  1022. {
  1023. ComputeReflectionVector(&batchBuffer[i].position,
  1024. &batchBuffer[i].normal,
  1025. &reflectionVector[i]);
  1026. }
  1027. }
  1028. else
  1029. {
  1030. for (DWORD i=0; i < count; i++)
  1031. {
  1032. ComputeReflectionVectorInfiniteViewer(&batchBuffer[i].normal,
  1033. &reflectionVector[i]);
  1034. }
  1035. }
  1036. pIn = (D3DVALUE*)reflectionVector;
  1037. dwStride = sizeof(D3DVECTOR);
  1038. }
  1039. if (pStage->pmTextureTransform == NULL)
  1040. {
  1041. D3DVALUE *pOutTmp = pOut;
  1042. for (DWORD i=count; i; i--)
  1043. {
  1044. memcpy(pOutTmp, pIn, dwOutTexSize);
  1045. NEXT(pIn, dwStride, D3DVALUE);
  1046. NEXT(pOutTmp, dwOutVerSize, D3DVALUE);
  1047. }
  1048. }
  1049. else
  1050. {
  1051. (*(g_pfnTextureTransformLoop[pStage->dwTexTransformFuncIndex]))
  1052. (pIn, pOut, pStage->pmTextureTransform, count,
  1053. dwStride, dwOutVerSize);
  1054. }
  1055. NEXT(pOut, dwOutTexSize, D3DVALUE);
  1056. }
  1057. NEXT(pOutTexture, dwOutVerSizeBatch, D3DVALUE);
  1058. for (DWORD m=0; m < pv->nTexCoord; m++)
  1059. {
  1060. NEXT(inTexture[m], dwTextureStride[m]*BATCH_SIZE, D3DVALUE);
  1061. }
  1062. }
  1063. }
  1064. }
  1065. else
  1066. {
  1067. if (!(pv->dwDeviceFlags & (D3DDEV_TEXTURETRANSFORM | D3DDEV_REMAPTEXTUREINDICES)))
  1068. {
  1069. for (DWORD i=count; i; i--)
  1070. {
  1071. memcpy(pOutTexture, inTexture[0], pv->dwTextureCoordSizeTotal);
  1072. NEXT(pOutTexture, dwOutVerSize, D3DVALUE);
  1073. NEXT(inTexture[0], dwInpVerSize, D3DVALUE);
  1074. }
  1075. }
  1076. else
  1077. if (!(pv->dwDeviceFlags & D3DDEV_REMAPTEXTUREINDICES))
  1078. {
  1079. D3DVALUE *pIn = inTexture[0];
  1080. D3DVALUE *pOut = pOutTexture;
  1081. for (DWORD k=0; k < dwNumTexCoord; k++)
  1082. {
  1083. const DWORD dwSize = pv->dwTextureCoordSize[k];
  1084. const DWORD dwInpSize = pv->dwInpTextureCoordSize[k];
  1085. if (pv->pmTexture[k] == NULL)
  1086. {
  1087. D3DVALUE *pOutTmp = pOut;
  1088. D3DVALUE *pInpTmp = pIn;
  1089. for (DWORD i=count; i; i--)
  1090. {
  1091. memcpy(pOutTmp, pInpTmp, dwSize);
  1092. NEXT(pInpTmp, dwInpVerSize, D3DVALUE);
  1093. NEXT(pOutTmp, dwOutVerSize, D3DVALUE);
  1094. }
  1095. }
  1096. else
  1097. {
  1098. const DWORD n = dwSize >> 2; // Number of output tex. coord.
  1099. const DWORD m = dwInpSize >> 2; // Number of input tex. coord.
  1100. (*(g_pfnTextureTransformLoop[MakeTexTransformFuncIndex(m, n)]))
  1101. (pIn, pOut, pv->pmTexture[k], count, dwInpVerSize, dwOutVerSize);
  1102. }
  1103. NEXT(pIn, dwInpSize, D3DVALUE);
  1104. NEXT(pOut, dwSize, D3DVALUE);
  1105. }
  1106. NEXT(inTexture[0], dwInpVerSizeBatch, D3DVALUE);
  1107. NEXT(pOutTexture, dwOutVerSizeBatch, D3DVALUE);
  1108. }
  1109. else
  1110. {
  1111. D3DVALUE *pOut = pOutTexture;
  1112. for (DWORD i=0; i < pv->dwNumTextureStages; i++)
  1113. {
  1114. LPD3DFE_TEXTURESTAGE pStage = &pv->textureStage[i];
  1115. const DWORD dwSize = pv->dwTextureCoordSize[i];
  1116. D3DVALUE *pIn;
  1117. DWORD dwStride;
  1118. D3DVECTOR reflectionVector[BATCH_SIZE];
  1119. if (pStage->dwTexGenMode == 0)
  1120. {
  1121. pIn = (D3DVALUE*)((BYTE*)inTexture[0] + pStage->dwInpOffset);
  1122. dwStride = dwInpVerSize;
  1123. }
  1124. else
  1125. if (pStage->dwTexGenMode == D3DTSS_TCI_CAMERASPACEPOSITION)
  1126. {
  1127. pIn = (D3DVALUE*)&batchBuffer[0].position;
  1128. dwStride = sizeof(BATCHBUFFER);
  1129. }
  1130. else
  1131. if (pStage->dwTexGenMode == D3DTSS_TCI_CAMERASPACENORMAL)
  1132. {
  1133. pIn = (D3DVALUE*)&batchBuffer[0].normal;
  1134. dwStride = sizeof(BATCHBUFFER);
  1135. }
  1136. else // D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR
  1137. {
  1138. if (pv->dwDeviceFlags & D3DDEV_LOCALVIEWER)
  1139. {
  1140. for (DWORD i=0; i < count; i++)
  1141. {
  1142. ComputeReflectionVector(&batchBuffer[i].position,
  1143. &batchBuffer[i].normal,
  1144. &reflectionVector[i]);
  1145. }
  1146. }
  1147. else
  1148. {
  1149. for (DWORD i=0; i < count; i++)
  1150. {
  1151. ComputeReflectionVectorInfiniteViewer(&batchBuffer[i].normal,
  1152. &reflectionVector[i]);
  1153. }
  1154. }
  1155. pIn = (D3DVALUE*)reflectionVector;
  1156. dwStride = sizeof(D3DVECTOR);
  1157. }
  1158. if (pStage->pmTextureTransform == NULL)
  1159. {
  1160. D3DVALUE *pOutTmp = pOut;
  1161. for (DWORD i=count; i; i--)
  1162. {
  1163. memcpy(pOutTmp, pIn, dwSize);
  1164. NEXT(pIn, dwStride, D3DVALUE);
  1165. NEXT(pOutTmp, dwOutVerSize, D3DVALUE);
  1166. }
  1167. }
  1168. else
  1169. {
  1170. (*(g_pfnTextureTransformLoop[pStage->dwTexTransformFuncIndex]))
  1171. (pIn, pOut, pStage->pmTextureTransform, count, dwStride, dwOutVerSize);
  1172. }
  1173. NEXT(pOut, dwSize, D3DVALUE);
  1174. }
  1175. NEXT(inTexture[0], dwInpVerSizeBatch, D3DVALUE);
  1176. NEXT(pOutTexture, dwOutVerSizeBatch, D3DVALUE);
  1177. }
  1178. }
  1179. }
  1180. if (count != count1)
  1181. {
  1182. pv->dwFirstClippedVertex = pv->dwNumVertices - dwNumVertices + count;
  1183. break;
  1184. }
  1185. NEXT(inNormal, dwNormalStrideBatch, D3DVECTOR);
  1186. NEXT(in, dwInpVerSizeBatch, D3DVECTOR);
  1187. dwNumVertices -= count;
  1188. } while (dwNumVertices);
  1189. d_UpdateExtents()
  1190. return pv->dwClipIntersection;
  1191. }