DiffusionProfileNode.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. // Amplify Shader Editor - Visual Shader Editing Tool
  2. // Copyright (c) Amplify Creations, Lda <info@amplify.pt>
  3. #if UNITY_2019_1_OR_NEWER
  4. using UnityEditor;
  5. using UnityEngine;
  6. using System;
  7. using System.Text;
  8. using System.Reflection;
  9. namespace AmplifyShaderEditor
  10. {
  11. public static class HDUtilsEx
  12. {
  13. private static System.Type type = null;
  14. #if UNITY_2019_3_OR_NEWER
  15. public static System.Type Type { get { return ( type == null ) ? type = System.Type.GetType( "UnityEngine.Rendering.HighDefinition.HDUtils, Unity.RenderPipelines.HighDefinition.Runtime" ) : type; } }
  16. #else
  17. public static System.Type Type { get { return ( type == null ) ? type = System.Type.GetType( "UnityEngine.Experimental.Rendering.HDPipeline.HDUtils, Unity.RenderPipelines.HighDefinition.Runtime" ) : type; } }
  18. #endif
  19. public static string ConvertVector4ToGUID( Vector4 vector )
  20. {
  21. object[] parameters = new object[] { vector };
  22. MethodInfo method;
  23. method = Type.GetMethod( "ConvertVector4ToGUID", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof( Vector4 ) }, null );
  24. if( method == null )
  25. method = Type.GetMethod( "ConvertVector4ToGUID", new Type[] { typeof( Vector4 ) } );
  26. return (string)method.Invoke( null, parameters );
  27. }
  28. public static Vector4 ConvertGUIDToVector4( string guid )
  29. {
  30. object[] parameters = new object[] { guid };
  31. MethodInfo method;
  32. method = Type.GetMethod( "ConvertGUIDToVector4", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof( string ) }, null );
  33. if( method == null )
  34. method = Type.GetMethod( "ConvertGUIDToVector4", new Type[] { typeof( string ) } );
  35. return (Vector4)method.Invoke( null, parameters );
  36. }
  37. }
  38. public static class DiffusionProfileSettingsEx
  39. {
  40. private static System.Type type = null;
  41. #if UNITY_2019_3_OR_NEWER
  42. public static System.Type Type { get { return ( type == null ) ? type = System.Type.GetType( "UnityEngine.Rendering.HighDefinition.DiffusionProfileSettings, Unity.RenderPipelines.HighDefinition.Runtime" ) : type; } }
  43. #else
  44. public static System.Type Type { get { return ( type == null ) ? type = System.Type.GetType( "UnityEngine.Experimental.Rendering.HDPipeline.DiffusionProfileSettings, Unity.RenderPipelines.HighDefinition.Runtime" ) : type; } }
  45. #endif
  46. public static uint Hash( UnityEngine.Object m_instance )
  47. {
  48. FieldInfo field;
  49. field = Type.GetField( "profile", BindingFlags.Instance | BindingFlags.NonPublic );
  50. if( field == null )
  51. field = Type.GetField( "profile" );
  52. var profile = field.GetValue( m_instance );
  53. var hashField = profile.GetType().GetField( "hash" );
  54. return (uint)hashField.GetValue( profile );
  55. }
  56. }
  57. [Serializable]
  58. [NodeAttributes( "Diffusion Profile", "Constants And Properties", "Returns Diffusion Profile Hash Id. To be used on Diffusion Profile port on HDRP templates.", KeyCode.None, true, 0, int.MaxValue )]
  59. public sealed class DiffusionProfileNode : PropertyNode
  60. {
  61. [SerializeField]
  62. private UnityEngine.Object m_defaultValue;
  63. [SerializeField]
  64. private UnityEngine.Object m_materialValue;
  65. [SerializeField]
  66. private bool m_defaultInspector = false;
  67. private bool m_isEditingFields;
  68. //[NonSerialized]
  69. //private DiffusionProfileSettings m_previousValue;
  70. public const string NodeErrorMsg = "Only valid on HDRP";
  71. protected override void CommonInit( int uniqueId )
  72. {
  73. base.CommonInit( uniqueId );
  74. AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue );
  75. m_drawPrecisionUI = false;
  76. m_currentPrecisionType = PrecisionType.Float;
  77. m_srpBatcherCompatible = true;
  78. m_freeType = false;
  79. #if UNITY_2019_3_OR_NEWER
  80. m_freeType = true;
  81. #endif
  82. m_errorMessageTypeIsError = NodeMessageType.Error;
  83. m_errorMessageTooltip = NodeErrorMsg;
  84. }
  85. protected override void OnUniqueIDAssigned()
  86. {
  87. base.OnUniqueIDAssigned();
  88. UIUtils.RegisterPropertyNode( this );
  89. }
  90. public override void CopyDefaultsToMaterial()
  91. {
  92. m_materialValue = m_defaultValue;
  93. }
  94. public override void DrawSubProperties()
  95. {
  96. m_defaultValue = EditorGUILayoutObjectField( Constants.DefaultValueLabel, m_defaultValue, DiffusionProfileSettingsEx.Type, true ) /*as UnityEngine.Object*/;
  97. }
  98. public override void DrawMaterialProperties()
  99. {
  100. if( m_materialMode )
  101. EditorGUI.BeginChangeCheck();
  102. m_materialValue = EditorGUILayoutObjectField( Constants.MaterialValueLabel, m_materialValue, DiffusionProfileSettingsEx.Type, true ) /*as DiffusionProfileSettings*/;
  103. if( m_materialMode && EditorGUI.EndChangeCheck() )
  104. {
  105. m_requireMaterialUpdate = true;
  106. }
  107. }
  108. public override void DrawMainPropertyBlock()
  109. {
  110. EditorGUILayout.BeginVertical();
  111. {
  112. if( m_freeType )
  113. {
  114. PropertyType parameterType = (PropertyType)EditorGUILayoutEnumPopup( ParameterTypeStr, m_currentParameterType );
  115. if( parameterType != m_currentParameterType )
  116. {
  117. ChangeParameterType( parameterType );
  118. BeginPropertyFromInspectorCheck();
  119. }
  120. }
  121. if( m_freeName )
  122. {
  123. switch( m_currentParameterType )
  124. {
  125. case PropertyType.Property:
  126. case PropertyType.InstancedProperty:
  127. {
  128. m_defaultInspector = EditorGUILayoutToggle( "Default Inspector", m_defaultInspector );
  129. if( m_defaultInspector )
  130. EditorGUILayout.HelpBox("While \"Default Inspector\" is turned ON you can't reorder this property or change it's name, and you can only have one per shader, use it only if you intend to share this shader with non-ASE users",MessageType.Info);
  131. EditorGUI.BeginDisabledGroup( m_defaultInspector );
  132. ShowPropertyInspectorNameGUI();
  133. ShowPropertyNameGUI( true );
  134. EditorGUI.EndDisabledGroup();
  135. ShowVariableMode();
  136. ShowAutoRegister();
  137. ShowPrecision();
  138. ShowToolbar();
  139. }
  140. break;
  141. case PropertyType.Global:
  142. {
  143. ShowPropertyInspectorNameGUI();
  144. ShowPropertyNameGUI( false );
  145. ShowVariableMode();
  146. ShowAutoRegister();
  147. ShowPrecision();
  148. ShowDefaults();
  149. }
  150. break;
  151. case PropertyType.Constant:
  152. {
  153. ShowPropertyInspectorNameGUI();
  154. ShowPrecision();
  155. ShowDefaults();
  156. }
  157. break;
  158. }
  159. }
  160. }
  161. EditorGUILayout.EndVertical();
  162. }
  163. public override void OnNodeLogicUpdate(DrawInfo drawInfo)
  164. {
  165. base.OnNodeLogicUpdate( drawInfo );
  166. m_showErrorMessage = ( ContainerGraph.CurrentCanvasMode == NodeAvailability.SurfaceShader ) ||
  167. ( ContainerGraph.CurrentCanvasMode == NodeAvailability.TemplateShader && ContainerGraph.CurrentSRPType != TemplateSRPType.HDRP );
  168. }
  169. public override void DrawProperties()
  170. {
  171. base.DrawProperties();
  172. if ( m_showErrorMessage )
  173. {
  174. EditorGUILayout.HelpBox(NodeErrorMsg, MessageType.Error );
  175. }
  176. }
  177. public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar )
  178. {
  179. base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar );
  180. if( m_currentParameterType != PropertyType.Constant )
  181. {
  182. if( m_defaultInspector )
  183. return "_DiffusionProfileHash";
  184. return PropertyData( dataCollector.PortCategory );
  185. }
  186. #if UNITY_2019_3_OR_NEWER
  187. return RoundTrip.ToRoundTrip( HDShadowUtilsEx.Asfloat( DefaultHash ) );
  188. #else
  189. return "asfloat(" + DefaultHash.ToString() + ")";
  190. #endif
  191. }
  192. public override string GetUniformValue()
  193. {
  194. if( m_defaultInspector )
  195. return "float _DiffusionProfileHash";
  196. return base.GetUniformValue();
  197. }
  198. public override bool GetUniformData( out string dataType, out string dataName, ref bool fullValue )
  199. {
  200. if( m_defaultInspector )
  201. {
  202. dataType = "float";
  203. dataName = "_DiffusionProfileHash";
  204. return true;
  205. }
  206. return base.GetUniformData( out dataType, out dataName, ref fullValue );
  207. }
  208. public override string GetPropertyValue()
  209. {
  210. Vector4 asset = Vector4.zero;
  211. if( m_defaultValue != null )
  212. asset = HDUtilsEx.ConvertGUIDToVector4( AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath( m_defaultValue ) ) );
  213. string assetVec = RoundTrip.ToRoundTrip( asset.x ) + ", " + RoundTrip.ToRoundTrip( asset.y ) + ", " + RoundTrip.ToRoundTrip( asset.z ) + ", " + RoundTrip.ToRoundTrip( asset.w );
  214. string lineOne = string.Empty;
  215. string lineTwo = string.Empty;
  216. if( m_defaultInspector )
  217. {
  218. lineOne = PropertyAttributes + "[HideInInspector]_DiffusionProfileAsset(\"" + m_propertyInspectorName + "\", Vector) = ( " + assetVec + " )";
  219. lineTwo = "\n[HideInInspector]_DiffusionProfileHash(\"" + m_propertyInspectorName + "\", Float) = " + RoundTrip.ToRoundTrip( HDShadowUtilsEx.Asfloat( DefaultHash ) );
  220. }
  221. else
  222. {
  223. #if UNITY_2020_2_OR_NEWER
  224. lineOne = "\n[DiffusionProfile]" + m_propertyName + "(\"" + m_propertyInspectorName + "\", Float) = " + RoundTrip.ToRoundTrip( HDShadowUtilsEx.Asfloat( DefaultHash ) );
  225. lineTwo = PropertyAttributes + "[HideInInspector]" + m_propertyName + "_Asset(\"" + m_propertyInspectorName + "\", Vector) = ( " + assetVec + " )";
  226. #else
  227. lineOne = PropertyAttributes + "[ASEDiffusionProfile(" + m_propertyName + ")]" + m_propertyName + "_asset(\"" + m_propertyInspectorName + "\", Vector) = ( " + assetVec + " )";
  228. lineTwo = "\n[HideInInspector]" + m_propertyName + "(\"" + m_propertyInspectorName + "\", Float) = " + RoundTrip.ToRoundTrip( HDShadowUtilsEx.Asfloat( DefaultHash ) );
  229. #endif
  230. }
  231. return lineOne + lineTwo;
  232. }
  233. public override void UpdateMaterial( Material mat )
  234. {
  235. base.UpdateMaterial( mat );
  236. if( UIUtils.IsProperty( m_currentParameterType ) && !InsideShaderFunction )
  237. {
  238. if( m_materialValue != null )
  239. {
  240. Vector4 asset = HDUtilsEx.ConvertGUIDToVector4( AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath( m_materialValue ) ) );
  241. if( m_defaultInspector )
  242. {
  243. mat.SetVector( "_DiffusionProfileAsset", asset );
  244. mat.SetFloat( "_DiffusionProfileHash", HDShadowUtilsEx.Asfloat( MaterialHash ) );
  245. }
  246. else
  247. {
  248. mat.SetVector( m_propertyName + "_asset", asset );
  249. mat.SetFloat( m_propertyName, HDShadowUtilsEx.Asfloat( MaterialHash ) );
  250. }
  251. }
  252. }
  253. }
  254. public override void ForceUpdateFromMaterial( Material material )
  255. {
  256. string propertyAsset = m_propertyName + "_asset";
  257. if( m_defaultInspector )
  258. propertyAsset = "_DiffusionProfileAsset";
  259. if( UIUtils.IsProperty( m_currentParameterType ) && material.HasProperty( propertyAsset ) )
  260. {
  261. var guid = HDUtilsEx.ConvertVector4ToGUID( material.GetVector( propertyAsset ) );
  262. var profile = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( guid ), DiffusionProfileSettingsEx.Type );
  263. if( profile != null )
  264. m_materialValue = profile;
  265. }
  266. }
  267. public override void WriteToString( ref string nodeInfo, ref string connectionsInfo )
  268. {
  269. base.WriteToString( ref nodeInfo, ref connectionsInfo );
  270. string defaultGuid = ( m_defaultValue != null ) ? AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath( m_defaultValue ) ) : "0";
  271. IOUtils.AddFieldValueToString( ref nodeInfo, defaultGuid );
  272. string materialGuid = ( m_materialValue != null ) ? AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath( m_materialValue ) ) : "0";
  273. IOUtils.AddFieldValueToString( ref nodeInfo, materialGuid );
  274. IOUtils.AddFieldValueToString( ref nodeInfo, m_defaultInspector );
  275. }
  276. public override void ReadFromString( ref string[] nodeParams )
  277. {
  278. if( UIUtils.CurrentShaderVersion() > 17004 )
  279. base.ReadFromString( ref nodeParams );
  280. else
  281. ParentReadFromString( ref nodeParams );
  282. string defaultGuid = GetCurrentParam( ref nodeParams );
  283. if( defaultGuid.Length > 1 )
  284. {
  285. m_defaultValue = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( defaultGuid ), DiffusionProfileSettingsEx.Type );
  286. }
  287. if( UIUtils.CurrentShaderVersion() > 17004 )
  288. {
  289. string materialGuid = GetCurrentParam( ref nodeParams );
  290. if( materialGuid.Length > 1 )
  291. {
  292. m_materialValue = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( materialGuid ), DiffusionProfileSettingsEx.Type );
  293. }
  294. }
  295. if( UIUtils.CurrentShaderVersion() > 17900 )
  296. {
  297. m_defaultInspector = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) );
  298. }
  299. }
  300. public override void ReadOutputDataFromString( ref string[] nodeParams )
  301. {
  302. base.ReadOutputDataFromString( ref nodeParams );
  303. if( UIUtils.CurrentShaderVersion() < 17005 )
  304. m_outputPorts[ 0 ].ChangeProperties( Constants.EmptyPortValue, WirePortDataType.FLOAT, false );
  305. }
  306. public override string GetPropertyValStr()
  307. {
  308. if( m_defaultInspector )
  309. return "_DiffusionProfileHash";
  310. return PropertyName;
  311. }
  312. //Vector4 ProfileGUID { get { return ( m_diffusionProfile != null ) ? HDUtils.ConvertGUIDToVector4( AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath( m_diffusionProfile ) ) ) : Vector4.zero; } }
  313. uint DefaultHash { get { return ( m_defaultValue != null ) ? DiffusionProfileSettingsEx.Hash( m_defaultValue ) : 0; } }
  314. uint MaterialHash { get { return ( m_materialValue != null ) ? DiffusionProfileSettingsEx.Hash( m_materialValue ) : 0; } }
  315. private static class HDShadowUtilsEx
  316. {
  317. private static System.Type type = null;
  318. public static System.Type Type { get { return ( type == null ) ? type = System.Type.GetType( "UnityEngine.Rendering.HighDefinition.HDShadowUtils, Unity.RenderPipelines.HighDefinition.Runtime" ) : type; } }
  319. public static float Asfloat( uint val )
  320. {
  321. #if UNITY_2019_3_OR_NEWER
  322. object[] parameters = new object[] { val };
  323. MethodInfo method = Type.GetMethod( "Asfloat", new Type[] { typeof( uint ) } );
  324. return (float)method.Invoke( null, parameters );
  325. #else
  326. return HDShadowUtils.Asfloat( val );
  327. #endif
  328. }
  329. public static uint Asuint( float val )
  330. {
  331. #if UNITY_2019_3_OR_NEWER
  332. object[] parameters = new object[] { val };
  333. MethodInfo method = Type.GetMethod( "Asuint", new Type[] { typeof( float ) } );
  334. return (uint)method.Invoke( null, parameters );
  335. #else
  336. return HDShadowUtils.Asuint( val );
  337. #endif
  338. }
  339. }
  340. private static class RoundTrip
  341. {
  342. private static String[] zeros = new String[ 1000 ];
  343. static RoundTrip()
  344. {
  345. for( int i = 0; i < zeros.Length; i++ )
  346. {
  347. zeros[ i ] = new String( '0', i );
  348. }
  349. }
  350. public static String ToRoundTrip( double value )
  351. {
  352. String str = value.ToString( "r" );
  353. int x = str.IndexOf( 'E' );
  354. if( x < 0 ) return str;
  355. int x1 = x + 1;
  356. String exp = str.Substring( x1, str.Length - x1 );
  357. int e = int.Parse( exp );
  358. String s = null;
  359. int numDecimals = 0;
  360. if( value < 0 )
  361. {
  362. int len = x - 3;
  363. if( e >= 0 )
  364. {
  365. if( len > 0 )
  366. {
  367. s = str.Substring( 0, 2 ) + str.Substring( 3, len );
  368. numDecimals = len;
  369. }
  370. else
  371. s = str.Substring( 0, 2 );
  372. }
  373. else
  374. {
  375. // remove the leading minus sign
  376. if( len > 0 )
  377. {
  378. s = str.Substring( 1, 1 ) + str.Substring( 3, len );
  379. numDecimals = len;
  380. }
  381. else
  382. s = str.Substring( 1, 1 );
  383. }
  384. }
  385. else
  386. {
  387. int len = x - 2;
  388. if( len > 0 )
  389. {
  390. s = str[ 0 ] + str.Substring( 2, len );
  391. numDecimals = len;
  392. }
  393. else
  394. s = str[ 0 ].ToString();
  395. }
  396. if( e >= 0 )
  397. {
  398. e = e - numDecimals;
  399. String z = ( e < zeros.Length ? zeros[ e ] : new String( '0', e ) );
  400. s = s + z;
  401. }
  402. else
  403. {
  404. e = ( -e - 1 );
  405. String z = ( e < zeros.Length ? zeros[ e ] : new String( '0', e ) );
  406. if( value < 0 )
  407. s = "-0." + z + s;
  408. else
  409. s = "0." + z + s;
  410. }
  411. return s;
  412. }
  413. }
  414. }
  415. }
  416. #endif