StencilBufferOpHelper.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. using System;
  2. using UnityEngine;
  3. using UnityEditor;
  4. using System.Collections.Generic;
  5. namespace AmplifyShaderEditor
  6. {
  7. [Serializable]
  8. public class StencilBufferOpHelper
  9. {
  10. public static readonly string[] StencilComparisonValues =
  11. {
  12. "<Default>",
  13. "Greater" ,
  14. "GEqual" ,
  15. "Less" ,
  16. "LEqual" ,
  17. "Equal" ,
  18. "NotEqual" ,
  19. "Always" ,
  20. "Never"
  21. };
  22. public static readonly Dictionary<string,int> StencilComparisonValuesDict = new Dictionary<string, int>()
  23. {
  24. {"Greater" , 1},
  25. {"GEqual" , 2},
  26. {"Less" , 3},
  27. {"LEqual" , 4},
  28. {"Equal" , 5},
  29. {"NotEqual", 6},
  30. {"Always" , 7},
  31. {"Never" , 8},
  32. };
  33. public static readonly string[] StencilComparisonLabels =
  34. {
  35. "<Default>",
  36. "Greater" ,
  37. "Greater or Equal" ,
  38. "Less" ,
  39. "Less or Equal" ,
  40. "Equal" ,
  41. "Not Equal" ,
  42. "Always" ,
  43. "Never"
  44. };
  45. public static readonly string[] StencilOpsValues =
  46. {
  47. "<Default>",
  48. "Keep",
  49. "Zero",
  50. "Replace",
  51. "IncrSat",
  52. "DecrSat",
  53. "Invert",
  54. "IncrWrap",
  55. "DecrWrap"
  56. };
  57. public static readonly Dictionary<string,int> StencilOpsValuesDict = new Dictionary<string, int>()
  58. {
  59. {"Keep", 1},
  60. {"Zero", 2},
  61. {"Replace", 3},
  62. {"IncrSat", 4},
  63. {"DecrSat", 5},
  64. {"Invert", 6},
  65. {"IncrWrap",7},
  66. {"DecrWrap",8},
  67. };
  68. public static readonly string[] StencilOpsLabels =
  69. {
  70. "<Default>",
  71. "Keep",
  72. "Zero",
  73. "Replace",
  74. "IncrSat",
  75. "DecrSat",
  76. "Invert",
  77. "IncrWrap",
  78. "DecrWrap"
  79. };
  80. private const string FoldoutLabelStr = " Stencil Buffer";
  81. private GUIContent ReferenceValueContent = new GUIContent( "Reference", "The value to be compared against (if Comparison is anything else than always) and/or the value to be written to the buffer (if either Pass, Fail or ZFail is set to replace)" );
  82. private GUIContent ReadMaskContent = new GUIContent( "Read Mask", "An 8 bit mask as an 0-255 integer, used when comparing the reference value with the contents of the buffer (referenceValue & readMask) comparisonFunction (stencilBufferValue & readMask)" );
  83. private GUIContent WriteMaskContent = new GUIContent( "Write Mask", "An 8 bit mask as an 0-255 integer, used when writing to the buffer" );
  84. private const string ComparisonStr = "Comparison";
  85. private const string PassStr = "Pass";
  86. private const string FailStr = "Fail";
  87. private const string ZFailStr = "ZFail";
  88. private const string ComparisonFrontStr = "Comp. Front";
  89. private const string PassFrontStr = "Pass Front";
  90. private const string FailFrontStr = "Fail Front";
  91. private const string ZFailFrontStr = "ZFail Front";
  92. private const string ComparisonBackStr = "Comp. Back";
  93. private const string PassBackStr = "Pass Back";
  94. private const string FailBackStr = "Fail Back";
  95. private const string ZFailBackStr = "ZFail Back";
  96. private const int ReferenceDefaultValue = 0;
  97. private const int ReadMaskDefaultValue = 255;
  98. private const int WriteMaskDefaultValue = 255;
  99. private const int ComparisonDefaultValue = 0;
  100. private const int PassStencilOpDefaultValue = 0;
  101. private const int FailStencilOpDefaultValue = 0;
  102. private const int ZFailStencilOpDefaultValue = 0;
  103. [SerializeField]
  104. private bool m_active;
  105. [SerializeField]
  106. private InlineProperty m_refValue = new InlineProperty( ReferenceDefaultValue );
  107. [SerializeField]
  108. private InlineProperty m_readMask = new InlineProperty( ReadMaskDefaultValue );
  109. [SerializeField]
  110. private InlineProperty m_writeMask = new InlineProperty( WriteMaskDefaultValue );
  111. //Comparison Function
  112. [SerializeField]
  113. private InlineProperty m_comparisonFunctionIdx = new InlineProperty( ComparisonDefaultValue );
  114. [SerializeField]
  115. private InlineProperty m_comparisonFunctionBackIdx = new InlineProperty( ComparisonDefaultValue );
  116. //Pass Stencil Op
  117. [SerializeField]
  118. private InlineProperty m_passStencilOpIdx = new InlineProperty( PassStencilOpDefaultValue );
  119. [SerializeField]
  120. private InlineProperty m_passStencilOpBackIdx = new InlineProperty( PassStencilOpDefaultValue );
  121. //Fail Stencil Op
  122. [SerializeField]
  123. private InlineProperty m_failStencilOpIdx = new InlineProperty( FailStencilOpDefaultValue );
  124. [SerializeField]
  125. private InlineProperty m_failStencilOpBackIdx = new InlineProperty( FailStencilOpDefaultValue );
  126. //ZFail Stencil Op
  127. [SerializeField]
  128. private InlineProperty m_zFailStencilOpIdx = new InlineProperty( ZFailStencilOpDefaultValue );
  129. [SerializeField]
  130. private InlineProperty m_zFailStencilOpBackIdx = new InlineProperty( ZFailStencilOpDefaultValue );
  131. public string CreateStencilOp( UndoParentNode owner )
  132. {
  133. string result = "\t\tStencil\n\t\t{\n";
  134. result += string.Format( "\t\t\tRef {0}\n", m_refValue.GetValueOrProperty() );
  135. if( m_readMask.Active || m_readMask.IntValue != ReadMaskDefaultValue )
  136. {
  137. result += string.Format( "\t\t\tReadMask {0}\n", m_readMask.GetValueOrProperty() );
  138. }
  139. if( m_writeMask.Active || m_writeMask.IntValue != WriteMaskDefaultValue )
  140. {
  141. result += string.Format( "\t\t\tWriteMask {0}\n", m_writeMask.GetValueOrProperty() );
  142. }
  143. if( ( owner as StandardSurfaceOutputNode ).CurrentCullMode == CullMode.Off )
  144. {
  145. if( m_comparisonFunctionIdx.IntValue != ComparisonDefaultValue || m_comparisonFunctionIdx.Active )
  146. result += string.Format( "\t\t\tCompFront {0}\n", m_comparisonFunctionIdx.GetValueOrProperty( StencilComparisonValues[ m_comparisonFunctionIdx.IntValue ] ) );
  147. if( m_passStencilOpIdx.IntValue != PassStencilOpDefaultValue || m_passStencilOpIdx.Active )
  148. result += string.Format( "\t\t\tPassFront {0}\n", m_passStencilOpIdx.GetValueOrProperty( StencilOpsValues[ m_passStencilOpIdx.IntValue ] ) );
  149. if( m_failStencilOpIdx.IntValue != FailStencilOpDefaultValue || m_failStencilOpIdx.Active )
  150. result += string.Format( "\t\t\tFailFront {0}\n", m_failStencilOpIdx.GetValueOrProperty( StencilOpsValues[ m_failStencilOpIdx.IntValue ] ) );
  151. if( m_zFailStencilOpIdx.IntValue != ZFailStencilOpDefaultValue || m_zFailStencilOpIdx.Active )
  152. result += string.Format( "\t\t\tZFailFront {0}\n", m_zFailStencilOpIdx.GetValueOrProperty( StencilOpsValues[ m_zFailStencilOpIdx.IntValue ] ) );
  153. if( m_comparisonFunctionBackIdx.IntValue != ComparisonDefaultValue || m_comparisonFunctionBackIdx.Active )
  154. result += string.Format( "\t\t\tCompBack {0}\n", m_comparisonFunctionBackIdx.GetValueOrProperty( StencilComparisonValues[ m_comparisonFunctionBackIdx.IntValue ] ) );
  155. if( m_passStencilOpBackIdx.IntValue != PassStencilOpDefaultValue || m_passStencilOpBackIdx.Active )
  156. result += string.Format( "\t\t\tPassBack {0}\n", m_passStencilOpBackIdx.GetValueOrProperty( StencilOpsValues[ m_passStencilOpBackIdx.IntValue ] ) );
  157. if( m_failStencilOpBackIdx.IntValue != FailStencilOpDefaultValue || m_failStencilOpBackIdx.Active )
  158. result += string.Format( "\t\t\tFailBack {0}\n", m_failStencilOpBackIdx.GetValueOrProperty( StencilOpsValues[ m_failStencilOpBackIdx.IntValue ] ) );
  159. if( m_zFailStencilOpBackIdx.IntValue != ZFailStencilOpDefaultValue || m_zFailStencilOpBackIdx.Active )
  160. result += string.Format( "\t\t\tZFailBack {0}\n", m_zFailStencilOpBackIdx.GetValueOrProperty( StencilOpsValues[ m_zFailStencilOpBackIdx.IntValue ] ) );
  161. }
  162. else
  163. {
  164. if( m_comparisonFunctionIdx.IntValue != ComparisonDefaultValue || m_comparisonFunctionIdx.Active )
  165. result += string.Format( "\t\t\tComp {0}\n", m_comparisonFunctionIdx.GetValueOrProperty( StencilComparisonValues[ m_comparisonFunctionIdx.IntValue ] ) );
  166. if( m_passStencilOpIdx.IntValue != PassStencilOpDefaultValue || m_passStencilOpIdx.Active )
  167. result += string.Format( "\t\t\tPass {0}\n", m_passStencilOpIdx.GetValueOrProperty( StencilOpsValues[ m_passStencilOpIdx.IntValue ] ) );
  168. if( m_failStencilOpIdx.IntValue != FailStencilOpDefaultValue || m_failStencilOpIdx.Active )
  169. result += string.Format( "\t\t\tFail {0}\n", m_failStencilOpIdx.GetValueOrProperty( StencilOpsValues[ m_failStencilOpIdx.IntValue ] ) );
  170. if( m_zFailStencilOpIdx.IntValue != ZFailStencilOpDefaultValue || m_zFailStencilOpIdx.Active )
  171. result += string.Format( "\t\t\tZFail {0}\n", m_zFailStencilOpIdx.GetValueOrProperty( StencilOpsValues[ m_zFailStencilOpIdx.IntValue ] ) );
  172. }
  173. result += "\t\t}\n";
  174. return result;
  175. }
  176. public void Draw( UndoParentNode owner )
  177. {
  178. bool foldoutValue = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedStencilOptions;
  179. NodeUtils.DrawPropertyGroup( owner, ref foldoutValue, ref m_active, FoldoutLabelStr, () =>
  180. {
  181. float cache = EditorGUIUtility.labelWidth;
  182. float cache2 = EditorGUIUtility.fieldWidth;
  183. EditorGUIUtility.labelWidth = 110;
  184. EditorGUIUtility.fieldWidth = 30;
  185. m_refValue.IntSlider( ref owner, ReferenceValueContent, 0, 255 );
  186. m_readMask.IntSlider( ref owner, ReadMaskContent, 0, 255 );
  187. m_writeMask.IntSlider( ref owner, WriteMaskContent, 0, 255 );
  188. //EditorGUIUtility.labelWidth = cache;
  189. EditorGUIUtility.fieldWidth = cache2;
  190. if( ( owner as StandardSurfaceOutputNode ).CurrentCullMode == CullMode.Off )
  191. {
  192. m_comparisonFunctionIdx.EnumTypePopup( ref owner, ComparisonFrontStr, StencilComparisonLabels );
  193. m_passStencilOpIdx.EnumTypePopup( ref owner, PassFrontStr, StencilOpsLabels );
  194. m_failStencilOpIdx.EnumTypePopup( ref owner, FailFrontStr, StencilOpsLabels );
  195. m_zFailStencilOpIdx.EnumTypePopup( ref owner, ZFailFrontStr, StencilOpsLabels );
  196. EditorGUILayout.Separator();
  197. m_comparisonFunctionBackIdx.EnumTypePopup( ref owner, ComparisonBackStr, StencilComparisonLabels );
  198. m_passStencilOpBackIdx.EnumTypePopup( ref owner, PassBackStr, StencilOpsLabels );
  199. m_failStencilOpBackIdx.EnumTypePopup( ref owner, FailBackStr, StencilOpsLabels );
  200. m_zFailStencilOpBackIdx.EnumTypePopup( ref owner, ZFailBackStr, StencilOpsLabels );
  201. }
  202. else
  203. {
  204. m_comparisonFunctionIdx.EnumTypePopup( ref owner, ComparisonStr, StencilComparisonLabels );
  205. m_passStencilOpIdx.EnumTypePopup( ref owner, PassFrontStr, StencilOpsLabels );
  206. m_failStencilOpIdx.EnumTypePopup( ref owner, FailFrontStr, StencilOpsLabels );
  207. m_zFailStencilOpIdx.EnumTypePopup( ref owner, ZFailFrontStr, StencilOpsLabels );
  208. }
  209. EditorGUIUtility.labelWidth = cache;
  210. } );
  211. owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedStencilOptions = foldoutValue;
  212. }
  213. public void ReadFromString( ref uint index, ref string[] nodeParams )
  214. {
  215. m_active = Convert.ToBoolean( nodeParams[ index++ ] );
  216. if( UIUtils.CurrentShaderVersion() > 14501 )
  217. {
  218. m_refValue.ReadFromString( ref index, ref nodeParams );
  219. m_readMask.ReadFromString( ref index, ref nodeParams );
  220. m_writeMask.ReadFromString( ref index, ref nodeParams );
  221. m_comparisonFunctionIdx.ReadFromString( ref index, ref nodeParams );
  222. m_passStencilOpIdx.ReadFromString( ref index, ref nodeParams );
  223. m_failStencilOpIdx.ReadFromString( ref index, ref nodeParams );
  224. m_zFailStencilOpIdx.ReadFromString( ref index, ref nodeParams );
  225. }
  226. else
  227. {
  228. m_refValue.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
  229. m_readMask.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
  230. m_writeMask.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
  231. m_comparisonFunctionIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
  232. m_passStencilOpIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
  233. m_failStencilOpIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
  234. m_zFailStencilOpIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
  235. }
  236. if( UIUtils.CurrentShaderVersion() > 13203 )
  237. {
  238. if( UIUtils.CurrentShaderVersion() > 14501 )
  239. {
  240. m_comparisonFunctionBackIdx.ReadFromString( ref index, ref nodeParams );
  241. m_passStencilOpBackIdx.ReadFromString( ref index, ref nodeParams );
  242. m_failStencilOpBackIdx.ReadFromString( ref index, ref nodeParams );
  243. m_zFailStencilOpBackIdx.ReadFromString( ref index, ref nodeParams );
  244. }
  245. else
  246. {
  247. m_comparisonFunctionBackIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
  248. m_passStencilOpBackIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
  249. m_failStencilOpBackIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
  250. m_zFailStencilOpBackIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
  251. }
  252. }
  253. }
  254. public void WriteToString( ref string nodeInfo )
  255. {
  256. IOUtils.AddFieldValueToString( ref nodeInfo, m_active );
  257. m_refValue.WriteToString( ref nodeInfo );
  258. m_readMask.WriteToString( ref nodeInfo );
  259. m_writeMask.WriteToString( ref nodeInfo );
  260. m_comparisonFunctionIdx.WriteToString( ref nodeInfo );
  261. m_passStencilOpIdx.WriteToString( ref nodeInfo );
  262. m_failStencilOpIdx.WriteToString( ref nodeInfo );
  263. m_zFailStencilOpIdx.WriteToString( ref nodeInfo );
  264. m_comparisonFunctionBackIdx.WriteToString( ref nodeInfo );
  265. m_passStencilOpBackIdx.WriteToString( ref nodeInfo );
  266. m_failStencilOpBackIdx.WriteToString( ref nodeInfo );
  267. m_zFailStencilOpBackIdx.WriteToString( ref nodeInfo );
  268. }
  269. public bool Active
  270. {
  271. get { return m_active; }
  272. set { m_active = value; }
  273. }
  274. }
  275. }