Team Fortress 2 Source Code as on 22/4/2020
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.

1393 lines
35 KiB

  1. ;------------------------------------
  2. ; RULES FOR AUTHORING VERTEX SHADERS:
  3. ;------------------------------------
  4. ; - never use "def" . . .set constants in code instead. . our constant shadowing will break otherwise.
  5. ; (same goes for pixel shaders)
  6. ; - use cN notation instead of c[N] notation. .makes grepping for registers easier.
  7. ; The only exception is c[a0.x+blah] where you have no choice.
  8. $g_NumRegisters = 12;
  9. ; NOTE: These must match the same values in vsh_prep.pl!
  10. $vPos = "v0";
  11. $vBoneWeights = "v1";
  12. $vBoneIndices = "v2";
  13. $vNormal = "v3";
  14. $vColor = "v5";
  15. $vSpecular = "v6";
  16. $vTexCoord0 = "v7";
  17. $vTexCoord1 = "v8";
  18. $vTexCoord2 = "v9";
  19. $vTexCoord3 = "v10";
  20. $vTangentS = "v11";
  21. $vTangentT = "v12";
  22. $vUserData = "v14";
  23. if( $g_dx9 )
  24. {
  25. if( $g_usesPos )
  26. {
  27. dcl_position $vPos;
  28. }
  29. if( $g_usesBoneWeights )
  30. {
  31. dcl_blendweight $vBoneWeights;
  32. }
  33. if( $g_usesBoneIndices )
  34. {
  35. dcl_blendindices $vBoneIndices;
  36. }
  37. if( $g_usesNormal )
  38. {
  39. dcl_normal $vNormal;
  40. }
  41. if( $g_usesColor )
  42. {
  43. dcl_color0 $vColor;
  44. }
  45. if( $g_usesSpecular )
  46. {
  47. dcl_color1 $vSpecular;
  48. }
  49. if( $g_usesTexCoord0 )
  50. {
  51. dcl_texcoord0 $vTexCoord0;
  52. }
  53. if( $g_usesTexCoord1 )
  54. {
  55. dcl_texcoord1 $vTexCoord1;
  56. }
  57. if( $g_usesTexCoord2 )
  58. {
  59. dcl_texcoord2 $vTexCoord2;
  60. }
  61. if( $g_usesTexCoord3 )
  62. {
  63. dcl_texcoord3 $vTexCoord3;
  64. }
  65. if( $g_usesTangentS )
  66. {
  67. dcl_tangent $vTangentS;
  68. }
  69. if( $g_usesTangentT )
  70. {
  71. dcl_binormal0 $vTangentT;
  72. }
  73. if( $g_usesUserData )
  74. {
  75. dcl_tangent $vUserData;
  76. }
  77. }
  78. # NOTE: These should match g_LightCombinations in vertexshaderdx8.cpp!
  79. # NOTE: Leave this on single lines or shit might blow up.
  80. @g_staticLightTypeArray = ( "none", "static", "none", "none", "none", "none", "none", "none", "none", "none", "none", "none", "static", "static", "static", "static", "static", "static", "static", "static", "static", "static" );
  81. @g_ambientLightTypeArray = ( "none", "none", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient", "ambient" );
  82. @g_localLightType1Array = ( "none", "none", "none", "spot", "point", "directional", "spot", "spot", "spot", "point", "point", "directional", "none", "spot", "point", "directional", "spot", "spot", "spot", "point", "point", "directional" );
  83. @g_localLightType2Array = ( "none", "none", "none", "none", "none", "none", "spot", "point", "directional", "point", "directional", "directional", "none", "none", "none", "none", "spot", "point", "directional", "point", "directional", "directional" );
  84. $cConstants0 = "c0";
  85. $cZero = "c0.x";
  86. $cOne = "c0.y";
  87. $cTwo = "c0.z";
  88. $cHalf = "c0.w";
  89. $cConstants1 = "c1";
  90. $cOOGamma = "c1.x"; # 1/2.2
  91. $cOtherOverbrightFactor = "c1.y"; # overbright
  92. $cOneThird = "c1.z"; # 1/3
  93. $cOverbrightFactor = "c1.w"; # 1/overbright
  94. $cEyePos = "c2";
  95. $cWaterZ = "c2.w";
  96. $cEyePosWaterZ = "c2";
  97. $cLightIndex = "c3";
  98. $cLight0Offset = "c3.x"; # 27
  99. $cLight1Offset = "c3.y"; # 32
  100. $cColorToIntScale = "c3.z"; # matrix array offset = 3.0f * 255.0f + 0.01 (epsilon ensures floor yields desired result)
  101. $cModel0Index = "c3.w"; # base for start of skinning matrices
  102. ; NOTE: These must match the same values in vsh_prep.pl!
  103. $cModelViewProj0 = "c4";
  104. $cModelViewProj1 = "c5";
  105. $cModelViewProj2 = "c6";
  106. $cModelViewProj3 = "c7";
  107. $cViewProj0 = "c8";
  108. $cViewProj1 = "c9";
  109. $cViewProj2 = "c10";
  110. $cViewProj3 = "c11";
  111. ; currently unused
  112. ; c12, c13
  113. $SHADER_SPECIFIC_CONST_10 = "c14";
  114. $SHADER_SPECIFIC_CONST_11 = "c15";
  115. $cFogParams = "c16";
  116. $cFogEndOverFogRange = "c16.x";
  117. $cFogOne = "c16.y";
  118. $cFogMaxDensity = "c16.z";
  119. $cOOFogRange = "c16.w"; # (1/(fogEnd-fogStart))
  120. $cViewModel0 = "c17";
  121. $cViewModel1 = "c18";
  122. $cViewModel2 = "c19";
  123. $cViewModel3 = "c20";
  124. $cAmbientColorPosX = "c21";
  125. $cAmbientColorNegX = "c22";
  126. $cAmbientColorPosY = "c23";
  127. $cAmbientColorNegY = "c24";
  128. $cAmbientColorPosZ = "c25";
  129. $cAmbientColorNegZ = "c26";
  130. $cAmbientColorPosXOffset = "21";
  131. $cAmbientColorPosYOffset = "23";
  132. $cAmbientColorPosZOffset = "25";
  133. $cLight0DiffColor = "c27";
  134. $cLight0Dir = "c28";
  135. $cLight0Pos = "c29";
  136. $cLight0SpotParams = "c30"; # [ exponent, stopdot, stopdot2, 1 / (stopdot - stopdot2)
  137. $cLight0Atten = "c31"; # [ constant, linear, quadratic, 0.0f ]
  138. $cLight1DiffColor = "c32";
  139. $cLight1Dir = "c33";
  140. $cLight1Pos = "c34";
  141. $cLight1SpotParams = "c35"; # [ exponent, stopdot, stopdot2, 1 / (stopdot - stopdot2)
  142. $cLight1Atten = "c36"; # [ constant, linear, quadratic, 0.0f ]
  143. $cModulationColor = "c37";
  144. $SHADER_SPECIFIC_CONST_0 = "c38";
  145. $SHADER_SPECIFIC_CONST_1 = "c39";
  146. $SHADER_SPECIFIC_CONST_2 = "c40";
  147. $SHADER_SPECIFIC_CONST_3 = "c41";
  148. $SHADER_SPECIFIC_CONST_4 = "c42";
  149. $SHADER_SPECIFIC_CONST_5 = "c43";
  150. $SHADER_SPECIFIC_CONST_6 = "c44";
  151. $SHADER_SPECIFIC_CONST_7 = "c45";
  152. $SHADER_SPECIFIC_CONST_8 = "c46";
  153. $SHADER_SPECIFIC_CONST_9 = "c47";
  154. ; $SHADER_SPECIFIC_CONST_10 is c14
  155. ; $SHADER_SPECIFIC_CONST_11 is c15
  156. ; There are 16 model matrices for skinning
  157. ; NOTE: These must match the same values in vsh_prep.pl!
  158. $cModel0 = "c48";
  159. $cModel1 = "c49";
  160. $cModel2 = "c50";
  161. sub OutputUsedRegisters
  162. {
  163. local( $i );
  164. ; USED REGISTERS
  165. for( $i = 0; $i < $g_NumRegisters; $i++ )
  166. {
  167. if( $g_allocated[$i] )
  168. {
  169. ; $g_allocatedname[$i] = r$i
  170. }
  171. }
  172. ;
  173. }
  174. sub AllocateRegister
  175. {
  176. local( *reg ) = shift;
  177. local( $regname ) = shift;
  178. local( $i );
  179. for( $i = 0; $i < $g_NumRegisters; $i++ )
  180. {
  181. if( !$g_allocated[$i] )
  182. {
  183. $g_allocated[$i] = 1;
  184. $g_allocatedname[$i] = $regname;
  185. ; AllocateRegister $regname = r$i
  186. $reg = "r$i";
  187. &OutputUsedRegisters();
  188. return;
  189. }
  190. }
  191. ; Out of registers allocating $regname!
  192. $reg = "rERROR_OUT_OF_REGISTERS";
  193. &OutputUsedRegisters();
  194. }
  195. ; pass in a reference to a var that contains a register. . ie \$var where var will constain "r1", etc
  196. sub FreeRegister
  197. {
  198. local( *reg ) = shift;
  199. local( $regname ) = shift;
  200. ; FreeRegister $regname = $reg
  201. if( $reg =~ m/rERROR_DEALLOCATED/ )
  202. {
  203. ; $regname already deallocated
  204. ; $reg = "rALREADY_DEALLOCATED";
  205. &OutputUsedRegisters();
  206. return;
  207. }
  208. ; if( $regname ne g_allocatedname[$reg] )
  209. ; {
  210. ; ; Error freeing $reg
  211. ; mov compileerror, freed unallocated register $regname
  212. ; }
  213. if( ( $reg =~ m/r(.*)/ ) )
  214. {
  215. $g_allocated[$1] = 0;
  216. }
  217. $reg = "rERROR_DEALLOCATED";
  218. &OutputUsedRegisters();
  219. }
  220. sub CheckUnfreedRegisters()
  221. {
  222. local( $i );
  223. for( $i = 0; $i < $g_NumRegisters; $i++ )
  224. {
  225. if( $g_allocated[$i] )
  226. {
  227. print "ERROR: r$i allocated to $g_allocatedname[$i] at end of program\n";
  228. $g_allocated[$i] = 0;
  229. }
  230. }
  231. }
  232. sub Normalize
  233. {
  234. local( $r ) = shift;
  235. dp3 $r.w, $r, $r
  236. rsq $r.w, $r.w
  237. mul $r, $r, $r.w
  238. }
  239. sub Cross
  240. {
  241. local( $result ) = shift;
  242. local( $a ) = shift;
  243. local( $b ) = shift;
  244. mul $result.xyz, $a.yzx, $b.zxy
  245. mad $result.xyz, -$b.yzx, $a.zxy, $result
  246. }
  247. sub RangeFog
  248. {
  249. local( $projPos ) = shift;
  250. ;------------------------------
  251. ; Regular range fog
  252. ;------------------------------
  253. ; oFog.x = 1.0f = no fog
  254. ; oFog.x = 0.0f = full fog
  255. ; compute fog factor f = (fog_end - dist)*(1/(fog_end-fog_start))
  256. ; this is == to: (fog_end/(fog_end-fog_start) - dist/(fog_end-fog_start)
  257. ; which can be expressed with a single mad instruction!
  258. ; Compute |projPos|
  259. local( $tmp );
  260. &AllocateRegister( \$tmp );
  261. dp3 $tmp.x, $projPos.xyw, $projPos.xyw
  262. rsq $tmp.x, $tmp.x
  263. rcp $tmp.x, $tmp.x
  264. if( $g_dx9 )
  265. {
  266. mad $tmp, -$tmp.x, $cOOFogRange, $cFogEndOverFogRange
  267. min $tmp, $tmp, $cOne
  268. max oFog, $tmp.x, $cFogMaxDensity
  269. }
  270. else
  271. {
  272. mad $tmp, -$tmp.x, $cOOFogRange, $cFogEndOverFogRange
  273. min $tmp, $tmp, $cOne
  274. max oFog.x, $tmp.x, $cFogMaxDensity
  275. }
  276. &FreeRegister( \$tmp );
  277. }
  278. sub DepthFog
  279. {
  280. local( $projPos ) = shift;
  281. local( $dest ) = shift;
  282. if ( $dest eq "" )
  283. {
  284. $dest = "oFog";
  285. }
  286. ;------------------------------
  287. ; Regular range fog
  288. ;------------------------------
  289. ; oFog.x = 1.0f = no fog
  290. ; oFog.x = 0.0f = full fog
  291. ; compute fog factor f = (fog_end - dist)*(1/(fog_end-fog_start))
  292. ; this is == to: (fog_end/(fog_end-fog_start) - dist/(fog_end-fog_start)
  293. ; which can be expressed with a single mad instruction!
  294. ; Compute |projPos|
  295. local( $tmp );
  296. &AllocateRegister( \$tmp );
  297. if( $g_dx9 )
  298. {
  299. mad $tmp, -$projPos.w, $cOOFogRange, $cFogEndOverFogRange
  300. min $tmp, $tmp, $cOne
  301. max $dest, $tmp.x, $cFogMaxDensity
  302. }
  303. else
  304. {
  305. mad $tmp, -$projPos.w, $cOOFogRange, $cFogEndOverFogRange
  306. min $tmp, $tmp, $cOne
  307. max $dest.x, $tmp.x, $cFogMaxDensity
  308. }
  309. &FreeRegister( \$tmp );
  310. }
  311. sub WaterRangeFog
  312. {
  313. ; oFog.x = 1.0f = no fog
  314. ; oFog.x = 0.0f = full fog
  315. ; only $worldPos.z is used out of worldPos
  316. local( $worldPos ) = shift;
  317. local( $projPos ) = shift;
  318. local( $tmp );
  319. &AllocateRegister( \$tmp );
  320. ; This is simple similar triangles. Imagine a line passing from the point directly vertically
  321. ; and another line passing from the point to the eye position.
  322. ; Let d = total distance from point to the eye
  323. ; Let h = vertical distance from the point to the eye
  324. ; Let hw = vertical distance from the point to the water surface
  325. ; Let dw = distance from the point to a point on the water surface that lies along the ray from point to eye
  326. ; Therefore d/h = dw/hw by similar triangles, or dw = d * hw / h.
  327. ; d = |projPos|, h = eyepos.z - worldPos.z, hw = waterheight.z - worldPos.z, dw = what we solve for
  328. ; Now, tmp.x = hw, and tmp.y = h
  329. add $tmp.xy, $cEyePosWaterZ.wz, -$worldPos.z
  330. ; if $tmp.x < 0, then set it to 0
  331. ; This is the equivalent of moving the vert to the water surface if it's above the water surface
  332. max $tmp.x, $tmp.x, $cZero
  333. ; Compute 1 / |projPos| = 1/d
  334. dp3 $tmp.z, $projPos.xyw, $projPos.xyw
  335. rsq $tmp.z, $tmp.z
  336. ; Now we have h/d
  337. mul $tmp.z, $tmp.z, $tmp.y
  338. ; Now we have d/h
  339. rcp $tmp.w, $tmp.z
  340. ; We finally have d * hw / h
  341. ; $tmp.w is now the distance that we see through water.
  342. mul $tmp.w, $tmp.x, $tmp.w
  343. if( $g_dx9 )
  344. {
  345. mad $tmp, -$tmp.w, $cOOFogRange, $cFogOne
  346. min $tmp, $tmp, $cOne
  347. max oFog, $tmp.x, $cFogMaxDensity
  348. }
  349. else
  350. {
  351. mad $tmp, -$tmp.w, $cOOFogRange, $cFogOne
  352. min $tmp, $tmp, $cOne
  353. max oFog.x, $tmp.x, $cFogMaxDensity
  354. }
  355. &FreeRegister( \$tmp );
  356. }
  357. sub WaterDepthFog
  358. {
  359. ; oFog.x = 1.0f = no fog
  360. ; oFog.x = 0.0f = full fog
  361. ; only $worldPos.z is used out of worldPos
  362. local( $worldPos ) = shift;
  363. local( $projPos ) = shift;
  364. local( $dest ) = shift;
  365. if ( $dest eq "" )
  366. {
  367. $dest = "oFog";
  368. }
  369. local( $tmp );
  370. &AllocateRegister( \$tmp );
  371. ; This is simple similar triangles. Imagine a line passing from the point directly vertically
  372. ; and another line passing from the point to the eye position.
  373. ; Let d = total distance from point to the eye
  374. ; Let h = vertical distance from the point to the eye
  375. ; Let hw = vertical distance from the point to the water surface
  376. ; Let dw = distance from the point to a point on the water surface that lies along the ray from point to eye
  377. ; Therefore d/h = dw/hw by similar triangles, or dw = d * hw / h.
  378. ; d = projPos.w, h = eyepos.z - worldPos.z, hw = waterheight.z - worldPos.z, dw = what we solve for
  379. ; Now, tmp.x = hw, and tmp.y = h
  380. add $tmp.xy, $cEyePosWaterZ.wz, -$worldPos.z
  381. ; if $tmp.x < 0, then set it to 0
  382. ; This is the equivalent of moving the vert to the water surface if it's above the water surface
  383. max $tmp.x, $tmp.x, $cZero
  384. ; Now we have 1/h
  385. rcp $tmp.z, $tmp.y
  386. ; Now we have d/h
  387. mul $tmp.w, $projPos.w, $tmp.z
  388. ; We finally have d * hw / h
  389. ; $tmp.w is now the distance that we see through water.
  390. mul $tmp.w, $tmp.x, $tmp.w
  391. if( $g_dx9 )
  392. {
  393. mad $tmp, -$tmp.w, $cOOFogRange, $cFogOne
  394. min $tmp, $tmp, $cOne
  395. max $dest, $tmp.x, $cZero
  396. }
  397. else
  398. {
  399. mad $tmp, -$tmp.w, $cOOFogRange, $cFogOne
  400. min $tmp, $tmp, $cOne
  401. max $dest.x, $tmp.x, $cZero
  402. }
  403. &FreeRegister( \$tmp );
  404. }
  405. ;------------------------------------------------------------------------------
  406. ; Main fogging routine
  407. ;------------------------------------------------------------------------------
  408. sub CalcFog
  409. {
  410. if( !defined $DOWATERFOG )
  411. {
  412. die "CalcFog called without using \$DOWATERFOG\n";
  413. }
  414. my $fogType;
  415. if( $DOWATERFOG == 0 )
  416. {
  417. $fogType = "rangefog";
  418. }
  419. else
  420. {
  421. $fogType = "heightfog";
  422. }
  423. # print "\$fogType = $fogType\n";
  424. ; CalcFog
  425. local( $worldPos ) = shift;
  426. local( $projPos ) = shift;
  427. local( $dest ) = shift;
  428. if ( $dest eq "" )
  429. {
  430. $dest = "oFog";
  431. }
  432. if( $fogType eq "rangefog" )
  433. {
  434. &DepthFog( $projPos, $dest );
  435. }
  436. elsif( $fogType eq "heightfog" )
  437. {
  438. &WaterDepthFog( $worldPos, $projPos, $dest );
  439. }
  440. else
  441. {
  442. die;
  443. }
  444. }
  445. sub CalcRangeFog
  446. {
  447. ; CalcFog
  448. local( $worldPos ) = shift;
  449. local( $projPos ) = shift;
  450. if( $DOWATERFOG == 0 )
  451. {
  452. &RangeFog( $projPos );
  453. }
  454. elsif( $DOWATERFOG == 1 )
  455. {
  456. &WaterRangeFog( $worldPos, $projPos );
  457. }
  458. else
  459. {
  460. die;
  461. }
  462. }
  463. sub GammaToLinear
  464. {
  465. local( $gamma ) = shift;
  466. local( $linear ) = shift;
  467. local( $tmp );
  468. &AllocateRegister( \$tmp );
  469. ; Is rcp more expensive than just storing 2.2 somewhere and doing a mov?
  470. rcp $gamma.w, $cOOGamma ; $gamma.w = 2.2
  471. lit $linear.z, $gamma.zzzw ; r0.z = linear blue
  472. lit $tmp.z, $gamma.yyyw ; r2.z = linear green
  473. mov $linear.y, $tmp.z ; r0.y = linear green
  474. lit $tmp.z, $gamma.xxxw ; r2.z = linear red
  475. mov $linear.x, $tmp.z ; r0.x = linear red
  476. &FreeRegister( \$tmp );
  477. }
  478. sub LinearToGamma
  479. {
  480. local( $linear ) = shift;
  481. local( $gamma ) = shift;
  482. local( $tmp );
  483. &AllocateRegister( \$tmp );
  484. mov $linear.w, $cOOGamma ; $linear.w = 1.0/2.2
  485. lit $gamma.z, $linear.zzzw ; r0.z = gamma blue
  486. lit $tmp.z, $linear.yyyw ; r2.z = gamma green
  487. mov $gamma.y, $tmp.z ; r0.y = gamma green
  488. lit $tmp.z, $linear.xxxw ; r2.z = gamma red
  489. mov $gamma.x, $tmp.z ; r0.x = gamma red
  490. &FreeRegister( \$tmp );
  491. }
  492. sub ComputeReflectionVector
  493. {
  494. local( $worldPos ) = shift;
  495. local( $worldNormal ) = shift;
  496. local( $reflectionVector ) = shift;
  497. local( $vertToEye ); &AllocateRegister( \$vertToEye );
  498. local( $tmp ); &AllocateRegister( \$tmp );
  499. ; compute reflection vector r = 2 * (n dot v) n - v
  500. sub $vertToEye.xyz, $cEyePos.xyz, $worldPos ; $tmp1 = v = c - p
  501. dp3 $tmp, $worldNormal, $vertToEye ; $tmp = n dot v
  502. mul $tmp.xyz, $tmp.xyz, $worldNormal ; $tmp = (n dot v ) n
  503. mad $reflectionVector.xyz, $tmp, $cTwo, -$vertToEye
  504. &FreeRegister( \$vertToEye );
  505. &FreeRegister( \$tmp );
  506. }
  507. sub ComputeSphereMapTexCoords
  508. {
  509. local( $reflectionVector ) = shift;
  510. local( $sphereMapTexCoords ) = shift;
  511. local( $tmp ); &AllocateRegister( \$tmp );
  512. ; transform reflection vector into view space
  513. dp3 $tmp.x, $reflectionVector, $cViewModel0
  514. dp3 $tmp.y, $reflectionVector, $cViewModel1
  515. dp3 $tmp.z, $reflectionVector, $cViewModel2
  516. ; generate <rx ry rz+1>
  517. add $tmp.z, $tmp.z, $cOne
  518. ; find 1 / the length of r2
  519. dp3 $tmp.w, $tmp, $tmp
  520. rsq $tmp.w, $tmp.w
  521. ; r1 = r2/|r2| + 1
  522. mad $tmp.xy, $tmp.w, $tmp, $cOne
  523. mul $sphereMapTexCoords.xy, $tmp.xy, $cHalf
  524. &FreeRegister( \$tmp );
  525. }
  526. sub SkinPosition
  527. {
  528. # print "\$SKINNING = $SKINNING\n";
  529. local( $worldPos ) = shift;
  530. if( !defined $SKINNING )
  531. {
  532. die "using \$SKINNING without defining.\n";
  533. }
  534. if( $SKINNING == 0 )
  535. {
  536. ;
  537. ; 0 bone skinning (4 instructions)
  538. ;
  539. ; Transform position into world space
  540. ; position
  541. dp4 $worldPos.x, $vPos, $cModel0
  542. dp4 $worldPos.y, $vPos, $cModel1
  543. dp4 $worldPos.z, $vPos, $cModel2
  544. mov $worldPos.w, $cOne
  545. }
  546. else
  547. {
  548. ;
  549. ; 3 bone skinning (19 instructions)
  550. ;
  551. local( $boneIndices );
  552. local( $blendedMatrix0 );
  553. local( $blendedMatrix1 );
  554. local( $blendedMatrix2 );
  555. local( $localPos );
  556. &AllocateRegister( \$boneIndices );
  557. &AllocateRegister( \$blendedMatrix0 );
  558. &AllocateRegister( \$blendedMatrix1 );
  559. &AllocateRegister( \$blendedMatrix2 );
  560. ; Transform position into world space using all bones
  561. ; denormalize d3dcolor to matrix index
  562. mad $boneIndices, $vBoneIndices, $cColorToIntScale, $cModel0Index
  563. if ( $g_x360 )
  564. {
  565. mov $boneIndices, $boneIndices.zyxw
  566. }
  567. ; r11 = boneindices at this point
  568. ; first matrix
  569. mov a0.x, $boneIndices.z
  570. mul $blendedMatrix0, $vBoneWeights.x, c[a0.x]
  571. mul $blendedMatrix1, $vBoneWeights.x, c[a0.x+1]
  572. mul $blendedMatrix2, $vBoneWeights.x, c[a0.x+2]
  573. ; second matrix
  574. mov a0.x, $boneIndices.y
  575. mad $blendedMatrix0, $vBoneWeights.y, c[a0.x], $blendedMatrix0
  576. mad $blendedMatrix1, $vBoneWeights.y, c[a0.x+1], $blendedMatrix1
  577. mad $blendedMatrix2, $vBoneWeights.y, c[a0.x+2], $blendedMatrix2
  578. ; Calculate third weight
  579. ; compute 1-(weight1+weight2) to calculate weight2
  580. ; Use $boneIndices.w as a temp since we aren't using it for anything.
  581. add $boneIndices.w, $vBoneWeights.x, $vBoneWeights.y
  582. sub $boneIndices.w, $cOne, $boneIndices.w
  583. ; third matrix
  584. mov a0.x, $boneIndices.x
  585. mad $blendedMatrix0, $boneIndices.w, c[a0.x], $blendedMatrix0
  586. mad $blendedMatrix1, $boneIndices.w, c[a0.x+1], $blendedMatrix1
  587. mad $blendedMatrix2, $boneIndices.w, c[a0.x+2], $blendedMatrix2
  588. dp4 $worldPos.x, $vPos, $blendedMatrix0
  589. dp4 $worldPos.y, $vPos, $blendedMatrix1
  590. dp4 $worldPos.z, $vPos, $blendedMatrix2
  591. mov $worldPos.w, $cOne
  592. &FreeRegister( \$boneIndices );
  593. &FreeRegister( \$blendedMatrix0 );
  594. &FreeRegister( \$blendedMatrix1 );
  595. &FreeRegister( \$blendedMatrix2 );
  596. }
  597. }
  598. sub SkinPositionAndNormal
  599. {
  600. # print "\$SKINNING = $SKINNING\n";
  601. local( $worldPos ) = shift;
  602. local( $worldNormal ) = shift;
  603. if( !defined $SKINNING )
  604. {
  605. die "using \$SKINNING without defining.\n";
  606. }
  607. if( $SKINNING == 0 )
  608. {
  609. ;
  610. ; 0 bone skinning (13 instructions)
  611. ;
  612. ; Transform position + normal + tangentS + tangentT into world space
  613. ; position
  614. dp4 $worldPos.x, $vPos, $cModel0
  615. dp4 $worldPos.y, $vPos, $cModel1
  616. dp4 $worldPos.z, $vPos, $cModel2
  617. mov $worldPos.w, $cOne
  618. ; normal
  619. dp3 $worldNormal.x, $vNormal, $cModel0
  620. dp3 $worldNormal.y, $vNormal, $cModel1
  621. dp3 $worldNormal.z, $vNormal, $cModel2
  622. }
  623. else
  624. {
  625. local( $boneIndices );
  626. local( $blendedMatrix0 );
  627. local( $blendedMatrix1 );
  628. local( $blendedMatrix2 );
  629. local( $localPos );
  630. local( $localNormal );
  631. local( $normalLength );
  632. local( $ooNormalLength );
  633. &AllocateRegister( \$boneIndices );
  634. &AllocateRegister( \$blendedMatrix0 );
  635. &AllocateRegister( \$blendedMatrix1 );
  636. &AllocateRegister( \$blendedMatrix2 );
  637. ; Transform position into world space using all bones
  638. ; denormalize d3dcolor to matrix index
  639. mad $boneIndices, $vBoneIndices, $cColorToIntScale, $cModel0Index
  640. if ( $g_x360 )
  641. {
  642. mov $boneIndices, $boneIndices.zyxw
  643. }
  644. ; r11 = boneindices at this point
  645. ; first matrix
  646. mov a0.x, $boneIndices.z
  647. mul $blendedMatrix0, $vBoneWeights.x, c[a0.x]
  648. mul $blendedMatrix1, $vBoneWeights.x, c[a0.x+1]
  649. mul $blendedMatrix2, $vBoneWeights.x, c[a0.x+2]
  650. ; second matrix
  651. mov a0.x, $boneIndices.y
  652. mad $blendedMatrix0, $vBoneWeights.y, c[a0.x], $blendedMatrix0
  653. mad $blendedMatrix1, $vBoneWeights.y, c[a0.x+1], $blendedMatrix1
  654. mad $blendedMatrix2, $vBoneWeights.y, c[a0.x+2], $blendedMatrix2
  655. ; Calculate third weight
  656. ; compute 1-(weight1+weight2) to calculate weight2
  657. ; Use $boneIndices.w as a temp since we aren't using it for anything.
  658. add $boneIndices.w, $vBoneWeights.x, $vBoneWeights.y
  659. sub $boneIndices.w, $cOne, $boneIndices.w
  660. ; third matrix
  661. mov a0.x, $boneIndices.x
  662. mad $blendedMatrix0, $boneIndices.w, c[a0.x], $blendedMatrix0
  663. mad $blendedMatrix1, $boneIndices.w, c[a0.x+1], $blendedMatrix1
  664. mad $blendedMatrix2, $boneIndices.w, c[a0.x+2], $blendedMatrix2
  665. dp4 $worldPos.x, $vPos, $blendedMatrix0
  666. dp4 $worldPos.y, $vPos, $blendedMatrix1
  667. dp4 $worldPos.z, $vPos, $blendedMatrix2
  668. mov $worldPos.w, $cOne
  669. ; normal
  670. dp3 $worldNormal.x, $vNormal, $blendedMatrix0
  671. dp3 $worldNormal.y, $vNormal, $blendedMatrix1
  672. dp3 $worldNormal.z, $vNormal, $blendedMatrix2
  673. &FreeRegister( \$boneIndices );
  674. &FreeRegister( \$blendedMatrix0 );
  675. &FreeRegister( \$blendedMatrix1 );
  676. &FreeRegister( \$blendedMatrix2 );
  677. }
  678. }
  679. sub SkinPositionNormalAndTangentSpace
  680. {
  681. # print "\$SKINNING = $SKINNING\n";
  682. local( $worldPos ) = shift;
  683. local( $worldNormal ) = shift;
  684. local( $worldTangentS ) = shift;
  685. local( $worldTangentT ) = shift;
  686. local( $userData );
  687. local( $localPos );
  688. local( $localNormal );
  689. local( $normalLength );
  690. local( $ooNormalLength );
  691. if( !defined $SKINNING )
  692. {
  693. die "using \$SKINNING without defining.\n";
  694. }
  695. # X360TBD: needed for compressed vertex format
  696. # if ( $g_x360 )
  697. # {
  698. # &AllocateRegister( \$userData );
  699. # ; remap compressed range [0..1] to [-1..1]
  700. # mad $userData, $vUserData, $cTwo, -$cOne
  701. # }
  702. if( $SKINNING == 0 )
  703. {
  704. ;
  705. ; 0 bone skinning (13 instructions)
  706. ;
  707. ; Transform position + normal + tangentS + tangentT into world space
  708. dp4 $worldPos.x, $vPos, $cModel0
  709. dp4 $worldPos.y, $vPos, $cModel1
  710. dp4 $worldPos.z, $vPos, $cModel2
  711. mov $worldPos.w, $cOne
  712. ; normal
  713. dp3 $worldNormal.x, $vNormal, $cModel0
  714. dp3 $worldNormal.y, $vNormal, $cModel1
  715. dp3 $worldNormal.z, $vNormal, $cModel2
  716. # X360TBD: needed for compressed vertex format
  717. # if ( $g_x360 )
  718. # {
  719. # ; tangents
  720. # dp3 $worldTangentS.x, $userData, $cModel0
  721. # dp3 $worldTangentS.y, $userData, $cModel1
  722. # dp3 $worldTangentS.z, $userData, $cModel2
  723. #
  724. # ; calculate tangent t via cross( N, S ) * S[3]
  725. # &Cross( $worldTangentT, $worldNormal, $worldTangentS );
  726. # mul $worldTangentT.xyz, $userData.w, $worldTangentT.xyz
  727. # }
  728. # else
  729. {
  730. ; tangents
  731. dp3 $worldTangentS.x, $vUserData, $cModel0
  732. dp3 $worldTangentS.y, $vUserData, $cModel1
  733. dp3 $worldTangentS.z, $vUserData, $cModel2
  734. ; calculate tangent t via cross( N, S ) * S[3]
  735. &Cross( $worldTangentT, $worldNormal, $worldTangentS );
  736. mul $worldTangentT.xyz, $vUserData.w, $worldTangentT.xyz
  737. }
  738. }
  739. else
  740. {
  741. local( $boneIndices );
  742. local( $blendedMatrix0 );
  743. local( $blendedMatrix1 );
  744. local( $blendedMatrix2 );
  745. &AllocateRegister( \$boneIndices );
  746. &AllocateRegister( \$blendedMatrix0 );
  747. &AllocateRegister( \$blendedMatrix1 );
  748. &AllocateRegister( \$blendedMatrix2 );
  749. ; Transform position into world space using all bones
  750. ; denormalize d3dcolor to matrix index
  751. mad $boneIndices, $vBoneIndices, $cColorToIntScale, $cModel0Index
  752. if ( $g_x360 )
  753. {
  754. mov $boneIndices, $boneIndices.zyxw
  755. }
  756. ; r11 = boneindices at this point
  757. ; first matrix
  758. mov a0.x, $boneIndices.z
  759. mul $blendedMatrix0, $vBoneWeights.x, c[a0.x]
  760. mul $blendedMatrix1, $vBoneWeights.x, c[a0.x+1]
  761. mul $blendedMatrix2, $vBoneWeights.x, c[a0.x+2]
  762. ; second matrix
  763. mov a0.x, $boneIndices.y
  764. mad $blendedMatrix0, $vBoneWeights.y, c[a0.x], $blendedMatrix0
  765. mad $blendedMatrix1, $vBoneWeights.y, c[a0.x+1], $blendedMatrix1
  766. mad $blendedMatrix2, $vBoneWeights.y, c[a0.x+2], $blendedMatrix2
  767. ; Calculate third weight
  768. ; compute 1-(weight1+weight2) to calculate weight2
  769. ; Use $boneIndices.w as a temp since we aren't using it for anything.
  770. add $boneIndices.w, $vBoneWeights.x, $vBoneWeights.y
  771. sub $boneIndices.w, $cOne, $boneIndices.w
  772. ; third matrix
  773. mov a0.x, $boneIndices.x
  774. mad $blendedMatrix0, $boneIndices.w, c[a0.x], $blendedMatrix0
  775. mad $blendedMatrix1, $boneIndices.w, c[a0.x+1], $blendedMatrix1
  776. mad $blendedMatrix2, $boneIndices.w, c[a0.x+2], $blendedMatrix2
  777. ; position
  778. dp4 $worldPos.x, $vPos, $blendedMatrix0
  779. dp4 $worldPos.y, $vPos, $blendedMatrix1
  780. dp4 $worldPos.z, $vPos, $blendedMatrix2
  781. mov $worldPos.w, $cOne
  782. ; normal
  783. dp3 $worldNormal.x, $vNormal, $blendedMatrix0
  784. dp3 $worldNormal.y, $vNormal, $blendedMatrix1
  785. dp3 $worldNormal.z, $vNormal, $blendedMatrix2
  786. # X360TBD: needed for compressed vertex format
  787. # if ( $g_x360 )
  788. # {
  789. # ; tangents
  790. # dp3 $worldTangentS.x, $userData, $blendedMatrix0
  791. # dp3 $worldTangentS.y, $userData, $blendedMatrix1
  792. # dp3 $worldTangentS.z, $userData, $blendedMatrix2
  793. #
  794. # ; calculate tangent t via cross( N, S ) * S[3]
  795. # &Cross( $worldTangentT, $worldNormal, $worldTangentS );
  796. # mul $worldTangentT.xyz, $userData.w, $worldTangentT.xyz
  797. # }
  798. # else
  799. {
  800. ; tangents
  801. dp3 $worldTangentS.x, $vUserData, $blendedMatrix0
  802. dp3 $worldTangentS.y, $vUserData, $blendedMatrix1
  803. dp3 $worldTangentS.z, $vUserData, $blendedMatrix2
  804. ; calculate tangent t via cross( N, S ) * S[3]
  805. &Cross( $worldTangentT, $worldNormal, $worldTangentS );
  806. mul $worldTangentT.xyz, $vUserData.w, $worldTangentT.xyz
  807. }
  808. &FreeRegister( \$boneIndices );
  809. &FreeRegister( \$blendedMatrix0 );
  810. &FreeRegister( \$blendedMatrix1 );
  811. &FreeRegister( \$blendedMatrix2 );
  812. }
  813. # X360TBD: needed for compressed vertex format
  814. # if ( $g_x360 )
  815. # {
  816. # &FreeRegister( \$userData );
  817. # }
  818. }
  819. sub ColorClamp
  820. {
  821. ; ColorClamp; stomps $color.w
  822. local( $color ) = shift;
  823. local( $dst ) = shift;
  824. ; Get the max of RGB and stick it in W
  825. max $color.w, $color.x, $color.y
  826. max $color.w, $color.w, $color.z
  827. ; get the greater of one and the max color.
  828. max $color.w, $color.w, $cOne
  829. rcp $color.w, $color.w
  830. mul $dst.xyz, $color.w, $color.xyz
  831. }
  832. sub AmbientLight
  833. {
  834. local( $worldNormal ) = shift;
  835. local( $linearColor ) = shift;
  836. local( $add ) = shift;
  837. ; Ambient lighting
  838. &AllocateRegister( \$nSquared );
  839. &AllocateRegister( \$isNegative );
  840. mul $nSquared.xyz, $worldNormal.xyz, $worldNormal.xyz ; compute n times n
  841. slt $isNegative.xyz, $worldNormal.xyz, $cZero ; Figure out whether each component is >0
  842. mov a0.x, $isNegative.x
  843. if( $add )
  844. {
  845. mad $linearColor.xyz, $nSquared.x, c[a0.x + $cAmbientColorPosXOffset], $linearColor ; $linearColor = normal[0]*normal[0] * box color of appropriate x side
  846. }
  847. else
  848. {
  849. mul $linearColor.xyz, $nSquared.x, c[a0.x + $cAmbientColorPosXOffset] ; $linearColor = normal[0]*normal[0] * box color of appropriate x side
  850. }
  851. mov a0.x, $isNegative.y
  852. mad $linearColor.xyz, $nSquared.y, c[a0.x + $cAmbientColorPosYOffset], $linearColor
  853. mov a0.x, $isNegative.z
  854. mad $linearColor.xyz, $nSquared.z, c[a0.x + $cAmbientColorPosZOffset], $linearColor
  855. &FreeRegister( \$isNegative );
  856. &FreeRegister( \$nSquared );
  857. }
  858. sub DirectionalLight
  859. {
  860. local( $worldNormal ) = shift;
  861. local( $linearColor ) = shift;
  862. local( $add ) = shift;
  863. &AllocateRegister( \$nDotL ); # FIXME: This only needs to be a scalar
  864. ; NOTE: Gotta use -l here, since light direction = -l
  865. ; DIRECTIONAL LIGHT
  866. ; compute n dot l
  867. dp3 $nDotL.x, -c[a0.x + 1], $worldNormal
  868. if ( $HALF_LAMBERT == 0 )
  869. {
  870. ; lambert
  871. max $nDotL.x, $nDotL.x, c0.x ; Clamp to zero
  872. }
  873. elsif ( $HALF_LAMBERT == 1 )
  874. {
  875. ; half-lambert
  876. mad $nDotL.x, $nDotL.x, $cHalf, $cHalf ; dot = (dot * 0.5 + 0.5)^2
  877. mul $nDotL.x, $nDotL.x, $nDotL.x
  878. }
  879. else
  880. {
  881. die "\$HALF_LAMBERT is hosed\n";
  882. }
  883. if( $add )
  884. {
  885. mad $linearColor.xyz, c[a0.x], $nDotL.x, $linearColor
  886. }
  887. else
  888. {
  889. mul $linearColor.xyz, c[a0.x], $nDotL.x
  890. }
  891. &FreeRegister( \$nDotL );
  892. }
  893. sub PointLight
  894. {
  895. local( $worldPos ) = shift;
  896. local( $worldNormal ) = shift;
  897. local( $linearColor ) = shift;
  898. local( $add ) = shift;
  899. local( $lightDir );
  900. &AllocateRegister( \$lightDir );
  901. ; POINT LIGHT
  902. ; compute light direction
  903. sub $lightDir, c[a0.x+2], $worldPos
  904. local( $lightDistSquared );
  905. local( $ooLightDist );
  906. &AllocateRegister( \$lightDistSquared );
  907. &AllocateRegister( \$ooLightDist );
  908. ; normalize light direction, maintain temporaries for attenuation
  909. dp3 $lightDistSquared, $lightDir, $lightDir
  910. rsq $ooLightDist, $lightDistSquared.x
  911. mul $lightDir, $lightDir, $ooLightDist.x
  912. local( $attenuationFactors );
  913. &AllocateRegister( \$attenuationFactors );
  914. ; compute attenuation amount (r2 = 'd*d d*d d*d d*d', r3 = '1/d 1/d 1/d 1/d')
  915. dst $attenuationFactors, $lightDistSquared, $ooLightDist ; r4 = ( 1, d, d*d, 1/d )
  916. &FreeRegister( \$lightDistSquared );
  917. &FreeRegister( \$ooLightDist );
  918. local( $attenuation );
  919. &AllocateRegister( \$attenuation );
  920. dp3 $attenuation, $attenuationFactors, c[a0.x+4] ; r3 = atten0 + d * atten1 + d*d * atten2
  921. rcp $lightDir.w, $attenuation ; $lightDir.w = 1 / (atten0 + d * atten1 + d*d * atten2)
  922. &FreeRegister( \$attenuationFactors );
  923. &FreeRegister( \$attenuation );
  924. local( $tmp );
  925. &AllocateRegister( \$tmp ); # FIXME : really only needs to be a scalar
  926. ; compute n dot l, fold in distance attenutation
  927. dp3 $tmp.x, $lightDir, $worldNormal
  928. if ( $HALF_LAMBERT == 0 )
  929. {
  930. ; lambert
  931. max $tmp.x, $tmp.x, c0.x ; Clamp to zero
  932. }
  933. elsif ( $HALF_LAMBERT == 1 )
  934. {
  935. ; half-lambert
  936. mad $tmp.x, $tmp.x, $cHalf, $cHalf ; dot = (dot * 0.5 + 0.5)^2
  937. mul $tmp.x, $tmp.x, $tmp.x
  938. }
  939. else
  940. {
  941. die "\$HALF_LAMBERT is hosed\n";
  942. }
  943. mul $tmp.x, $tmp.x, $lightDir.w
  944. if( $add )
  945. {
  946. mad $linearColor.xyz, c[a0.x], $tmp.x, $linearColor
  947. }
  948. else
  949. {
  950. mul $linearColor.xyz, c[a0.x], $tmp.x
  951. }
  952. &FreeRegister( \$lightDir );
  953. &FreeRegister( \$tmp ); # FIXME : really only needs to be a scalar
  954. }
  955. sub SpotLight
  956. {
  957. local( $worldPos ) = shift;
  958. local( $worldNormal ) = shift;
  959. local( $linearColor ) = shift;
  960. local( $add ) = shift;
  961. local( $lightDir );
  962. &AllocateRegister( \$lightDir );
  963. ; SPOTLIGHT
  964. ; compute light direction
  965. sub $lightDir, c[a0.x+2], $worldPos
  966. local( $lightDistSquared );
  967. local( $ooLightDist );
  968. &AllocateRegister( \$lightDistSquared );
  969. &AllocateRegister( \$ooLightDist );
  970. ; normalize light direction, maintain temporaries for attenuation
  971. dp3 $lightDistSquared, $lightDir, $lightDir
  972. rsq $ooLightDist, $lightDistSquared.x
  973. mul $lightDir, $lightDir, $ooLightDist.x
  974. local( $attenuationFactors );
  975. &AllocateRegister( \$attenuationFactors );
  976. ; compute attenuation amount (r2 = 'd*d d*d d*d d*d', r3 = '1/d 1/d 1/d 1/d')
  977. dst $attenuationFactors, $lightDistSquared, $ooLightDist ; r4 = ( 1, d, d*d, 1/d )
  978. &FreeRegister( \$lightDistSquared );
  979. &FreeRegister( \$ooLightDist );
  980. local( $attenuation ); &AllocateRegister( \$attenuation );
  981. dp3 $attenuation, $attenuationFactors, c[a0.x+4] ; r3 = atten0 + d * atten1 + d*d * atten2
  982. rcp $lightDir.w, $attenuation ; r1.w = 1 / (atten0 + d * atten1 + d*d * atten2)
  983. &FreeRegister( \$attenuationFactors );
  984. &FreeRegister( \$attenuation );
  985. local( $litSrc ); &AllocateRegister( \$litSrc );
  986. local( $tmp ); &AllocateRegister( \$tmp ); # FIXME - only needs to be scalar
  987. ; compute n dot l
  988. dp3 $litSrc.x, $worldNormal, $lightDir
  989. if ( $HALF_LAMBERT == 0 )
  990. {
  991. ; lambert
  992. max $litSrc.x, $litSrc.x, c0.x ; Clamp to zero
  993. }
  994. elsif ( $HALF_LAMBERT == 1 )
  995. {
  996. ; half-lambert
  997. mad $litSrc.x, $litSrc.x, $cHalf, $cHalf ; dot = (dot * 0.5 + 0.5) ^ 2
  998. mul $litSrc.x, $litSrc.x, $litSrc.x
  999. }
  1000. else
  1001. {
  1002. die "\$HALF_LAMBERT is hosed\n";
  1003. }
  1004. ; compute angular attenuation
  1005. dp3 $tmp.x, c[a0.x+1], -$lightDir ; dot = -delta * spot direction
  1006. sub $litSrc.y, $tmp.x, c[a0.x+3].z ; r2.y = dot - stopdot2
  1007. &FreeRegister( \$tmp );
  1008. mul $litSrc.y, $litSrc.y, c[a0.x+3].w ; r2.y = (dot - stopdot2) / (stopdot - stopdot2)
  1009. mov $litSrc.w, c[a0.x+3].x ; r2.w = exponent
  1010. local( $litDst ); &AllocateRegister( \$litDst );
  1011. lit $litDst, $litSrc ; r3.y = N dot L or 0, whichever is bigger
  1012. &FreeRegister( \$litSrc );
  1013. ; r3.z = pow((dot - stopdot2) / (stopdot - stopdot2), exponent)
  1014. min $litDst.z, $litDst.z, $cOne ; clamp pow() to 1
  1015. local( $tmp1 ); &AllocateRegister( \$tmp1 );
  1016. local( $tmp2 ); &AllocateRegister( \$tmp2 ); # FIXME - could be scalar
  1017. ; fold in distance attenutation with other factors
  1018. mul $tmp1, c[a0.x], $lightDir.w
  1019. mul $tmp2.x, $litDst.y, $litDst.z
  1020. if( $add )
  1021. {
  1022. mad $linearColor.xyz, $tmp1, $tmp2.x, $linearColor
  1023. }
  1024. else
  1025. {
  1026. mul $linearColor.xyz, $tmp1, $tmp2.x
  1027. }
  1028. &FreeRegister( \$lightDir );
  1029. &FreeRegister( \$litDst );
  1030. &FreeRegister( \$tmp1 );
  1031. &FreeRegister( \$tmp2 );
  1032. }
  1033. sub DoLight
  1034. {
  1035. local( $lightType ) = shift;
  1036. local( $worldPos ) = shift;
  1037. local( $worldNormal ) = shift;
  1038. local( $linearColor ) = shift;
  1039. local( $add ) = shift;
  1040. if( $lightType eq "spot" )
  1041. {
  1042. &SpotLight( $worldPos, $worldNormal, $linearColor, $add );
  1043. }
  1044. elsif( $lightType eq "point" )
  1045. {
  1046. &PointLight( $worldPos, $worldNormal, $linearColor, $add );
  1047. }
  1048. elsif( $lightType eq "directional" )
  1049. {
  1050. &DirectionalLight( $worldNormal, $linearColor, $add );
  1051. }
  1052. else
  1053. {
  1054. die "don't know about light type \"$lightType\"\n";
  1055. }
  1056. }
  1057. sub DoLighting
  1058. {
  1059. if( !defined $LIGHT_COMBO )
  1060. {
  1061. die "DoLighting called without using \$LIGHT_COMBO\n";
  1062. }
  1063. if ( !defined $HALF_LAMBERT )
  1064. {
  1065. die "DoLighting called without using \$HALF_LAMBERT\n";
  1066. }
  1067. my $staticLightType = $g_staticLightTypeArray[$LIGHT_COMBO];
  1068. my $ambientLightType = $g_ambientLightTypeArray[$LIGHT_COMBO];
  1069. my $localLightType1 = $g_localLightType1Array[$LIGHT_COMBO];
  1070. my $localLightType2 = $g_localLightType2Array[$LIGHT_COMBO];
  1071. # print "\$staticLightType = $staticLightType\n";
  1072. # print "\$ambientLightType = $ambientLightType\n";
  1073. # print "\$localLightType1 = $localLightType1\n";
  1074. # print "\$localLightType2 = $localLightType2\n";
  1075. local( $worldPos ) = shift;
  1076. local( $worldNormal ) = shift;
  1077. ; special case for no lighting
  1078. if( $staticLightType eq "none" && $ambientLightType eq "none" &&
  1079. $localLightType1 eq "none" && $localLightType2 eq "none" )
  1080. {
  1081. ; Have to write something here since debug d3d runtime will barf otherwise.
  1082. mov oD0, $cOne
  1083. return;
  1084. }
  1085. ; special case for static lighting only
  1086. ; Don't need to bother converting to linear space in this case.
  1087. if( $staticLightType eq "static" && $ambientLightType eq "none" &&
  1088. $localLightType1 eq "none" && $localLightType2 eq "none" )
  1089. {
  1090. mov oD0, $vSpecular
  1091. return;
  1092. }
  1093. alloc $linearColor
  1094. alloc $gammaColor
  1095. local( $add ) = 0;
  1096. if( $staticLightType eq "static" )
  1097. {
  1098. ; The static lighting comes in in gamma space and has also been premultiplied by $cOverbrightFactor
  1099. ; need to get it into
  1100. ; linear space so that we can do adds.
  1101. rcp $gammaColor.w, $cOverbrightFactor
  1102. mul $gammaColor.xyz, $vSpecular, $gammaColor.w
  1103. &GammaToLinear( $gammaColor, $linearColor );
  1104. $add = 1;
  1105. }
  1106. if( $ambientLightType eq "ambient" )
  1107. {
  1108. &AmbientLight( $worldNormal, $linearColor, $add );
  1109. $add = 1;
  1110. }
  1111. if( $localLightType1 ne "none" )
  1112. {
  1113. mov a0.x, $cLight0Offset
  1114. &DoLight( $localLightType1, $worldPos, $worldNormal, $linearColor, $add );
  1115. $add = 1;
  1116. }
  1117. if( $localLightType2 ne "none" )
  1118. {
  1119. mov a0.x, $cLight1Offset
  1120. &DoLight( $localLightType2, $worldPos, $worldNormal, $linearColor, $add );
  1121. $add = 1;
  1122. }
  1123. ;------------------------------------------------------------------------------
  1124. ; Output color (gamma correction)
  1125. ;------------------------------------------------------------------------------
  1126. &LinearToGamma( $linearColor, $gammaColor );
  1127. if( 0 )
  1128. {
  1129. mul oD0.xyz, $gammaColor.xyz, $cOverbrightFactor
  1130. }
  1131. else
  1132. {
  1133. mul $gammaColor.xyz, $gammaColor.xyz, $cOverbrightFactor
  1134. &ColorClamp( $gammaColor, "oD0" );
  1135. }
  1136. ; mov oD0.xyz, $linearColor
  1137. mov oD0.w, $cOne ; make sure all components are defined
  1138. free $linearColor
  1139. free $gammaColor
  1140. }
  1141. sub DoDynamicLightingToLinear
  1142. {
  1143. local( $worldPos ) = shift;
  1144. local( $worldNormal ) = shift;
  1145. local( $linearColor ) = shift;
  1146. if( !defined $LIGHT_COMBO )
  1147. {
  1148. die "DoLighting called without using \$LIGHT_COMBO\n";
  1149. }
  1150. if ( !defined $HALF_LAMBERT )
  1151. {
  1152. die "DoLighting called without using \$HALF_LAMBERT\n";
  1153. }
  1154. my $staticLightType = $g_staticLightTypeArray[$LIGHT_COMBO];
  1155. my $ambientLightType = $g_ambientLightTypeArray[$LIGHT_COMBO];
  1156. my $localLightType1 = $g_localLightType1Array[$LIGHT_COMBO];
  1157. my $localLightType2 = $g_localLightType2Array[$LIGHT_COMBO];
  1158. # No lights at all. . note that we don't even consider static lighting here.
  1159. if( $ambientLightType eq "none" &&
  1160. $localLightType1 eq "none" && $localLightType2 eq "none" )
  1161. {
  1162. mov $linearColor, $cZero
  1163. return;
  1164. }
  1165. local( $add ) = 0;
  1166. if( $ambientLightType eq "ambient" )
  1167. {
  1168. &AmbientLight( $worldNormal, $linearColor, $add );
  1169. $add = 1;
  1170. }
  1171. if( $localLightType1 ne "none" )
  1172. {
  1173. mov a0.x, $cLight0Offset
  1174. &DoLight( $localLightType1, $worldPos, $worldNormal, $linearColor, $add );
  1175. $add = 1;
  1176. }
  1177. if( $localLightType2 ne "none" )
  1178. {
  1179. mov a0.x, $cLight1Offset
  1180. &DoLight( $localLightType2, $worldPos, $worldNormal, $linearColor, $add );
  1181. $add = 1;
  1182. }
  1183. }
  1184. sub NotImplementedYet
  1185. {
  1186. &AllocateRegister( \$projPos );
  1187. dp4 $projPos.x, $worldPos, $cViewProj0
  1188. dp4 $projPos.y, $worldPos, $cViewProj1
  1189. dp4 $projPos.z, $worldPos, $cViewProj2
  1190. dp4 $projPos.w, $worldPos, $cViewProj3
  1191. mov oPos, $projPos
  1192. &FreeRegister( \$projPos );
  1193. exit;
  1194. }