TreeSway.fx 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. //////////////////////////////////////////////////////////////////////////////
  2. // ©2007 Electronic Arts Inc
  3. //
  4. // FX Shader for Fields of Grass Red Alert 3
  5. //////////////////////////////////////////////////////////////////////////////
  6. #define USE_INTERACTIVE_LIGHTS 1
  7. #define SUPPORT_CLOUDS 1
  8. #define SUPPORT_FOG 1
  9. #define SUPPORT_GLOBAL_LIGHTS 1
  10. #define SUPPORT_LOCAL_LIGHTS 1
  11. #define MaxNumPointLights 3
  12. #include "Common.fxh"
  13. #include "Gamma.fxh"
  14. #include "ShadowMap.fxh"
  15. int _SasGlobal : SasGlobal
  16. <
  17. string UIWidget = "None";
  18. int3 SasVersion = int3(1, 0, 0);
  19. int MaxLocalLights = MaxNumPointLights;
  20. int MaxSupportedInstancingMode = INSTANCING_MODE_ONE_PER_DRAW_CALL;
  21. > = 0;
  22. #if defined(EA_PLATFORM_WINDOWS) && defined(_3DSMAX_)
  23. // ----------------------------------------------------------------------------
  24. // SAMPLER : nhendrickss : had to pull these in here for MAX to compile
  25. // ----------------------------------------------------------------------------
  26. #define SAMPLER_2D_BEGIN(samplerName, annotations) \
  27. texture samplerName \
  28. < \
  29. annotations \
  30. >; \
  31. sampler2D samplerName##Sampler = sampler_state \
  32. { \
  33. Texture = < samplerName >;
  34. #define SAMPLER_2D_END };
  35. #define SAMPLER( samplerName ) samplerName##Sampler
  36. #define SAMPLER_CUBE_BEGIN(samplerName, annotations) \
  37. texture samplerName \
  38. < \
  39. annotations \
  40. >; \
  41. samplerCUBE samplerName##Sampler = sampler_state \
  42. { \
  43. Texture = < samplerName >;
  44. #define SAMPLER_CUBE_END };
  45. #endif
  46. // ----------------------------------------------------------------------------
  47. // Skinning
  48. // ----------------------------------------------------------------------------
  49. #define MaxSkinningBonesPerVertex 1
  50. #include "Skinning.fxh"
  51. // ----------------------------------------------------------------------------
  52. // Editable parameters
  53. // ----------------------------------------------------------------------------
  54. SAMPLER_2D_BEGIN( DiffuseTexture,
  55. string UIName = "Diffuse Texture";
  56. )
  57. MinFilter = MinFilterBest;
  58. MagFilter = MagFilterBest;
  59. MipFilter = MipFilterBest;
  60. MaxAnisotropy = 8;
  61. AddressU = Wrap;
  62. AddressV = Wrap;
  63. SAMPLER_2D_END
  64. float3 AmbientColor
  65. <
  66. string UIName = "Ambient Color";
  67. string UIWidget = "Color";
  68. > = float3(0.4, 0.4, 0.4);
  69. float4 DiffuseColor
  70. <
  71. string UIName = "Diffuse Color";
  72. string UIWidget = "Color";
  73. > = float4(1.0, 1.0, 1.0, 1.0);
  74. bool SwayEnable
  75. <
  76. string UIName = "Sway Enable";
  77. > = false;
  78. // --------------------------------------------------
  79. // Editable controls for the 1st Gerstner Wave
  80. // --------------------------------------------------
  81. float Amp1
  82. <
  83. string UIName = "Sway Amplitude";
  84. string UIWidget = "Slider";
  85. float UIMax = 100.0f;
  86. float UIMin = 0;
  87. float UIStep = 0.01f;
  88. > = float (1.0);
  89. float Freq1
  90. <
  91. string UIName = "Sway Frequency";
  92. string UIWidget = "Slider";
  93. float UIMax = 100.0f;
  94. float UIMin = 0;
  95. float UIStep = 0.01f;
  96. > = float (10.0);
  97. float Phase1
  98. <
  99. string UIName = "Sway Phase";
  100. string UIWidget = "Slider";
  101. float UIMax = 100.0f;
  102. float UIMin = 0;
  103. float UIStep = 0.01f;
  104. > = float (1.0);
  105. // ----------------------------------------------------------------------------
  106. // Shroud
  107. // ----------------------------------------------------------------------------
  108. ShroudSetup Shroud
  109. <
  110. string UIWidget = "None";
  111. string SasBindAddress = "Terrain.Shroud";
  112. > = DEFAULT_SHROUD;
  113. SAMPLER_2D_BEGIN( ShroudTexture,
  114. string UIWidget = "None";
  115. string SasBindAddress = "Terrain.Shroud.Texture";
  116. )
  117. MinFilter = Linear;
  118. MagFilter = Linear;
  119. MipFilter = Linear;
  120. AddressU = Clamp;
  121. AddressV = Clamp;
  122. SAMPLER_2D_END
  123. // ----------------------------------------------------------------------------
  124. // WW3D defaults
  125. // ----------------------------------------------------------------------------
  126. #if !defined(USE_INDIRECT_CONSTANT)
  127. float OpacityOverride
  128. <
  129. string UIWidget = "None";
  130. string SasBindAddress = "WW3D.OpacityOverride";
  131. > = 1.0;
  132. #endif // #if !defined(USE_INDIRECT_CONSTANT)
  133. // ----------------------------------------------------------------------------
  134. // Transformations (world transformations are in skinning header)
  135. // ----------------------------------------------------------------------------
  136. #if defined(_WW3D_)
  137. #if !defined(USE_INDIRECT_CONSTANT)
  138. float4x4 ViewProjection
  139. <
  140. string UIWidget = "None";
  141. string SasBindAddress = "Sas.Camera.WorldToProjection";
  142. >;
  143. float3 EyePosition
  144. <
  145. string UIWidget = "None";
  146. string SasBindAddress = "Sas.Camera.Position";
  147. >;
  148. #endif // #if !defined(USE_INDIRECT_CONSTANT)
  149. float4x4 GetViewProjection()
  150. {
  151. return ViewProjection;
  152. }
  153. float3 GetEyePosition()
  154. {
  155. return EyePosition;
  156. }
  157. #else // #if defined(_WW3D_)
  158. float4x4 View : View;
  159. float4x3 ViewI : ViewInverse;
  160. float4x4 Projection : Projection;
  161. float4x4 GetViewProjection()
  162. {
  163. return mul(View, Projection);
  164. }
  165. float3 GetEyePosition()
  166. {
  167. return ViewI[3];
  168. }
  169. #endif // #if defined(_WW3D_)
  170. float Time : Time;
  171. // Helper function to modify the world position of a vertex with the tree swaying
  172. void ApplyTreeSway(inout float3 worldPosition, float swayStrength)
  173. {
  174. if (SwayEnable)
  175. {
  176. // add sin wave
  177. float2 Pos = frac(worldPosition.xy);
  178. float Amp = Amp1;
  179. float Phase = Phase1 * Time;
  180. float Freq = Freq1;
  181. float vDisp = sin(Pos * Freq + Phase) * Amp;
  182. worldPosition += vDisp * swayStrength;
  183. }
  184. }
  185. // ----------------------------------------------------------------------------
  186. // SHADER: DEFAULT
  187. // ----------------------------------------------------------------------------
  188. struct VSOutput
  189. {
  190. float4 Position : POSITION;
  191. float2 TexCoord0 : TEXCOORD0;
  192. float2 ShroudTexCoord : TEXCOORD1;
  193. float4 ShadowMapTexCoord : TEXCOORD2;
  194. float3 MainLightDiffuseColor : TEXCOORD3;
  195. float4 Color : COLOR0;
  196. float Fog : COLOR1;
  197. };
  198. // ----------------------------------------------------------------------------
  199. // SHADER: VS
  200. // ----------------------------------------------------------------------------
  201. VSOutput VS(VSInputSkinningOneBoneTangentFrame InSkin,
  202. float2 TexCoord : TEXCOORD0,
  203. float4 VertexColor : COLOR0,
  204. uniform int numJointsPerVertex,
  205. uniform bool usePointLights)
  206. {
  207. USE_DIRECTIONAL_LIGHT_INTERACTIVE(DirectionalLight, 0);
  208. VSOutput Out;
  209. float3 worldPosition = 0;
  210. float3 worldNormal = 0;
  211. float3 worldTangent = 0;
  212. float3 worldBinormal = 0;
  213. CalculatePositionAndTangentFrame(InSkin, numJointsPerVertex,
  214. worldPosition, worldNormal, worldTangent, worldBinormal);
  215. #if defined(_3DSMAX_)
  216. VertexColor.w = 1; //MAX cares nothing for vertex colors, allows basic displacement previewing in MAX
  217. #endif
  218. ApplyTreeSway(worldPosition, VertexColor.w);
  219. // Compute half direction between view and light direction in tangent space
  220. Out.Color = float4(AmbientLightColor * AmbientColor, OpacityOverride);
  221. // Compute all directional lights per vertex
  222. float3 diffuseLight = 0;
  223. diffuseLight = DirectionalLight[0].Color * max(0, dot(worldNormal, DirectionalLight[0].Direction));
  224. Out.MainLightDiffuseColor = diffuseLight * DiffuseColor;
  225. diffuseLight = 0;
  226. for (int i = 1; i < NumDirectionalLights; i++)
  227. {
  228. diffuseLight += DirectionalLight[i].Color * max(0, dot(worldNormal, DirectionalLight[i].Direction));
  229. }
  230. // Compute point lights
  231. if (usePointLights)
  232. {
  233. for (int i = 0; i < NumPointLights; i++)
  234. {
  235. diffuseLight += CalculatePointLightDiffuse(PointLight[i], worldPosition, worldNormal);
  236. }
  237. }
  238. Out.Color.xyz += diffuseLight * DiffuseColor;
  239. Out.Color /= 2; // Prevent clamping in interpolator
  240. // transform position to projection space
  241. Out.Position = mul(float4(worldPosition, 1), GetViewProjection());
  242. // pass texture coordinates for fetching the diffuse and agitator maps
  243. Out.TexCoord0 = TexCoord;
  244. Out.ShadowMapTexCoord = CalculateShadowMapTexCoord(worldPosition);
  245. Out.ShroudTexCoord = CalculateShroudTexCoord(Shroud, worldPosition);
  246. // Calculate fog
  247. Out.Fog = CalculateFog(Fog, worldPosition, GetEyePosition());
  248. return Out;
  249. }
  250. // ----------------------------------------------------------------------------
  251. // SHADER: PS
  252. // ----------------------------------------------------------------------------
  253. float4 PS(VSOutput In, uniform bool hasShadow, uniform bool applyGammaCorrection) COLORTARGET
  254. {
  255. // Get diffuse color
  256. float4 baseTexture = tex2D( SAMPLER(DiffuseTexture), In.TexCoord0);
  257. if (applyGammaCorrection)
  258. {
  259. baseTexture.xyz = GammaToLinear(baseTexture.xyz);
  260. }
  261. float4 color = In.Color * 2;
  262. float shadowAmount = 1.0;
  263. if (hasShadow)
  264. {
  265. shadowAmount = shadow( SAMPLER(ShadowMap), In.ShadowMapTexCoord);
  266. }
  267. color.xyz += In.MainLightDiffuseColor * shadowAmount;
  268. color *= baseTexture;
  269. #if defined(_WW3D_) && !defined(_W3DVIEW_)
  270. color.xyz *= tex2D(SAMPLER(ShroudTexture), In.ShroudTexCoord);
  271. #endif
  272. return CorrectForFrameBufferGamma(color);
  273. }
  274. // ----------------------------------------------------------------------------
  275. VSOutput VS_Xenon( VSInputSkinningOneBoneTangentFrame InSkin,
  276. float2 TexCoord : TEXCOORD0,
  277. float4 VertexColor : COLOR0)
  278. {
  279. return VS( InSkin, TexCoord, VertexColor, min(NumJointsPerVertex, 1), true );
  280. }
  281. // ----------------------------------------------------------------------------
  282. float4 PS_Xenon( VSOutput In ) : COLOR
  283. {
  284. return PS(In, HasShadow, true);
  285. }
  286. #if defined(EA_PLATFORM_PS3)
  287. // ----------------------------------------------------------------------------
  288. float4 PS_PS3( VSOutput In ) : COLOR
  289. {
  290. USE_DIRECTIONAL_LIGHT_INTERACTIVE(DirectionalLight, 0);
  291. // Get diffuse color
  292. float4 baseTexture = tex2D( SAMPLER(DiffuseTexture), In.TexCoord0);
  293. baseTexture *= tex2D(SAMPLER(ShroudTexture), In.ShroudTexCoord).x;
  294. return(baseTexture);
  295. }
  296. #endif // #if defined(EA_PLATFORM_PS3)
  297. // ----------------------------------------------------------------------------
  298. // Arrays: Default
  299. // ----------------------------------------------------------------------------
  300. DEFINE_ARRAY_MULTIPLIER( VS_Multiplier_Final = 2 );
  301. #define VS_NumJointsPerVertex \
  302. compile VS_2_0 VS(0, true), \
  303. compile VS_2_0 VS(1, true)
  304. #if SUPPORTS_SHADER_ARRAYS
  305. vertexshader VS_Array[VS_Multiplier_Final] =
  306. {
  307. VS_NumJointsPerVertex
  308. };
  309. #endif
  310. DEFINE_ARRAY_MULTIPLIER( PS_Multiplier_NumShadows = 1 );
  311. #define PS_NumShadows \
  312. compile PS_2_0 PS(0, true), \
  313. compile PS_2_0 PS(1, true)
  314. DEFINE_ARRAY_MULTIPLIER( PS_Multiplier_Final = PS_Multiplier_NumShadows * 2 );
  315. #if SUPPORTS_SHADER_ARRAYS
  316. pixelshader PS_Array[PS_Multiplier_Final] =
  317. {
  318. PS_NumShadows
  319. };
  320. #endif
  321. // ----------------------------------------------------------------------------
  322. // Technique: Default
  323. // ----------------------------------------------------------------------------
  324. technique Default
  325. {
  326. pass p0
  327. {
  328. VertexShader = ARRAY_EXPRESSION_VS( VS_Array,
  329. min(NumJointsPerVertex, 1),
  330. compile VS_VERSION VS_Xenon() );
  331. #if defined(EA_PLATFORM_PS3)
  332. PixelShader = ARRAY_EXPRESSION_PS( PS_Array,
  333. HasShadow * PS_Multiplier_NumShadows,
  334. compile PS_VERSION PS_PS3() );
  335. #else // #if defined(EA_PLATFORM_PS3)
  336. PixelShader = ARRAY_EXPRESSION_PS( PS_Array,
  337. HasShadow * PS_Multiplier_NumShadows,
  338. compile PS_VERSION PS_Xenon() );
  339. #endif // #if defined(EA_PLATFORM_PS3)
  340. ZEnable = true;
  341. ZFunc = ZFUNC_INFRONT;
  342. ZWriteEnable = true;
  343. CullMode = none;
  344. AlphaBlendEnable = false;
  345. AlphaTestEnable = true;
  346. AlphaFunc = GreaterEqual;
  347. AlphaRef = DEFAULT_ALPHATEST_THRESHOLD;
  348. }
  349. }
  350. #if ENABLE_LOD
  351. // ----------------------------------------------------------------------------
  352. // Arrays: Default (Medium LOD)
  353. // ----------------------------------------------------------------------------
  354. DEFINE_ARRAY_MULTIPLIER( VS_M_Multiplier_Final = 2 );
  355. #define VS_M_NumJointsPerVertex \
  356. compile VS_2_0 VS(0, false), \
  357. compile VS_2_0 VS(1, false)
  358. #if SUPPORTS_SHADER_ARRAYS
  359. vertexshader VS_M_Array[VS_M_Multiplier_Final] =
  360. {
  361. VS_M_NumJointsPerVertex
  362. };
  363. #endif
  364. DEFINE_ARRAY_MULTIPLIER( PS_M_Multiplier_NumShadows = 1 );
  365. #define PS_M_NumShadows \
  366. compile PS_2_0 PS(0, false), \
  367. compile PS_2_0 PS(1, false)
  368. DEFINE_ARRAY_MULTIPLIER( PS_M_Multiplier_Final = PS_M_Multiplier_NumShadows * 2 );
  369. #if SUPPORTS_SHADER_ARRAYS
  370. pixelshader PS_M_Array[PS_M_Multiplier_Final] =
  371. {
  372. PS_M_NumShadows
  373. };
  374. #endif
  375. // ----------------------------------------------------------------------------
  376. // Technique: Default (Medium LOD)
  377. // ----------------------------------------------------------------------------
  378. technique Default_M
  379. {
  380. pass p0
  381. {
  382. VertexShader = ARRAY_EXPRESSION_VS( VS_M_Array,
  383. min(NumJointsPerVertex, 1),
  384. NO_ARRAY_ALTERNATIVE);
  385. PixelShader = ARRAY_EXPRESSION_PS( PS_M_Array,
  386. HasShadow * PS_M_Multiplier_NumShadows,
  387. NO_ARRAY_ALTERNATIVE);
  388. ZEnable = true;
  389. ZFunc = ZFUNC_INFRONT;
  390. ZWriteEnable = true;
  391. CullMode = none;
  392. AlphaBlendEnable = false;
  393. AlphaTestEnable = true;
  394. AlphaFunc = GreaterEqual;
  395. AlphaRef = DEFAULT_ALPHATEST_THRESHOLD;
  396. }
  397. }
  398. #endif // ENABLE_LOD
  399. // ----------------------------------------------------------------------------
  400. // SHADER: CreateShadowMapVS
  401. // ----------------------------------------------------------------------------
  402. struct VSOutput_CreateShadowMap
  403. {
  404. float4 Position : POSITION;
  405. float2 TexCoord0 : TEXCOORD0;
  406. float Depth : TEXCOORD1;
  407. };
  408. // ----------------------------------------------------------------------------
  409. VSOutput_CreateShadowMap CreateShadowMapVS(VSInputSkinningOneBoneTangentFrame InSkin,
  410. float2 TexCoord : TEXCOORD0,
  411. float4 VertexColor : COLOR0,
  412. uniform int numJointsPerVertex)
  413. {
  414. VSOutput_CreateShadowMap Out;
  415. float3 worldPosition = 0;
  416. float3 worldNormal = 0;
  417. float3 worldTangent = 0;
  418. float3 worldBinormal = 0;
  419. CalculatePositionAndTangentFrame(InSkin, numJointsPerVertex,
  420. worldPosition, worldNormal, worldTangent, worldBinormal);
  421. ApplyTreeSway(worldPosition, VertexColor.w);
  422. // Transform position to projection space
  423. Out.Position = mul(float4(worldPosition, 1), GetViewProjection());
  424. Out.Depth = Out.Position.z / Out.Position.w;
  425. Out.TexCoord0 = TexCoord;
  426. return Out;
  427. }
  428. // ----------------------------------------------------------------------------
  429. float4 CreateShadowMapPS(VSOutput_CreateShadowMap In) : COLOR
  430. {
  431. float opacity = OpacityOverride * tex2D(SAMPLER(DiffuseTexture), In.TexCoord0).w;
  432. // Simulate alpha testing for floating point render target
  433. clip(opacity - ((float)DEFAULT_ALPHATEST_THRESHOLD / 255));
  434. return In.Depth;
  435. }
  436. // ----------------------------------------------------------------------------
  437. VSOutput_CreateShadowMap CreateShadowMapVS_Xenon(VSInputSkinningOneBoneTangentFrame InSkin,
  438. float2 TexCoord : TEXCOORD0,
  439. float4 VertexColor : COLOR0)
  440. {
  441. return CreateShadowMapVS( InSkin, TexCoord, VertexColor, min(NumJointsPerVertex, 1) );
  442. }
  443. // ----------------------------------------------------------------------------
  444. // Technique _CreateShadowMap
  445. // ----------------------------------------------------------------------------
  446. DEFINE_ARRAY_MULTIPLIER( VSCreateShadowMap_Multiplier_Final = 2 );
  447. #define VSCreateShadowMap_NumJointsPerVertex \
  448. compile VS_2_0 CreateShadowMapVS(0), \
  449. compile VS_2_0 CreateShadowMapVS(1)
  450. #if SUPPORTS_SHADER_ARRAYS
  451. vertexshader VSCreateShadowMap_Array[VSCreateShadowMap_Multiplier_Final] =
  452. {
  453. VSCreateShadowMap_NumJointsPerVertex
  454. };
  455. #endif
  456. // ----------------------------------------------------------------------------
  457. technique _CreateShadowMap
  458. {
  459. pass p0
  460. {
  461. VertexShader = ARRAY_EXPRESSION_VS( VSCreateShadowMap_Array,
  462. min(NumJointsPerVertex, 1),
  463. compile VS_VERSION CreateShadowMapVS_Xenon() );
  464. PixelShader = compile PS_2_0 CreateShadowMapPS();
  465. ZEnable = true;
  466. ZFunc = ZFUNC_INFRONT;
  467. ZWriteEnable = true;
  468. CullMode = none;
  469. AlphaBlendEnable = false;
  470. AlphaTestEnable = false;
  471. }
  472. }