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.

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