kritoa

SpeedTree.shader

Aug 4th, 2017
102
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
  2.  
  3. Shader "Nature/SpeedTree"
  4. {
  5. Properties
  6. {
  7. _Color ("Main Color", Color) = (1,1,1,1)
  8. _HueVariation ("Hue Variation", Color) = (1.0,0.5,0.0,0.1)
  9. _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
  10. _DetailTex ("Detail", 2D) = "black" {}
  11. _BumpMap ("Normal Map", 2D) = "bump" {}
  12. _Cutoff ("Alpha Cutoff", Range(0,1)) = 0.333
  13. [MaterialEnum(Off,0,Front,1,Back,2)] _Cull ("Cull", Int) = 2
  14. [MaterialEnum(None,0,Fastest,1,Fast,2,Better,3,Best,4,Palm,5)] _WindQuality ("Wind Quality", Range(0,5)) = 0
  15. }
  16.  
  17. // targeting SM3.0+
  18. SubShader
  19. {
  20. Tags
  21. {
  22. "Queue"="Geometry"
  23. "IgnoreProjector"="True"
  24. "RenderType"="Opaque"
  25. "DisableBatching"="LODFading"
  26. }
  27. LOD 400
  28. Cull [_Cull]
  29.  
  30. CGPROGRAM
  31. #pragma surface surf Lambert vertex:SpeedTreeVertKritoa nodirlightmap nodynlightmap noshadowmask
  32. #pragma target 3.0
  33. #pragma multi_compile __ LOD_FADE_PERCENTAGE LOD_FADE_CROSSFADE
  34. #pragma instancing_options assumeuniformscaling lodfade maxcount:50
  35. #pragma shader_feature GEOM_TYPE_BRANCH GEOM_TYPE_BRANCH_DETAIL GEOM_TYPE_FROND GEOM_TYPE_LEAF GEOM_TYPE_MESH
  36. #pragma shader_feature EFFECT_BUMP
  37. #pragma shader_feature EFFECT_HUE_VARIATION
  38. #define ENABLE_WIND
  39. #include "SpeedTreeCommon.cginc"
  40.  
  41. void OffsetSpeedTreeVertexKritoa(inout SpeedTreeVB data, float lodValue)
  42. {
  43. float3 finalPosition = data.vertex.xyz;
  44.  
  45. #ifdef ENABLE_WIND
  46. half windQuality = _WindQuality * _WindEnabled;
  47.  
  48. float3 rotatedWindVector, rotatedBranchAnchor;
  49. if (windQuality <= WIND_QUALITY_NONE)
  50. {
  51. rotatedWindVector = float3(0.0f, 0.0f, 0.0f);
  52. rotatedBranchAnchor = float3(0.0f, 0.0f, 0.0f);
  53. }
  54. else
  55. {
  56. // compute rotated wind parameters
  57. rotatedWindVector = normalize(mul(_ST_WindVector.xyz, (float3x3)unity_ObjectToWorld));
  58. rotatedBranchAnchor = normalize(mul(_ST_WindBranchAnchor.xyz, (float3x3)unity_ObjectToWorld)) * _ST_WindBranchAnchor.w;
  59. }
  60. #endif
  61.  
  62. #if defined(GEOM_TYPE_BRANCH) || defined(GEOM_TYPE_FROND)
  63.  
  64. // smooth LOD
  65. #ifdef LOD_FADE_PERCENTAGE
  66. finalPosition = lerp(finalPosition, data.texcoord1.xyz, lodValue);
  67. #endif
  68.  
  69. // frond wind, if needed
  70. #if defined(ENABLE_WIND) && defined(GEOM_TYPE_FROND)
  71. if (windQuality == WIND_QUALITY_PALM)
  72. finalPosition = RippleFrond(finalPosition, data.normal, data.texcoord.x, data.texcoord.y, data.texcoord2.x, data.texcoord2.y, data.texcoord2.z);
  73. #endif
  74.  
  75. #elif defined(GEOM_TYPE_LEAF)
  76.  
  77. // remove anchor position
  78. finalPosition -= data.texcoord1.xyz;
  79.  
  80. bool isFacingLeaf = data.color.a == 0;
  81. if (isFacingLeaf)
  82. {
  83. #ifdef LOD_FADE_PERCENTAGE
  84. finalPosition *= lerp(1.0, data.texcoord1.w, lodValue);
  85. #endif
  86.  
  87. // face camera-facing leaf to camera
  88. // float offsetLen = length(finalPosition);
  89. // finalPosition = mul(finalPosition.xyz, (float3x3)UNITY_MATRIX_IT_MV); // inv(MV) * finalPosition // old camera facing (orients to view matrix, bad!!)
  90.  
  91. // KRITOA: can't get this to work - somebody help
  92.  
  93. // orient to camera position with up vector instead now
  94. // float3 camPos = _WorldSpaceCameraPos.xyz;
  95. // float3 objectOrigin = data.texcoord1.xyz; //mul(unity_ObjectToWorld, float3(0,0,0));
  96. // float3 objectForward = normalize(camPos-objectOrigin);
  97. // float3 objectRight = normalize(cross(float3(0,1,0),objectForward));
  98. // float3 objectUp = normalize(cross(objectForward,objectRight));
  99. // finalPosition = mul(float3x3(objectRight, objectUp, objectForward),finalPosition.xyz);
  100. // finalPosition = mul(finalPosition.xyz,float3x3(objectRight.x, objectUp.x, objectForward.x,
  101. // objectRight.y, objectUp.y, objectForward.y,
  102. // objectRight.z, objectUp.z, objectForward.z));
  103. // finalPosition = mul(float3x3(objectRight.x, objectUp.x, objectForward.x,
  104. // objectRight.y, objectUp.y, objectForward.y,
  105. // objectRight.z, objectUp.z, objectForward.z),
  106. // finalPosition.xyz);
  107. // finalPosition = mul(finalPosition.xyz,float3x3(objectRight.x, objectRight.y, objectRight.z,
  108. // objectUp.x, objectUp.y, objectUp.z,
  109. // objectForward.x, objectForward.y, objectForward.z));
  110. // finalPosition = mul(float3x3(objectRight.x, objectRight.y, objectRight.z,
  111. // objectUp.x, objectUp.y, objectUp.z,
  112. // objectForward.x, objectForward.y, objectForward.z),
  113. // finalPosition.xyz);
  114.  
  115. // finalPosition = normalize(finalPosition) * offsetLen; // make sure the offset vector is still scaled
  116. }
  117. else
  118. {
  119. #ifdef LOD_FADE_PERCENTAGE
  120. float3 lodPosition = float3(data.texcoord1.w, data.texcoord3.x, data.texcoord3.y);
  121. finalPosition = lerp(finalPosition, lodPosition, lodValue);
  122. #endif
  123. }
  124.  
  125. #ifdef ENABLE_WIND
  126. // leaf wind
  127. if (windQuality > WIND_QUALITY_FASTEST && windQuality < WIND_QUALITY_PALM)
  128. {
  129. float leafWindTrigOffset = data.texcoord1.x + data.texcoord1.y;
  130. finalPosition = LeafWind(windQuality == WIND_QUALITY_BEST, data.texcoord2.w > 0.0, finalPosition, data.normal, data.texcoord2.x, float3(0,0,0), data.texcoord2.y, data.texcoord2.z, leafWindTrigOffset, rotatedWindVector);
  131. }
  132. #endif
  133.  
  134. // move back out to anchor
  135. finalPosition += data.texcoord1.xyz;
  136.  
  137. #endif
  138.  
  139. #ifdef ENABLE_WIND
  140. float3 treePos = float3(unity_ObjectToWorld[0].w, unity_ObjectToWorld[1].w, unity_ObjectToWorld[2].w);
  141.  
  142. #ifndef GEOM_TYPE_MESH
  143. if (windQuality >= WIND_QUALITY_BETTER)
  144. {
  145. // branch wind (applies to all 3D geometry)
  146. finalPosition = BranchWind(windQuality == WIND_QUALITY_PALM, finalPosition, treePos, float4(data.texcoord.zw, 0, 0), rotatedWindVector, rotatedBranchAnchor);
  147. }
  148. #endif
  149.  
  150. if (windQuality > WIND_QUALITY_NONE)
  151. {
  152. // global wind
  153. finalPosition = GlobalWind(finalPosition, treePos, true, rotatedWindVector, _ST_WindGlobal.x);
  154. }
  155. #endif
  156.  
  157. data.vertex.xyz = finalPosition;
  158. }
  159.  
  160. void SpeedTreeVertKritoa(inout SpeedTreeVB IN, out Input OUT)
  161. {
  162. UNITY_INITIALIZE_OUTPUT(Input, OUT);
  163.  
  164. OUT.mainTexUV = IN.texcoord.xy;
  165. OUT.color = _Color;
  166. OUT.color.rgb *= IN.color.r; // ambient occlusion factor
  167.  
  168. #ifdef EFFECT_HUE_VARIATION
  169. float hueVariationAmount = frac(unity_ObjectToWorld[0].w + unity_ObjectToWorld[1].w + unity_ObjectToWorld[2].w);
  170. hueVariationAmount += frac(IN.vertex.x + IN.normal.y + IN.normal.x) * 0.5 - 0.3;
  171. OUT.HueVariationAmount = saturate(hueVariationAmount * _HueVariation.a);
  172. #endif
  173.  
  174. #ifdef GEOM_TYPE_BRANCH_DETAIL
  175. // The two types are always in different sub-range of the mesh so no interpolation (between detail and blend) problem.
  176. OUT.Detail.xy = IN.texcoord2.xy;
  177. if (IN.color.a == 0) // Blend
  178. OUT.Detail.z = IN.texcoord2.z;
  179. else // Detail texture
  180. OUT.Detail.z = 2.5f; // stay out of Blend's .z range
  181. #endif
  182.  
  183. OffsetSpeedTreeVertexKritoa(IN, unity_LODFade.x);
  184.  
  185. UNITY_TRANSFER_DITHER_CROSSFADE(OUT, IN.vertex)
  186. }
  187.  
  188.  
  189. void surf(Input IN, inout SurfaceOutput OUT)
  190. {
  191. SpeedTreeFragOut o;
  192. SpeedTreeFrag(IN, o);
  193. SPEEDTREE_COPY_FRAG(OUT, o)
  194. }
  195. ENDCG
  196.  
  197. Pass
  198. {
  199. Tags { "LightMode" = "ShadowCaster" }
  200.  
  201. CGPROGRAM
  202. #pragma vertex vert
  203. #pragma fragment frag
  204. #pragma target 3.0
  205. #pragma multi_compile __ LOD_FADE_PERCENTAGE LOD_FADE_CROSSFADE
  206. #pragma multi_compile_instancing
  207. #pragma instancing_options assumeuniformscaling lodfade maxcount:50
  208. #pragma shader_feature GEOM_TYPE_BRANCH GEOM_TYPE_BRANCH_DETAIL GEOM_TYPE_FROND GEOM_TYPE_LEAF GEOM_TYPE_MESH
  209. #pragma multi_compile_shadowcaster
  210. #define ENABLE_WIND
  211. #include "SpeedTreeCommon.cginc"
  212.  
  213. void OffsetSpeedTreeVertexKritoa(inout SpeedTreeVB data, float lodValue)
  214. {
  215. float3 finalPosition = data.vertex.xyz;
  216.  
  217. #ifdef ENABLE_WIND
  218. half windQuality = _WindQuality * _WindEnabled;
  219.  
  220. float3 rotatedWindVector, rotatedBranchAnchor;
  221. if (windQuality <= WIND_QUALITY_NONE)
  222. {
  223. rotatedWindVector = float3(0.0f, 0.0f, 0.0f);
  224. rotatedBranchAnchor = float3(0.0f, 0.0f, 0.0f);
  225. }
  226. else
  227. {
  228. // compute rotated wind parameters
  229. rotatedWindVector = normalize(mul(_ST_WindVector.xyz, (float3x3)unity_ObjectToWorld));
  230. rotatedBranchAnchor = normalize(mul(_ST_WindBranchAnchor.xyz, (float3x3)unity_ObjectToWorld)) * _ST_WindBranchAnchor.w;
  231. }
  232. #endif
  233.  
  234. #if defined(GEOM_TYPE_BRANCH) || defined(GEOM_TYPE_FROND)
  235.  
  236. // smooth LOD
  237. #ifdef LOD_FADE_PERCENTAGE
  238. finalPosition = lerp(finalPosition, data.texcoord1.xyz, lodValue);
  239. #endif
  240.  
  241. // frond wind, if needed
  242. #if defined(ENABLE_WIND) && defined(GEOM_TYPE_FROND)
  243. if (windQuality == WIND_QUALITY_PALM)
  244. finalPosition = RippleFrond(finalPosition, data.normal, data.texcoord.x, data.texcoord.y, data.texcoord2.x, data.texcoord2.y, data.texcoord2.z);
  245. #endif
  246.  
  247. #elif defined(GEOM_TYPE_LEAF)
  248.  
  249. // remove anchor position
  250. finalPosition -= data.texcoord1.xyz;
  251.  
  252. bool isFacingLeaf = data.color.a == 0;
  253. if (isFacingLeaf)
  254. {
  255. #ifdef LOD_FADE_PERCENTAGE
  256. finalPosition *= lerp(1.0, data.texcoord1.w, lodValue);
  257. #endif
  258.  
  259. // face camera-facing leaf to camera
  260. // float offsetLen = length(finalPosition);
  261. // finalPosition = mul(finalPosition.xyz, (float3x3)UNITY_MATRIX_IT_MV); // inv(MV) * finalPosition // old camera facing (orients to view matrix, bad!)
  262.  
  263. //KRITOA: can't get this to work. Somebody help.
  264.  
  265. // orient to camera position with up vector instead now
  266. // float3 camPos = _WorldSpaceCameraPos.xyz;
  267. // float3 objectOrigin = data.texcoord1.xyz; //mul(unity_ObjectToWorld, float3(0,0,0));
  268. // float3 objectForward = normalize(camPos-objectOrigin);
  269. // float3 objectRight = normalize(cross(float3(0,1,0),objectForward));
  270. // float3 objectUp = normalize(cross(objectForward,objectRight));
  271. // finalPosition = mul(float3x3(objectRight, objectUp, objectForward),finalPosition.xyz);
  272. // finalPosition = mul(finalPosition.xyz,float3x3(objectRight.x, objectUp.x, objectForward.x,
  273. // objectRight.y, objectUp.y, objectForward.y,
  274. // objectRight.z, objectUp.z, objectForward.z));
  275. // finalPosition = mul(float3x3(objectRight.x, objectUp.x, objectForward.x,
  276. // objectRight.y, objectUp.y, objectForward.y,
  277. // objectRight.z, objectUp.z, objectForward.z),
  278. // finalPosition.xyz);
  279. // finalPosition = mul(finalPosition.xyz,float3x3(objectRight.x, objectRight.y, objectRight.z,
  280. // objectUp.x, objectUp.y, objectUp.z,
  281. // objectForward.x, objectForward.y, objectForward.z));
  282. // finalPosition = mul(float3x3(objectRight.x, objectRight.y, objectRight.z,
  283. // objectUp.x, objectUp.y, objectUp.z,
  284. // objectForward.x, objectForward.y, objectForward.z),
  285. // finalPosition.xyz);
  286.  
  287. // finalPosition = normalize(finalPosition) * offsetLen; // make sure the offset vector is still scaled
  288. }
  289. else
  290. {
  291. #ifdef LOD_FADE_PERCENTAGE
  292. float3 lodPosition = float3(data.texcoord1.w, data.texcoord3.x, data.texcoord3.y);
  293. finalPosition = lerp(finalPosition, lodPosition, lodValue);
  294. #endif
  295. }
  296.  
  297. #ifdef ENABLE_WIND
  298. // leaf wind
  299. if (windQuality > WIND_QUALITY_FASTEST && windQuality < WIND_QUALITY_PALM)
  300. {
  301. float leafWindTrigOffset = data.texcoord1.x + data.texcoord1.y;
  302. finalPosition = LeafWind(windQuality == WIND_QUALITY_BEST, data.texcoord2.w > 0.0, finalPosition, data.normal, data.texcoord2.x, float3(0,0,0), data.texcoord2.y, data.texcoord2.z, leafWindTrigOffset, rotatedWindVector);
  303. }
  304. #endif
  305.  
  306. // move back out to anchor
  307. finalPosition += data.texcoord1.xyz;
  308.  
  309. #endif
  310.  
  311. #ifdef ENABLE_WIND
  312. float3 treePos = float3(unity_ObjectToWorld[0].w, unity_ObjectToWorld[1].w, unity_ObjectToWorld[2].w);
  313.  
  314. #ifndef GEOM_TYPE_MESH
  315. if (windQuality >= WIND_QUALITY_BETTER)
  316. {
  317. // branch wind (applies to all 3D geometry)
  318. finalPosition = BranchWind(windQuality == WIND_QUALITY_PALM, finalPosition, treePos, float4(data.texcoord.zw, 0, 0), rotatedWindVector, rotatedBranchAnchor);
  319. }
  320. #endif
  321.  
  322. if (windQuality > WIND_QUALITY_NONE)
  323. {
  324. // global wind
  325. finalPosition = GlobalWind(finalPosition, treePos, true, rotatedWindVector, _ST_WindGlobal.x);
  326. }
  327. #endif
  328.  
  329. data.vertex.xyz = finalPosition;
  330. }
  331.  
  332. void SpeedTreeVertKritoa(inout SpeedTreeVB IN, out Input OUT)
  333. {
  334. UNITY_INITIALIZE_OUTPUT(Input, OUT);
  335.  
  336. OUT.mainTexUV = IN.texcoord.xy;
  337. OUT.color = _Color;
  338. OUT.color.rgb *= IN.color.r; // ambient occlusion factor
  339.  
  340. #ifdef EFFECT_HUE_VARIATION
  341. float hueVariationAmount = frac(unity_ObjectToWorld[0].w + unity_ObjectToWorld[1].w + unity_ObjectToWorld[2].w);
  342. hueVariationAmount += frac(IN.vertex.x + IN.normal.y + IN.normal.x) * 0.5 - 0.3;
  343. OUT.HueVariationAmount = saturate(hueVariationAmount * _HueVariation.a);
  344. #endif
  345.  
  346. #ifdef GEOM_TYPE_BRANCH_DETAIL
  347. // The two types are always in different sub-range of the mesh so no interpolation (between detail and blend) problem.
  348. OUT.Detail.xy = IN.texcoord2.xy;
  349. if (IN.color.a == 0) // Blend
  350. OUT.Detail.z = IN.texcoord2.z;
  351. else // Detail texture
  352. OUT.Detail.z = 2.5f; // stay out of Blend's .z range
  353. #endif
  354.  
  355. OffsetSpeedTreeVertexKritoa(IN, unity_LODFade.x);
  356.  
  357. UNITY_TRANSFER_DITHER_CROSSFADE(OUT, IN.vertex)
  358. }
  359.  
  360.  
  361. struct v2f
  362. {
  363. V2F_SHADOW_CASTER;
  364. #ifdef SPEEDTREE_ALPHATEST
  365. float2 uv : TEXCOORD1;
  366. #endif
  367. UNITY_DITHER_CROSSFADE_COORDS_IDX(2)
  368. UNITY_VERTEX_INPUT_INSTANCE_ID
  369. UNITY_VERTEX_OUTPUT_STEREO
  370. };
  371.  
  372. v2f vert(SpeedTreeVB v)
  373. {
  374. v2f o;
  375. UNITY_SETUP_INSTANCE_ID(v);
  376. UNITY_TRANSFER_INSTANCE_ID(v, o);
  377. UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
  378. #ifdef SPEEDTREE_ALPHATEST
  379. o.uv = v.texcoord.xy;
  380. #endif
  381. OffsetSpeedTreeVertexKritoa(v, unity_LODFade.x);
  382. TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
  383. UNITY_TRANSFER_DITHER_CROSSFADE_HPOS(o, o.pos)
  384.  
  385. return o;
  386. }
  387.  
  388. float4 frag(v2f i) : SV_Target
  389. {
  390. UNITY_SETUP_INSTANCE_ID(i);
  391. #ifdef SPEEDTREE_ALPHATEST
  392. clip(tex2D(_MainTex, i.uv).a * _Color.a - _Cutoff);
  393. #endif
  394. UNITY_APPLY_DITHER_CROSSFADE(i)
  395. SHADOW_CASTER_FRAGMENT(i)
  396. }
  397. ENDCG
  398. }
  399.  
  400. Pass
  401. {
  402. Tags { "LightMode" = "Vertex" }
  403.  
  404. CGPROGRAM
  405. #pragma vertex vert
  406. #pragma fragment frag
  407. #pragma target 3.0
  408. #pragma multi_compile_fog
  409. #pragma multi_compile __ LOD_FADE_PERCENTAGE LOD_FADE_CROSSFADE
  410. #pragma multi_compile_instancing
  411. #pragma instancing_options assumeuniformscaling lodfade maxcount:50
  412. #pragma shader_feature GEOM_TYPE_BRANCH GEOM_TYPE_BRANCH_DETAIL GEOM_TYPE_FROND GEOM_TYPE_LEAF GEOM_TYPE_MESH
  413. #pragma shader_feature EFFECT_HUE_VARIATION
  414. #define ENABLE_WIND
  415. #include "SpeedTreeCommon.cginc"
  416.  
  417. struct v2f
  418. {
  419. float4 vertex : SV_POSITION;
  420. UNITY_FOG_COORDS(0)
  421. Input data : TEXCOORD1;
  422. UNITY_VERTEX_INPUT_INSTANCE_ID
  423. UNITY_VERTEX_OUTPUT_STEREO
  424. };
  425.  
  426. v2f vert(SpeedTreeVB v)
  427. {
  428. v2f o;
  429. UNITY_SETUP_INSTANCE_ID(v);
  430. UNITY_TRANSFER_INSTANCE_ID(v, o);
  431. UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
  432. SpeedTreeVert(v, o.data);
  433. o.data.color.rgb *= ShadeVertexLightsFull(v.vertex, v.normal, 4, true);
  434. o.vertex = UnityObjectToClipPos(v.vertex);
  435. UNITY_TRANSFER_FOG(o,o.vertex);
  436. return o;
  437. }
  438.  
  439. fixed4 frag(v2f i) : SV_Target
  440. {
  441. UNITY_SETUP_INSTANCE_ID(i);
  442. SpeedTreeFragOut o;
  443. SpeedTreeFrag(i.data, o);
  444. fixed4 c = fixed4(o.Albedo, o.Alpha);
  445. UNITY_APPLY_FOG(i.fogCoord, c);
  446. return c;
  447. }
  448. ENDCG
  449. }
  450. }
  451.  
  452. // targeting SM2.0: Cross-fading, Normal-mapping, Hue variation and Wind animation are turned off for less instructions
  453. SubShader
  454. {
  455. Tags
  456. {
  457. "Queue"="Geometry"
  458. "IgnoreProjector"="True"
  459. "RenderType"="Opaque"
  460. "DisableBatching"="LODFading"
  461. }
  462. LOD 400
  463. Cull [_Cull]
  464.  
  465. CGPROGRAM
  466. #pragma surface surf Lambert vertex:SpeedTreeVertKritoa nodirlightmap nodynlightmap noshadowmask
  467. #pragma multi_compile __ LOD_FADE_PERCENTAGE
  468. #pragma shader_feature GEOM_TYPE_BRANCH GEOM_TYPE_BRANCH_DETAIL GEOM_TYPE_FROND GEOM_TYPE_LEAF GEOM_TYPE_MESH
  469. #include "SpeedTreeCommon.cginc"
  470.  
  471. void OffsetSpeedTreeVertexKritoa(inout SpeedTreeVB data, float lodValue)
  472. {
  473. float3 finalPosition = data.vertex.xyz;
  474.  
  475. #ifdef ENABLE_WIND
  476. half windQuality = _WindQuality * _WindEnabled;
  477.  
  478. float3 rotatedWindVector, rotatedBranchAnchor;
  479. if (windQuality <= WIND_QUALITY_NONE)
  480. {
  481. rotatedWindVector = float3(0.0f, 0.0f, 0.0f);
  482. rotatedBranchAnchor = float3(0.0f, 0.0f, 0.0f);
  483. }
  484. else
  485. {
  486. // compute rotated wind parameters
  487. rotatedWindVector = normalize(mul(_ST_WindVector.xyz, (float3x3)unity_ObjectToWorld));
  488. rotatedBranchAnchor = normalize(mul(_ST_WindBranchAnchor.xyz, (float3x3)unity_ObjectToWorld)) * _ST_WindBranchAnchor.w;
  489. }
  490. #endif
  491.  
  492. #if defined(GEOM_TYPE_BRANCH) || defined(GEOM_TYPE_FROND)
  493.  
  494. // smooth LOD
  495. #ifdef LOD_FADE_PERCENTAGE
  496. finalPosition = lerp(finalPosition, data.texcoord1.xyz, lodValue);
  497. #endif
  498.  
  499. // frond wind, if needed
  500. #if defined(ENABLE_WIND) && defined(GEOM_TYPE_FROND)
  501. if (windQuality == WIND_QUALITY_PALM)
  502. finalPosition = RippleFrond(finalPosition, data.normal, data.texcoord.x, data.texcoord.y, data.texcoord2.x, data.texcoord2.y, data.texcoord2.z);
  503. #endif
  504.  
  505. #elif defined(GEOM_TYPE_LEAF)
  506.  
  507. // remove anchor position
  508. finalPosition -= data.texcoord1.xyz;
  509.  
  510. bool isFacingLeaf = data.color.a == 0;
  511. if (isFacingLeaf)
  512. {
  513. #ifdef LOD_FADE_PERCENTAGE
  514. finalPosition *= lerp(1.0, data.texcoord1.w, lodValue);
  515. #endif
  516.  
  517. // face camera-facing leaf to camera
  518. // float offsetLen = length(finalPosition);
  519. // finalPosition = mul(finalPosition.xyz, (float3x3)UNITY_MATRIX_IT_MV); // inv(MV) * finalPosition // old camera facing (orients to view matrix, bad!)
  520.  
  521. // KRITOA: can't get this to work. Somebody help.
  522.  
  523. // orient to camera position with up vector instead now
  524. // float3 camPos = _WorldSpaceCameraPos.xyz;
  525. // float3 objectOrigin = data.texcoord1.xyz; //mul(unity_ObjectToWorld, float3(0,0,0));
  526. // float3 objectForward = normalize(camPos-objectOrigin);
  527. // float3 objectRight = normalize(cross(float3(0,1,0),objectForward));
  528. // float3 objectUp = normalize(cross(objectForward,objectRight));
  529. // finalPosition = mul(float3x3(objectRight, objectUp, objectForward),finalPosition.xyz);
  530. // finalPosition = mul(finalPosition.xyz,float3x3(objectRight.x, objectUp.x, objectForward.x,
  531. // objectRight.y, objectUp.y, objectForward.y,
  532. // objectRight.z, objectUp.z, objectForward.z));
  533. // finalPosition = mul(float3x3(objectRight.x, objectUp.x, objectForward.x,
  534. // objectRight.y, objectUp.y, objectForward.y,
  535. // objectRight.z, objectUp.z, objectForward.z),
  536. // finalPosition.xyz);
  537. // finalPosition = mul(finalPosition.xyz,float3x3(objectRight.x, objectRight.y, objectRight.z,
  538. // objectUp.x, objectUp.y, objectUp.z,
  539. // objectForward.x, objectForward.y, objectForward.z));
  540. // finalPosition = mul(float3x3(objectRight.x, objectRight.y, objectRight.z,
  541. // objectUp.x, objectUp.y, objectUp.z,
  542. // objectForward.x, objectForward.y, objectForward.z),
  543. // finalPosition.xyz);
  544.  
  545. // finalPosition = normalize(finalPosition) * offsetLen; // make sure the offset vector is still scaled
  546. }
  547. else
  548. {
  549. #ifdef LOD_FADE_PERCENTAGE
  550. float3 lodPosition = float3(data.texcoord1.w, data.texcoord3.x, data.texcoord3.y);
  551. finalPosition = lerp(finalPosition, lodPosition, lodValue);
  552. #endif
  553. }
  554.  
  555. #ifdef ENABLE_WIND
  556. // leaf wind
  557. if (windQuality > WIND_QUALITY_FASTEST && windQuality < WIND_QUALITY_PALM)
  558. {
  559. float leafWindTrigOffset = data.texcoord1.x + data.texcoord1.y;
  560. finalPosition = LeafWind(windQuality == WIND_QUALITY_BEST, data.texcoord2.w > 0.0, finalPosition, data.normal, data.texcoord2.x, float3(0,0,0), data.texcoord2.y, data.texcoord2.z, leafWindTrigOffset, rotatedWindVector);
  561. }
  562. #endif
  563.  
  564. // move back out to anchor
  565. finalPosition += data.texcoord1.xyz;
  566.  
  567. #endif
  568.  
  569. #ifdef ENABLE_WIND
  570. float3 treePos = float3(unity_ObjectToWorld[0].w, unity_ObjectToWorld[1].w, unity_ObjectToWorld[2].w);
  571.  
  572. #ifndef GEOM_TYPE_MESH
  573. if (windQuality >= WIND_QUALITY_BETTER)
  574. {
  575. // branch wind (applies to all 3D geometry)
  576. finalPosition = BranchWind(windQuality == WIND_QUALITY_PALM, finalPosition, treePos, float4(data.texcoord.zw, 0, 0), rotatedWindVector, rotatedBranchAnchor);
  577. }
  578. #endif
  579.  
  580. if (windQuality > WIND_QUALITY_NONE)
  581. {
  582. // global wind
  583. finalPosition = GlobalWind(finalPosition, treePos, true, rotatedWindVector, _ST_WindGlobal.x);
  584. }
  585. #endif
  586.  
  587. data.vertex.xyz = finalPosition;
  588. }
  589.  
  590. void SpeedTreeVertKritoa(inout SpeedTreeVB IN, out Input OUT)
  591. {
  592. UNITY_INITIALIZE_OUTPUT(Input, OUT);
  593.  
  594. OUT.mainTexUV = IN.texcoord.xy;
  595. OUT.color = _Color;
  596. OUT.color.rgb *= IN.color.r; // ambient occlusion factor
  597.  
  598. #ifdef EFFECT_HUE_VARIATION
  599. float hueVariationAmount = frac(unity_ObjectToWorld[0].w + unity_ObjectToWorld[1].w + unity_ObjectToWorld[2].w);
  600. hueVariationAmount += frac(IN.vertex.x + IN.normal.y + IN.normal.x) * 0.5 - 0.3;
  601. OUT.HueVariationAmount = saturate(hueVariationAmount * _HueVariation.a);
  602. #endif
  603.  
  604. #ifdef GEOM_TYPE_BRANCH_DETAIL
  605. // The two types are always in different sub-range of the mesh so no interpolation (between detail and blend) problem.
  606. OUT.Detail.xy = IN.texcoord2.xy;
  607. if (IN.color.a == 0) // Blend
  608. OUT.Detail.z = IN.texcoord2.z;
  609. else // Detail texture
  610. OUT.Detail.z = 2.5f; // stay out of Blend's .z range
  611. #endif
  612.  
  613. OffsetSpeedTreeVertexKritoa(IN, unity_LODFade.x);
  614.  
  615. UNITY_TRANSFER_DITHER_CROSSFADE(OUT, IN.vertex)
  616. }
  617.  
  618. void surf(Input IN, inout SurfaceOutput OUT)
  619. {
  620. SpeedTreeFragOut o;
  621. SpeedTreeFrag(IN, o);
  622. SPEEDTREE_COPY_FRAG(OUT, o)
  623. }
  624. ENDCG
  625.  
  626. Pass
  627. {
  628. Tags { "LightMode" = "ShadowCaster" }
  629.  
  630. CGPROGRAM
  631. #pragma vertex vert
  632. #pragma fragment frag
  633. #pragma multi_compile __ LOD_FADE_PERCENTAGE
  634. #pragma shader_feature GEOM_TYPE_BRANCH GEOM_TYPE_BRANCH_DETAIL GEOM_TYPE_FROND GEOM_TYPE_LEAF GEOM_TYPE_MESH
  635. #pragma multi_compile_shadowcaster
  636. #include "SpeedTreeCommon.cginc"
  637.  
  638. void OffsetSpeedTreeVertexKritoa(inout SpeedTreeVB data, float lodValue)
  639. {
  640. float3 finalPosition = data.vertex.xyz;
  641.  
  642. #ifdef ENABLE_WIND
  643. half windQuality = _WindQuality * _WindEnabled;
  644.  
  645. float3 rotatedWindVector, rotatedBranchAnchor;
  646. if (windQuality <= WIND_QUALITY_NONE)
  647. {
  648. rotatedWindVector = float3(0.0f, 0.0f, 0.0f);
  649. rotatedBranchAnchor = float3(0.0f, 0.0f, 0.0f);
  650. }
  651. else
  652. {
  653. // compute rotated wind parameters
  654. rotatedWindVector = normalize(mul(_ST_WindVector.xyz, (float3x3)unity_ObjectToWorld));
  655. rotatedBranchAnchor = normalize(mul(_ST_WindBranchAnchor.xyz, (float3x3)unity_ObjectToWorld)) * _ST_WindBranchAnchor.w;
  656. }
  657. #endif
  658.  
  659. #if defined(GEOM_TYPE_BRANCH) || defined(GEOM_TYPE_FROND)
  660.  
  661. // smooth LOD
  662. #ifdef LOD_FADE_PERCENTAGE
  663. finalPosition = lerp(finalPosition, data.texcoord1.xyz, lodValue);
  664. #endif
  665.  
  666. // frond wind, if needed
  667. #if defined(ENABLE_WIND) && defined(GEOM_TYPE_FROND)
  668. if (windQuality == WIND_QUALITY_PALM)
  669. finalPosition = RippleFrond(finalPosition, data.normal, data.texcoord.x, data.texcoord.y, data.texcoord2.x, data.texcoord2.y, data.texcoord2.z);
  670. #endif
  671.  
  672. #elif defined(GEOM_TYPE_LEAF)
  673.  
  674. // remove anchor position
  675. finalPosition -= data.texcoord1.xyz;
  676.  
  677. bool isFacingLeaf = data.color.a == 0;
  678. if (isFacingLeaf)
  679. {
  680. #ifdef LOD_FADE_PERCENTAGE
  681. finalPosition *= lerp(1.0, data.texcoord1.w, lodValue);
  682. #endif
  683.  
  684. // face camera-facing leaf to camera
  685. // float offsetLen = length(finalPosition);
  686. // finalPosition = mul(finalPosition.xyz, (float3x3)UNITY_MATRIX_IT_MV); // inv(MV) * finalPosition // old camera facing (orients to view matrix, bad!)
  687.  
  688. //KRITOA: Can't get this to work. Somebody help.
  689.  
  690. // orient to camera position with up vector instead now
  691. // float3 camPos = _WorldSpaceCameraPos.xyz;
  692. // float3 objectOrigin = data.texcoord1.xyz; //mul(unity_ObjectToWorld, float3(0,0,0));
  693. // float3 objectForward = normalize(camPos-objectOrigin);
  694. // float3 objectRight = normalize(cross(float3(0,1,0),objectForward));
  695. // float3 objectUp = normalize(cross(objectForward,objectRight));
  696. // finalPosition = mul(float3x3(objectRight, objectUp, objectForward),finalPosition.xyz);
  697. // finalPosition = mul(finalPosition.xyz,float3x3(objectRight.x, objectUp.x, objectForward.x,
  698. // objectRight.y, objectUp.y, objectForward.y,
  699. // objectRight.z, objectUp.z, objectForward.z));
  700. // finalPosition = mul(float3x3(objectRight.x, objectUp.x, objectForward.x,
  701. // objectRight.y, objectUp.y, objectForward.y,
  702. // objectRight.z, objectUp.z, objectForward.z),
  703. // finalPosition.xyz);
  704. // finalPosition = mul(finalPosition.xyz,float3x3(objectRight.x, objectRight.y, objectRight.z,
  705. // objectUp.x, objectUp.y, objectUp.z,
  706. // objectForward.x, objectForward.y, objectForward.z));
  707. // finalPosition = mul(float3x3(objectRight.x, objectRight.y, objectRight.z,
  708. // objectUp.x, objectUp.y, objectUp.z,
  709. // objectForward.x, objectForward.y, objectForward.z),
  710. // finalPosition.xyz);
  711.  
  712. // finalPosition = normalize(finalPosition) * offsetLen; // make sure the offset vector is still scaled
  713. }
  714. else
  715. {
  716. #ifdef LOD_FADE_PERCENTAGE
  717. float3 lodPosition = float3(data.texcoord1.w, data.texcoord3.x, data.texcoord3.y);
  718. finalPosition = lerp(finalPosition, lodPosition, lodValue);
  719. #endif
  720. }
  721.  
  722. #ifdef ENABLE_WIND
  723. // leaf wind
  724. if (windQuality > WIND_QUALITY_FASTEST && windQuality < WIND_QUALITY_PALM)
  725. {
  726. float leafWindTrigOffset = data.texcoord1.x + data.texcoord1.y;
  727. finalPosition = LeafWind(windQuality == WIND_QUALITY_BEST, data.texcoord2.w > 0.0, finalPosition, data.normal, data.texcoord2.x, float3(0,0,0), data.texcoord2.y, data.texcoord2.z, leafWindTrigOffset, rotatedWindVector);
  728. }
  729. #endif
  730.  
  731. // move back out to anchor
  732. finalPosition += data.texcoord1.xyz;
  733.  
  734. #endif
  735.  
  736. #ifdef ENABLE_WIND
  737. float3 treePos = float3(unity_ObjectToWorld[0].w, unity_ObjectToWorld[1].w, unity_ObjectToWorld[2].w);
  738.  
  739. #ifndef GEOM_TYPE_MESH
  740. if (windQuality >= WIND_QUALITY_BETTER)
  741. {
  742. // branch wind (applies to all 3D geometry)
  743. finalPosition = BranchWind(windQuality == WIND_QUALITY_PALM, finalPosition, treePos, float4(data.texcoord.zw, 0, 0), rotatedWindVector, rotatedBranchAnchor);
  744. }
  745. #endif
  746.  
  747. if (windQuality > WIND_QUALITY_NONE)
  748. {
  749. // global wind
  750. finalPosition = GlobalWind(finalPosition, treePos, true, rotatedWindVector, _ST_WindGlobal.x);
  751. }
  752. #endif
  753.  
  754. data.vertex.xyz = finalPosition;
  755. }
  756.  
  757. void SpeedTreeVertKritoa(inout SpeedTreeVB IN, out Input OUT)
  758. {
  759. UNITY_INITIALIZE_OUTPUT(Input, OUT);
  760.  
  761. OUT.mainTexUV = IN.texcoord.xy;
  762. OUT.color = _Color;
  763. OUT.color.rgb *= IN.color.r; // ambient occlusion factor
  764.  
  765. #ifdef EFFECT_HUE_VARIATION
  766. float hueVariationAmount = frac(unity_ObjectToWorld[0].w + unity_ObjectToWorld[1].w + unity_ObjectToWorld[2].w);
  767. hueVariationAmount += frac(IN.vertex.x + IN.normal.y + IN.normal.x) * 0.5 - 0.3;
  768. OUT.HueVariationAmount = saturate(hueVariationAmount * _HueVariation.a);
  769. #endif
  770.  
  771. #ifdef GEOM_TYPE_BRANCH_DETAIL
  772. // The two types are always in different sub-range of the mesh so no interpolation (between detail and blend) problem.
  773. OUT.Detail.xy = IN.texcoord2.xy;
  774. if (IN.color.a == 0) // Blend
  775. OUT.Detail.z = IN.texcoord2.z;
  776. else // Detail texture
  777. OUT.Detail.z = 2.5f; // stay out of Blend's .z range
  778. #endif
  779.  
  780. OffsetSpeedTreeVertexKritoa(IN, unity_LODFade.x);
  781.  
  782. UNITY_TRANSFER_DITHER_CROSSFADE(OUT, IN.vertex)
  783. }
  784.  
  785. struct v2f
  786. {
  787. V2F_SHADOW_CASTER;
  788. #ifdef SPEEDTREE_ALPHATEST
  789. float2 uv : TEXCOORD1;
  790. #endif
  791. };
  792.  
  793. v2f vert(SpeedTreeVB v)
  794. {
  795. v2f o;
  796. #ifdef SPEEDTREE_ALPHATEST
  797. o.uv = v.texcoord.xy;
  798. #endif
  799. OffsetSpeedTreeVertexKritoa(v, unity_LODFade.x);
  800. TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
  801. return o;
  802. }
  803.  
  804. float4 frag(v2f i) : SV_Target
  805. {
  806. #ifdef SPEEDTREE_ALPHATEST
  807. clip(tex2D(_MainTex, i.uv).a * _Color.a - _Cutoff);
  808. #endif
  809. SHADOW_CASTER_FRAGMENT(i)
  810. }
  811. ENDCG
  812. }
  813.  
  814. Pass
  815. {
  816. Tags { "LightMode" = "Vertex" }
  817.  
  818. CGPROGRAM
  819. #pragma vertex vert
  820. #pragma fragment frag
  821. #pragma multi_compile_fog
  822. #pragma multi_compile __ LOD_FADE_PERCENTAGE
  823. #pragma shader_feature GEOM_TYPE_BRANCH GEOM_TYPE_BRANCH_DETAIL GEOM_TYPE_FROND GEOM_TYPE_LEAF GEOM_TYPE_MESH
  824. #include "SpeedTreeCommon.cginc"
  825.  
  826. struct v2f
  827. {
  828. float4 vertex : SV_POSITION;
  829. UNITY_FOG_COORDS(0)
  830. Input data : TEXCOORD1;
  831. UNITY_VERTEX_OUTPUT_STEREO
  832. };
  833.  
  834. v2f vert(SpeedTreeVB v)
  835. {
  836. v2f o;
  837. UNITY_SETUP_INSTANCE_ID(v);
  838. UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
  839. SpeedTreeVert(v, o.data);
  840. o.data.color.rgb *= ShadeVertexLightsFull(v.vertex, v.normal, 2, false);
  841. o.vertex = UnityObjectToClipPos(v.vertex);
  842. UNITY_TRANSFER_FOG(o,o.vertex);
  843. return o;
  844. }
  845.  
  846. fixed4 frag(v2f i) : SV_Target
  847. {
  848. SpeedTreeFragOut o;
  849. SpeedTreeFrag(i.data, o);
  850. fixed4 c = fixed4(o.Albedo, o.Alpha);
  851. UNITY_APPLY_FOG(i.fogCoord, c);
  852. return c;
  853. }
  854. ENDCG
  855. }
  856. }
  857.  
  858. FallBack "Transparent/Cutout/VertexLit"
  859. CustomEditor "SpeedTreeMaterialInspector"
  860. }
RAW Paste Data