VoronoiNode.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  1. // Amplify Shader Editor - Visual Shader Editing Tool
  2. // Copyright (c) Amplify Creations, Lda <info@amplify.pt>
  3. using System;
  4. using UnityEditor;
  5. using UnityEngine;
  6. namespace AmplifyShaderEditor
  7. {
  8. [Serializable]
  9. [NodeAttributes( "Voronoi", "Miscellaneous", "Voronoi", Tags = "noise" )]
  10. public sealed class VoronoiNode : ParentNode
  11. {
  12. // Unity Voronoi
  13. private readonly string UnityVoronoiNoiseFunc = "UnityVoronoi({0},{1},{2},{3})";
  14. private readonly string[] UnityVoroniNoiseFunctionsBody =
  15. {
  16. "inline float2 UnityVoronoiRandomVector( float2 UV, float offset )\n",
  17. "{\n",
  18. "\tfloat2x2 m = float2x2( 15.27, 47.63, 99.41, 89.98 );\n",
  19. "\tUV = frac( sin(mul(UV, m) ) * 46839.32 );\n",
  20. "\treturn float2( sin(UV.y* +offset ) * 0.5 + 0.5, cos( UV.x* offset ) * 0.5 + 0.5 );\n",
  21. "}\n",
  22. "\n",
  23. "//x - Out y - Cells\n",
  24. "float3 UnityVoronoi( float2 UV, float AngleOffset, float CellDensity, inout float2 mr )\n",
  25. "{\n",
  26. "\tfloat2 g = floor( UV * CellDensity );\n",
  27. "\tfloat2 f = frac( UV * CellDensity );\n",
  28. "\tfloat t = 8.0;\n",
  29. "\tfloat3 res = float3( 8.0, 0.0, 0.0 );\n",
  30. "\n",
  31. "\tfor( int y = -1; y <= 1; y++ )\n",
  32. "\t{\n",
  33. "\t for( int x = -1; x <= 1; x++ )\n",
  34. "\t {\n",
  35. "\t\t\tfloat2 lattice = float2( x, y );\n",
  36. "\t\t\tfloat2 offset = UnityVoronoiRandomVector( lattice + g, AngleOffset );\n",
  37. "\t\t\tfloat d = distance( lattice + offset, f );\n",
  38. "\n",
  39. "\t\t\tif( d < res.x )\n",
  40. "\t\t\t{\n",
  41. "\t\t\t\tmr = f - lattice - offset;\n",
  42. "\t\t\t\tres = float3( d, offset.x, offset.y );\n",
  43. "\t\t\t}\n",
  44. "\t }\n",
  45. "\t}\n",
  46. "\treturn res;\n",
  47. "}\n",
  48. };
  49. ////////////
  50. private const string VoronoiHashHeader = "float2 voronoihash{0}( float2 p )";
  51. private readonly string[] VoronoiHashBody = { "p = p - 2 * floor( p / 2 );",
  52. "p = float2( dot( p, float2( 127.1, 311.7 ) ), dot( p, float2( 269.5, 183.3 ) ) );",
  53. "return frac( sin( p ) *43758.5453);" };
  54. private const string VoronoiHeader = "float voronoi{0}( float2 v, float time, inout float2 id, inout float2 mr, float smoothness, inout float2 smoothId )";
  55. private const string VoronoiFunc = "voronoi{0}( {1}, {2}, {3}, {4}, {5}, {6} )";
  56. private string[] VoronoiBody =
  57. {
  58. "float2 n = floor( v );",
  59. "float2 f = frac( v );",
  60. "float F1 = 8.0;",
  61. "float F2 = 8.0; float2 mg = 0;",
  62. "for ( int j = -1; j <= 1; j++ )",
  63. "{",
  64. " \tfor ( int i = -1; i <= 1; i++ )",
  65. " \t{",
  66. " \t\tfloat2 g = float2( i, j );",
  67. " \t\tfloat2 o = voronoihash{0}( n + g );",
  68. " \t\tfloat2 r = f - g - ( sin( 0 + o * 6.2831 ) * 0.5 + 0.5 );",
  69. " \t\tfloat d = dot( r, r );",
  70. " \t\tif( d<F1 ) {",//12
  71. " \t\t\tF2 = F1;",//13
  72. " \t\t\tF1 = d; mg = g; mr = r; id = o;",//14
  73. " \t\t} else if( d<F2 ) {",//15
  74. " \t\t\tF2 = d;",//16
  75. "",//this is where we inject smooth Id
  76. " \t\t}" ,//18
  77. " \t}",
  78. "}",
  79. "return F1;"
  80. };
  81. private string VoronoiDistanceBody =
  82. "\nF1 = 8.0;" +
  83. "\nfor ( int j = -2; j <= 2; j++ )" +
  84. "\n{{" +
  85. "\nfor ( int i = -2; i <= 2; i++ )" +
  86. "\n{{" +
  87. "\nfloat2 g = mg + float2( i, j );" +
  88. "\nfloat2 o = voronoihash{1}( n + g );" +
  89. "\n{0}" +
  90. "\nfloat d = dot( 0.5 * ( r + mr ), normalize( r - mr ) );" +
  91. "\nF1 = min( F1, d );" +
  92. "\n}}" +
  93. "\n}}" +
  94. "\nreturn F1;";
  95. [SerializeField]
  96. private int m_distanceFunction = 0;
  97. [SerializeField]
  98. private float m_minkowskiPower = 1;
  99. [SerializeField]
  100. private int m_functionType = 0;
  101. [SerializeField]
  102. private int m_octaves = 1;
  103. [SerializeField]
  104. private bool m_tileable = false;
  105. [SerializeField]
  106. private int m_tileScale = 1;
  107. [SerializeField]
  108. private bool m_useUnity = false;
  109. [SerializeField]
  110. private bool m_calculateSmoothValue = false;
  111. [SerializeField]
  112. private bool m_applySmoothToIds = false;
  113. private const string FunctionTypeStr = "Method";//"Function Type";
  114. private readonly string[] m_functionTypeStr = { "Cells", "Crystal", "Glass", "Caustic", "Distance" };
  115. private const string DistanceFunctionLabelStr = "Distance Function";
  116. private readonly string[] m_distanceFunctionStr = { "Euclidean\u00B2", "Euclidean", "Manhattan", "Chebyshev", "Minkowski" };
  117. [SerializeField]
  118. private int m_searchQuality = 0;
  119. private const string SearchQualityLabelStr = "Search Quality";
  120. private readonly string[] m_searchQualityStr = { "9 Cells", "25 Cells", "49 Cells" };
  121. private const string UseTileScaleStr = "_UseTileScale";
  122. private const string TileScaleStr = "_TileScale";
  123. private const string MinkowskiPowerStr = "_MinkowskiPower";
  124. private const string DistFuncStr = "_DistFunc";
  125. private const string MethodTypeStr = "_MethodType";
  126. private const string SearchQualityStr = "_SearchQuality";
  127. private const string OctavesStr = "_Octaves";
  128. private const string UseSmoothnessStr = "_UseSmoothness";
  129. private int m_UseTileScaleId;
  130. private int m_TileScaleId;
  131. private int m_MinkowskiPowerId;
  132. private int m_DistFuncId;
  133. private int m_MethodTypeId;
  134. private int m_SearchQualityId;
  135. private int m_OctavesId;
  136. private int m_UseSmoothnessId;
  137. private int m_cachedUvsId = -1;
  138. protected override void CommonInit( int uniqueId )
  139. {
  140. base.CommonInit( uniqueId );
  141. AddInputPort( WirePortDataType.FLOAT2, false, "UV" );
  142. AddInputPort( WirePortDataType.FLOAT, false, "Angle" );
  143. AddInputPort( WirePortDataType.FLOAT, false, "Scale" );
  144. AddInputPort( WirePortDataType.FLOAT, false, "Smoothness" );
  145. m_inputPorts[ 1 ].AutoDrawInternalData = true;
  146. m_inputPorts[ 2 ].AutoDrawInternalData = true;
  147. m_inputPorts[ 2 ].FloatInternalData = 1;
  148. AddOutputPort( WirePortDataType.FLOAT, "Out" );
  149. AddOutputPort( WirePortDataType.FLOAT2, "ID" );
  150. AddOutputPort( WirePortDataType.FLOAT2, "UV" );
  151. m_textLabelWidth = 120;
  152. //m_useInternalPortData = true;
  153. m_autoWrapProperties = true;
  154. m_previewShaderGUID = "bc1498ccdade442479038b24982fc946";
  155. ChangePorts();
  156. ChechSmoothPorts();
  157. }
  158. void ChechSmoothPorts()
  159. {
  160. m_inputPorts[ 3 ].Visible = !m_useUnity && m_calculateSmoothValue && (m_functionType == 0) ;
  161. m_sizeIsDirty = true;
  162. }
  163. void ChangePorts()
  164. {
  165. m_previewMaterialPassId = 0;
  166. }
  167. public override void OnEnable()
  168. {
  169. base.OnEnable();
  170. m_UseTileScaleId = Shader.PropertyToID( UseTileScaleStr );
  171. m_TileScaleId = Shader.PropertyToID( TileScaleStr );
  172. m_MinkowskiPowerId = Shader.PropertyToID( MinkowskiPowerStr );
  173. m_DistFuncId = Shader.PropertyToID( DistFuncStr );
  174. m_MethodTypeId = Shader.PropertyToID( MethodTypeStr );
  175. m_SearchQualityId = Shader.PropertyToID( SearchQualityStr );
  176. m_OctavesId = Shader.PropertyToID( OctavesStr );
  177. m_UseSmoothnessId = Shader.PropertyToID( UseSmoothnessStr );
  178. }
  179. public override void SetPreviewInputs()
  180. {
  181. base.SetPreviewInputs();
  182. if( m_cachedUvsId == -1 )
  183. m_cachedUvsId = Shader.PropertyToID( "_CustomUVs" );
  184. PreviewMaterial.SetInt( m_cachedUvsId, ( m_inputPorts[ 0 ].IsConnected ? 1 : 0 ) );
  185. m_previewMaterialPassId = m_useUnity ? 0 : 1;
  186. if( !m_useUnity )
  187. {
  188. PreviewMaterial.SetInt( m_SearchQualityId, m_searchQuality + 1 );
  189. if( m_functionType == 4)
  190. {
  191. PreviewMaterial.SetInt( m_DistFuncId, 0 );
  192. } else
  193. {
  194. PreviewMaterial.SetInt( m_DistFuncId, m_distanceFunction );
  195. }
  196. if( m_distanceFunction == 4 )
  197. {
  198. PreviewMaterial.SetFloat( m_MinkowskiPowerId, m_minkowskiPower );
  199. }
  200. PreviewMaterial.SetInt( m_MethodTypeId, m_functionType );
  201. int smoothnessValue = m_calculateSmoothValue ? 1 : 0;
  202. PreviewMaterial.SetInt( m_UseSmoothnessId, smoothnessValue );
  203. PreviewMaterial.SetFloat( m_UseTileScaleId, m_tileable ? 1.0f : 0.0f );
  204. if( m_tileable )
  205. PreviewMaterial.SetInt( m_TileScaleId, m_tileScale );
  206. PreviewMaterial.SetInt( m_OctavesId, m_octaves );
  207. }
  208. }
  209. public override void RenderNodePreview()
  210. {
  211. //Runs at least one time
  212. if( !m_initialized )
  213. {
  214. // nodes with no preview don't update at all
  215. PreviewIsDirty = false;
  216. return;
  217. }
  218. if( !PreviewIsDirty )
  219. return;
  220. SetPreviewInputs();
  221. if( !Preferences.User.DisablePreviews )
  222. {
  223. RenderTexture temp = RenderTexture.active;
  224. RenderTexture.active = m_outputPorts[ 0 ].OutputPreviewTexture;
  225. PreviewMaterial.SetInt( "_PreviewID" , 0 );
  226. Graphics.Blit( null , m_outputPorts[ 0 ].OutputPreviewTexture , PreviewMaterial , m_previewMaterialPassId );
  227. RenderTexture.active = m_outputPorts[ 1 ].OutputPreviewTexture;
  228. PreviewMaterial.SetInt( "_PreviewID" , 1 );
  229. Graphics.Blit( null , m_outputPorts[ 1 ].OutputPreviewTexture , PreviewMaterial , m_previewMaterialPassId );
  230. RenderTexture.active = m_outputPorts[ 2 ].OutputPreviewTexture;
  231. PreviewMaterial.SetInt( "_PreviewID" , 2 );
  232. Graphics.Blit( null , m_outputPorts[ 2 ].OutputPreviewTexture , PreviewMaterial , m_previewMaterialPassId );
  233. RenderTexture.active = temp;
  234. }
  235. PreviewIsDirty = m_continuousPreviewRefresh;
  236. FinishPreviewRender = true;
  237. }
  238. public override void DrawProperties()
  239. {
  240. base.DrawProperties();
  241. EditorGUI.BeginChangeCheck();
  242. {
  243. EditorGUI.BeginDisabledGroup( m_useUnity );
  244. {
  245. EditorGUI.BeginChangeCheck();
  246. m_functionType = EditorGUILayoutPopup( FunctionTypeStr, m_functionType, m_functionTypeStr );
  247. if( EditorGUI.EndChangeCheck() )
  248. {
  249. ChechSmoothPorts();
  250. }
  251. EditorGUI.BeginDisabledGroup( m_functionType == 4 );
  252. m_distanceFunction = EditorGUILayoutPopup( DistanceFunctionLabelStr, m_distanceFunction, m_distanceFunctionStr );
  253. if( m_distanceFunction == 4 )
  254. {
  255. m_minkowskiPower = EditorGUILayoutSlider( "Minkowski Power", m_minkowskiPower, 1, 5 );
  256. }
  257. EditorGUI.EndDisabledGroup();
  258. m_searchQuality = EditorGUILayoutPopup( SearchQualityLabelStr, m_searchQuality, m_searchQualityStr );
  259. m_octaves = EditorGUILayoutIntSlider( "Octaves", m_octaves, 1, 8 );
  260. m_tileable = EditorGUILayoutToggle( "Tileable", m_tileable );
  261. EditorGUI.BeginDisabledGroup( !m_tileable );
  262. m_tileScale = EditorGUILayoutIntField( "Tile Scale", m_tileScale );
  263. EditorGUI.EndDisabledGroup();
  264. //Only smoothing cells type for now
  265. if( m_functionType == 0 )
  266. {
  267. EditorGUI.BeginChangeCheck();
  268. m_calculateSmoothValue = EditorGUILayoutToggle( "Smooth", m_calculateSmoothValue );
  269. if( EditorGUI.EndChangeCheck() )
  270. {
  271. ChechSmoothPorts();
  272. }
  273. if( m_calculateSmoothValue )
  274. {
  275. m_applySmoothToIds = EditorGUILayoutToggle( " Apply To ID" , m_applySmoothToIds );
  276. }
  277. }
  278. }
  279. EditorGUI.EndDisabledGroup();
  280. EditorGUI.BeginChangeCheck();
  281. m_useUnity = EditorGUILayoutToggle( "Unity's Voronoi", m_useUnity );
  282. if( EditorGUI.EndChangeCheck() )
  283. {
  284. ChangePorts();
  285. ChechSmoothPorts();
  286. }
  287. }
  288. if( EditorGUI.EndChangeCheck() )
  289. {
  290. PreviewIsDirty = true;
  291. }
  292. NodeUtils.DrawPropertyGroup( ref m_internalDataFoldout, Constants.InternalDataLabelStr, () =>
  293. {
  294. for( int i = 0; i < m_inputPorts.Count; i++ )
  295. {
  296. if( m_inputPorts[ i ].ValidInternalData && !m_inputPorts[ i ].IsConnected && m_inputPorts[ i ].Visible && m_inputPorts[ i ].AutoDrawInternalData )
  297. {
  298. m_inputPorts[ i ].ShowInternalData( this );
  299. }
  300. }
  301. } );
  302. }
  303. void ChangeFunction( string scale )
  304. {
  305. VoronoiBody[ 10 ] = "\t\to = ( sin( time + o * 6.2831 ) * 0.5 + 0.5 ); float2 r = f - g - o;";
  306. int q = m_searchQuality + 1;
  307. VoronoiBody[ 4 ] = "for ( int j = -" + q + "; j <= " + q + "; j++ )";
  308. VoronoiBody[ 6 ] = "\tfor ( int i = -" + q + "; i <= " + q + "; i++ )";
  309. int dFunction = m_distanceFunction;
  310. if( m_functionType == 4 )
  311. dFunction = 0;
  312. switch( dFunction )
  313. {
  314. default:
  315. case 0:
  316. VoronoiBody[ 11 ] = "\t\tfloat d = 0.5 * dot( r, r );";
  317. break;
  318. case 1:
  319. VoronoiBody[ 11 ] = "\t\tfloat d = 0.707 * sqrt(dot( r, r ));";
  320. break;
  321. case 2:
  322. VoronoiBody[ 11 ] = "\t\tfloat d = 0.5 * ( abs(r.x) + abs(r.y) );";
  323. break;
  324. case 3:
  325. VoronoiBody[ 11 ] = "\t\tfloat d = max(abs(r.x), abs(r.y));";
  326. break;
  327. case 4:
  328. VoronoiBody[ 11 ] = "\t\tfloat d = " + ( 1 / Mathf.Pow( 2, 1 / m_minkowskiPower ) ).ToString( "n3" ) + " * pow( ( pow( abs( r.x ), " + m_minkowskiPower + " ) + pow( abs( r.y ), " + m_minkowskiPower + " ) ), " + ( 1 / m_minkowskiPower ).ToString( "n3" ) + " );";
  329. break;
  330. }
  331. if( m_functionType == 0 )
  332. {
  333. if( m_calculateSmoothValue )
  334. {
  335. VoronoiBody[ 12 ] = " //\t\tif( d<F1 ) {";
  336. VoronoiBody[ 13 ] = " //\t\t\tF2 = F1;";
  337. VoronoiBody[ 14 ] = " \t\t\tfloat h = smoothstep(0.0, 1.0, 0.5 + 0.5 * (F1 - d) / smoothness); F1 = lerp(F1, d, h) - smoothness * h * (1.0 - h);mg = g; mr = r; id = o;";
  338. VoronoiBody[ 15 ] = " //\t\t} else if( d<F2 ) {";
  339. VoronoiBody[ 16 ] = " //\t\t\tF2 = d;";
  340. VoronoiBody[ 17 ] = m_applySmoothToIds? "\t\t\tfloat correctionFactor = smoothness * h * (1.0f - h) / ( 1.0f + 3.0f * smoothness ); smoothId = lerp( smoothId,id, h ) - correctionFactor;":string.Empty;
  341. VoronoiBody[ 18 ] = " //\t\t}";
  342. }
  343. else
  344. {
  345. VoronoiBody[ 12 ] = " \t\tif( d<F1 ) {";
  346. VoronoiBody[ 13 ] = " \t\t\tF2 = F1;";
  347. VoronoiBody[ 14 ] = " \t\t\tF1 = d; mg = g; mr = r; id = o;";
  348. VoronoiBody[ 15 ] = " \t\t} else if( d<F2 ) {";
  349. VoronoiBody[ 16 ] = " \t\t\tF2 = d;";
  350. VoronoiBody[ 17 ] = string.Empty;
  351. VoronoiBody[ 18 ] = " \t\t}";
  352. }
  353. }
  354. else
  355. {
  356. VoronoiBody[ 12 ] = " \t\tif( d<F1 ) {";
  357. VoronoiBody[ 13 ] = " \t\t\tF2 = F1;";
  358. VoronoiBody[ 14 ] = " \t\t\tF1 = d; mg = g; mr = r; id = o;";
  359. VoronoiBody[ 15 ] = " \t\t} else if( d<F2 ) {";
  360. VoronoiBody[ 16 ] = " \t\t\tF2 = d;";
  361. VoronoiBody[ 17 ] = string.Empty;
  362. VoronoiBody[ 18 ] = " \t\t}";
  363. }
  364. switch( m_functionType )
  365. {
  366. default:
  367. case 0:
  368. VoronoiBody[ 21 ] = "return F1;";
  369. break;
  370. case 1:
  371. VoronoiBody[ 21 ] = "return F2;";
  372. break;
  373. case 2:
  374. VoronoiBody[ 21 ] = "return F2 - F1;";
  375. break;
  376. case 3:
  377. VoronoiBody[ 21 ] = "return (F2 + F1) * 0.5;";
  378. break;
  379. case 4:
  380. VoronoiBody[ 21 ] = string.Format( VoronoiDistanceBody , VoronoiBody[ 10 ], OutputId );
  381. break;
  382. }
  383. if( m_tileable )
  384. {
  385. VoronoiHashBody[ 0 ] = "p = p - " + m_tileScale + " * floor( p / " + m_tileScale + " );";
  386. }
  387. else
  388. {
  389. VoronoiHashBody[ 0 ] = "";
  390. }
  391. }
  392. public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar )
  393. {
  394. if( m_outputPorts[ outputId ].IsLocalValue( dataCollector.PortCategory ) )
  395. {
  396. return m_outputPorts[ outputId ].LocalValue( dataCollector.PortCategory );
  397. }
  398. if( m_useUnity )
  399. {
  400. string uvValue = string.Empty;
  401. if( m_inputPorts[ 0 ].IsConnected )
  402. uvValue = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector );
  403. else
  404. {
  405. if( dataCollector.IsTemplate )
  406. uvValue = dataCollector.TemplateDataCollectorInstance.GenerateAutoUVs( 0 );
  407. else
  408. uvValue = GeneratorUtils.GenerateAutoUVs( ref dataCollector, UniqueId, 0 );
  409. }
  410. string angleOffset = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector );
  411. string cellDensity = m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector );
  412. dataCollector.AddLocalVariable( UniqueId, string.Format( "float2 uv{0} = 0;", OutputId ) );
  413. dataCollector.AddFunction( UnityVoroniNoiseFunctionsBody[ 0 ], UnityVoroniNoiseFunctionsBody, false );
  414. string varName = "unityVoronoy" + OutputId;
  415. string varValue = string.Format( UnityVoronoiNoiseFunc, uvValue, angleOffset, cellDensity, "uv" + OutputId );
  416. dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT3, varName, varValue );
  417. m_outputPorts[ 0 ].SetLocalValue( varName + ".x", dataCollector.PortCategory );
  418. m_outputPorts[ 1 ].SetLocalValue( varName + ".yz", dataCollector.PortCategory );
  419. m_outputPorts[ 2 ].SetLocalValue( "uv" + OutputId, dataCollector.PortCategory );
  420. return m_outputPorts[ outputId ].LocalValue( dataCollector.PortCategory );
  421. }
  422. else
  423. {
  424. string scaleValue = m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector );
  425. string timeVarValue = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector );
  426. string timeVarName = "time" + OutputId;
  427. dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT, timeVarName, timeVarValue );
  428. ChangeFunction( scaleValue );
  429. string voronoiHashFunc = string.Empty;
  430. string VoronoiHashHeaderFormatted = string.Format( VoronoiHashHeader, OutputId );
  431. IOUtils.AddFunctionHeader( ref voronoiHashFunc, VoronoiHashHeaderFormatted );
  432. for( int i = 0; i < VoronoiHashBody.Length; i++ )
  433. {
  434. IOUtils.AddFunctionLine( ref voronoiHashFunc, VoronoiHashBody[ i ] );
  435. }
  436. IOUtils.CloseFunctionBody( ref voronoiHashFunc );
  437. dataCollector.AddFunction( VoronoiHashHeaderFormatted, voronoiHashFunc );
  438. string smoothnessName = "0";
  439. //need to add a local value to send to function since its an inout and sending a numeric value to it generates a compilation error
  440. string smoothIdName = "voronoiSmoothId" + OutputId;
  441. dataCollector.AddLocalVariable( UniqueId , CurrentPrecisionType , WirePortDataType.FLOAT2 , smoothIdName , "0" );
  442. if( m_calculateSmoothValue )
  443. {
  444. smoothnessName = "voronoiSmooth" + OutputId;
  445. string smoothnessValue = m_inputPorts[ 3 ].GeneratePortInstructions( ref dataCollector );
  446. dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT, smoothnessName, smoothnessValue );
  447. }
  448. string voronoiFunc = string.Empty;
  449. IOUtils.AddFunctionHeader( ref voronoiFunc, string.Format( VoronoiHeader, OutputId ) );
  450. for( int i = 0; i < VoronoiBody.Length; i++ )
  451. {
  452. if( i == 9 )
  453. {
  454. IOUtils.AddFunctionLine( ref voronoiFunc, string.Format( VoronoiBody[ i ],OutputId ) );
  455. }
  456. else
  457. {
  458. IOUtils.AddFunctionLine( ref voronoiFunc, VoronoiBody[ i ] );
  459. }
  460. }
  461. IOUtils.CloseFunctionBody( ref voronoiFunc );
  462. dataCollector.AddFunction( string.Format( VoronoiHeader, OutputId ), voronoiFunc );
  463. string uvs = string.Empty;
  464. if( m_inputPorts[ 0 ].IsConnected )
  465. uvs = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector );
  466. else
  467. {
  468. if( dataCollector.IsTemplate )
  469. {
  470. uvs = dataCollector.TemplateDataCollectorInstance.GenerateAutoUVs( 0 );
  471. }
  472. else
  473. {
  474. uvs = GeneratorUtils.GenerateAutoUVs( ref dataCollector, UniqueId, 0 );
  475. }
  476. }
  477. dataCollector.AddLocalVariable( UniqueId, string.Format( "float2 coords{0} = {1} * {2};", OutputId, uvs, scaleValue ) );
  478. dataCollector.AddLocalVariable( UniqueId, string.Format( "float2 id{0} = 0;", OutputId ) );
  479. dataCollector.AddLocalVariable( UniqueId, string.Format( "float2 uv{0} = 0;", OutputId ) );
  480. if( m_octaves == 1 )
  481. {
  482. dataCollector.AddLocalVariable( UniqueId, string.Format( "float voroi{0} = {1};", OutputId, string.Format( VoronoiFunc, OutputId, "coords" + OutputId,timeVarName, "id"+ OutputId, "uv" + OutputId, smoothnessName , smoothIdName ) ) );
  483. }
  484. else
  485. {
  486. dataCollector.AddLocalVariable( UniqueId, string.Format( "float fade{0} = 0.5;", OutputId ) );
  487. dataCollector.AddLocalVariable( UniqueId, string.Format( "float voroi{0} = 0;", OutputId ) );
  488. dataCollector.AddLocalVariable( UniqueId, string.Format( "float rest{0} = 0;", OutputId ) );
  489. dataCollector.AddLocalVariable( UniqueId, string.Format( "for( int it{0} = 0; it{0} <" + m_octaves + "; it{0}++ ){{", OutputId) );
  490. dataCollector.AddLocalVariable( UniqueId, string.Format( "voroi{0} += fade{0} * voronoi{0}( coords{0}, time{0}, id{0}, uv{0}, {1},{2} );", OutputId, smoothnessName, smoothIdName ) );
  491. dataCollector.AddLocalVariable( UniqueId, string.Format( "rest{0} += fade{0};", OutputId ) );
  492. dataCollector.AddLocalVariable( UniqueId, string.Format( "coords{0} *= 2;", OutputId ) );
  493. dataCollector.AddLocalVariable( UniqueId, string.Format( "fade{0} *= 0.5;", OutputId ) );
  494. dataCollector.AddLocalVariable( UniqueId, "}" + "//Voronoi" + OutputId );
  495. dataCollector.AddLocalVariable( UniqueId, string.Format( "voroi{0} /= rest{0};", OutputId ) );
  496. }
  497. m_outputPorts[ 0 ].SetLocalValue( "voroi" + OutputId, dataCollector.PortCategory );
  498. m_outputPorts[ 1 ].SetLocalValue( ( m_functionType == 0 && m_calculateSmoothValue && m_applySmoothToIds ) ? smoothIdName : ( "id" + OutputId ), dataCollector.PortCategory );
  499. m_outputPorts[ 2 ].SetLocalValue( "uv" + OutputId, dataCollector.PortCategory );
  500. return m_outputPorts[ outputId ].LocalValue( dataCollector.PortCategory );
  501. }
  502. }
  503. public override void ReadFromString( ref string[] nodeParams )
  504. {
  505. base.ReadFromString( ref nodeParams );
  506. m_searchQuality = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );
  507. m_distanceFunction = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );
  508. m_minkowskiPower = Convert.ToSingle( GetCurrentParam( ref nodeParams ) );
  509. m_functionType = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );
  510. m_octaves = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );
  511. m_tileable = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) );
  512. m_tileScale = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );
  513. m_useUnity = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) );
  514. if( UIUtils.CurrentShaderVersion() > 17402 )
  515. {
  516. m_calculateSmoothValue = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) );
  517. }
  518. if( UIUtils.CurrentShaderVersion() > 18902 )
  519. {
  520. m_applySmoothToIds = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) );
  521. }
  522. ChangePorts();
  523. ChechSmoothPorts();
  524. }
  525. public override void WriteToString( ref string nodeInfo, ref string connectionsInfo )
  526. {
  527. base.WriteToString( ref nodeInfo, ref connectionsInfo );
  528. IOUtils.AddFieldValueToString( ref nodeInfo, m_searchQuality );
  529. IOUtils.AddFieldValueToString( ref nodeInfo, m_distanceFunction );
  530. IOUtils.AddFieldValueToString( ref nodeInfo, m_minkowskiPower );
  531. IOUtils.AddFieldValueToString( ref nodeInfo, m_functionType );
  532. IOUtils.AddFieldValueToString( ref nodeInfo, m_octaves );
  533. IOUtils.AddFieldValueToString( ref nodeInfo, m_tileable.ToString() );
  534. IOUtils.AddFieldValueToString( ref nodeInfo, m_tileScale );
  535. IOUtils.AddFieldValueToString( ref nodeInfo, m_useUnity );
  536. IOUtils.AddFieldValueToString( ref nodeInfo, m_calculateSmoothValue );
  537. IOUtils.AddFieldValueToString( ref nodeInfo , m_applySmoothToIds );
  538. }
  539. }
  540. }