OutlineOpHelper.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683
  1. // Amplify Shader Editor - Visual Shader Editing Tool
  2. // Copyright (c) Amplify Creations, Lda <info@amplify.pt>
  3. using UnityEngine;
  4. using UnityEditor;
  5. using System;
  6. using System.Collections.Generic;
  7. namespace AmplifyShaderEditor
  8. {
  9. public enum OutlineMode
  10. {
  11. VertexOffset,
  12. VertexScale
  13. }
  14. [Serializable]
  15. public sealed class OutlineOpHelper
  16. {
  17. private string[] ModeTags =
  18. {
  19. "Tags{ }",
  20. "Tags{ \"RenderType\" = \"TransparentCutout\" \"Queue\" = \"AlphaTest+0\"}",
  21. "Tags{ \"RenderType\" = \"Transparent\" \"Queue\" = \"Transparent+0\"}",
  22. "Tags{ \"RenderType\" = \"Transparent\" \"Queue\" = \"Transparent+0\" }"
  23. };
  24. private string[] ModePragma =
  25. {
  26. string.Empty,
  27. string.Empty,
  28. "alpha:fade ",
  29. "alpha:premul "
  30. };
  31. private readonly string OutlineSurfaceConfig = "#pragma surface outlineSurf Outline {0} keepalpha noshadow noambient novertexlights nolightmap nodynlightmap nodirlightmap nometa noforwardadd vertex:outlineVertexDataFunc ";
  32. private readonly string OutlineBodyStructBegin = "struct Input {";
  33. private readonly string OutlineBodyStructDefault = "\thalf filler;";
  34. private readonly string OutlineBodyStructEnd = "};";
  35. private readonly string OutlineDefaultUniformColor = "half4 _ASEOutlineColor;";
  36. private readonly string OutlineDefaultUniformWidth = "half _ASEOutlineWidth;";
  37. private readonly string OutlineDefaultUniformColorInstanced = "UNITY_DEFINE_INSTANCED_PROP( half4, _ASEOutlineColor )";
  38. private readonly string OutlineDefaultUniformWidthInstanced = "UNITY_DEFINE_INSTANCED_PROP( half, _ASEOutlineWidth )";
  39. private readonly string OutlineDefaultVertexHeader = "void outlineVertexDataFunc( inout appdata_full v, out Input o )\n\t\t{";
  40. private readonly string OutlineTessVertexHeader = "void outlineVertexDataFunc( inout appdata_full v )\n\t\t{";
  41. private readonly string OutlineDefaultVertexOutputDeclaration = "\tUNITY_INITIALIZE_OUTPUT( Input, o );";
  42. private readonly string[] OutlineSurfBody = {
  43. "\to.Emission = _ASEOutlineColor.rgb;",
  44. "\to.Alpha = 1;"
  45. };
  46. private readonly string[] OutlineSurfBodyInstanced = {
  47. "\to.Emission = UNITY_ACCESS_INSTANCED_PROP(_ASEOutlineColor).rgb;",
  48. "\to.Alpha = 1;"
  49. };
  50. private readonly string[] OutlineBodyDefaultSurfBegin = {
  51. "}",
  52. "inline half4 LightingOutline( SurfaceOutput s, half3 lightDir, half atten ) { return half4 ( 0,0,0, s.Alpha); }",
  53. "void outlineSurf( Input i, inout SurfaceOutput o )",
  54. "{"};
  55. private readonly string[] OutlineBodyDefaultSurfEnd = {
  56. "}",
  57. "ENDCG",
  58. "\n"};
  59. //private const string OutlineInstancedHeader = "#pragma multi_compile_instancing";
  60. //private readonly string[] OutlineBodyInstancedBegin = {
  61. // "UNITY_INSTANCING_CBUFFER_START({0})",
  62. // "\tUNITY_DEFINE_INSTANCED_PROP( half4, _ASEOutlineColor )",
  63. // "\tUNITY_DEFINE_INSTANCED_PROP(half, _ASEOutlineWidth)",
  64. // "UNITY_INSTANCING_CBUFFER_END",
  65. // "void outlineVertexDataFunc( inout appdata_full v, out Input o )",
  66. // "{",
  67. // "\tUNITY_INITIALIZE_OUTPUT( Input, o );"};
  68. //private readonly string[] OutlineBodyInstancedEnd = {
  69. // "}",
  70. // "inline half4 LightingOutline( SurfaceOutput s, half3 lightDir, half atten ) { return half4 ( 0,0,0, s.Alpha); }",
  71. // "void outlineSurf( Input i, inout SurfaceOutput o ) { o.Emission = UNITY_ACCESS_INSTANCED_PROP( _ASEOutlineColor ).rgb; o.Alpha = 1; }",
  72. // "ENDCG",
  73. // "\n"};
  74. private const string WidthVariableAccessInstanced = "UNITY_ACCESS_INSTANCED_PROP( _ASEOutlineWidth )";
  75. private const string OutlineVertexOffsetMode = "\tv.vertex.xyz += ( v.normal * {0} );";
  76. private const string OutlineVertexScaleMode = "\tv.vertex.xyz *= ( 1 + {0});";
  77. private const string OutlineVertexCustomMode = "\tv.vertex.xyz += {0};";
  78. private const string OutlineColorLabel = "Color";
  79. private const string OutlineWidthLabel = "Width";
  80. private const string ColorPropertyName = "_ASEOutlineColor";
  81. private const string WidthPropertyName = "_ASEOutlineWidth";
  82. private const string WidthPropertyNameInstanced = "UNITY_ACCESS_INSTANCED_PROP(_ASEOutlineWidth)";
  83. private const string ColorPropertyDec = "_ASEOutlineColor( \"Outline Color\", Color ) = ({0})";
  84. private const string OutlinePropertyDec = "_ASEOutlineWidth( \"Outline Width\", Float ) = {0}";
  85. private const string ModePropertyStr = "Mode";
  86. private const string NoFogStr = "No Fog";
  87. private const string BillboardInstructionFormat = "\t{0};";
  88. private readonly char[] m_colorMaskChar = { 'R' , 'G' , 'B' , 'A' };
  89. [SerializeField]
  90. private Color m_outlineColor;
  91. [SerializeField]
  92. private float m_outlineWidth;
  93. [SerializeField]
  94. private bool m_enabled;
  95. [SerializeField]
  96. private OutlineMode m_mode = OutlineMode.VertexOffset;
  97. [SerializeField]
  98. private bool m_noFog = true;
  99. private bool[] m_colorMask = { true , true , true , true };
  100. private CullMode m_cullMode = CullMode.Front;
  101. private int m_zTestMode = 0;
  102. private int m_zWriteMode = 0;
  103. private bool m_dirtyInput = false;
  104. private string m_inputs = string.Empty;
  105. private List<PropertyDataCollector> m_inputList = new List<PropertyDataCollector>();
  106. private string m_uniforms = string.Empty;
  107. private List<PropertyDataCollector> m_uniformList = new List<PropertyDataCollector>();
  108. private List<PropertyDataCollector> m_instancedPropertiesList = new List<PropertyDataCollector>();
  109. private string m_instancedProperties = string.Empty;
  110. private string m_instructions = string.Empty;
  111. private string m_functions = string.Empty;
  112. private string m_includes = string.Empty;
  113. private string m_pragmas = string.Empty;
  114. private string m_defines = string.Empty;
  115. private string m_standardAdditionalDirectives = string.Empty;
  116. private string m_vertexData = string.Empty;
  117. private string m_grabPasses = string.Empty;
  118. private Dictionary<string, string> m_localFunctions;
  119. //private OutlineMode m_customMode = OutlineMode.VertexOffset;
  120. private int m_offsetMode = 0;
  121. private bool m_customNoFog = true;
  122. public void Draw( ParentNode owner, GUIStyle toolbarstyle, Material mat )
  123. {
  124. Color cachedColor = GUI.color;
  125. GUI.color = new Color( cachedColor.r, cachedColor.g, cachedColor.b, 0.5f );
  126. EditorGUILayout.BeginHorizontal( toolbarstyle );
  127. GUI.color = cachedColor;
  128. owner.ContainerGraph.ParentWindow.InnerWindowVariables.OutlineActiveMode = owner.GUILayoutToggle( owner.ContainerGraph.ParentWindow.InnerWindowVariables.OutlineActiveMode , EditorVariablesManager.OutlineActiveMode.LabelName, UIUtils.MenuItemToggleStyle, GUILayout.ExpandWidth( true ) );
  129. EditorGUI.BeginChangeCheck();
  130. m_enabled = owner.EditorGUILayoutToggle( string.Empty, m_enabled, UIUtils.MenuItemEnableStyle, GUILayout.Width( 16 ) );
  131. if( EditorGUI.EndChangeCheck() )
  132. {
  133. if( m_enabled )
  134. UpdateToMaterial( mat );
  135. UIUtils.RequestSave();
  136. }
  137. EditorGUILayout.EndHorizontal();
  138. if( owner.ContainerGraph.ParentWindow.InnerWindowVariables.OutlineActiveMode )
  139. {
  140. cachedColor = GUI.color;
  141. GUI.color = new Color( cachedColor.r, cachedColor.g, cachedColor.b, ( EditorGUIUtility.isProSkin ? 0.5f : 0.25f ) );
  142. EditorGUILayout.BeginVertical( UIUtils.MenuItemBackgroundStyle );
  143. GUI.color = cachedColor;
  144. EditorGUILayout.Separator();
  145. EditorGUI.BeginDisabledGroup( !m_enabled );
  146. EditorGUI.indentLevel += 1;
  147. {
  148. m_mode = (OutlineMode)owner.EditorGUILayoutEnumPopup( ModePropertyStr, m_mode );
  149. EditorGUI.BeginChangeCheck();
  150. m_outlineColor = owner.EditorGUILayoutColorField( OutlineColorLabel, m_outlineColor );
  151. if( EditorGUI.EndChangeCheck() && mat != null )
  152. {
  153. if( mat.HasProperty( ColorPropertyName ) )
  154. {
  155. mat.SetColor( ColorPropertyName, m_outlineColor );
  156. }
  157. }
  158. EditorGUI.BeginChangeCheck();
  159. m_outlineWidth = owner.EditorGUILayoutFloatField( OutlineWidthLabel, m_outlineWidth );
  160. if( EditorGUI.EndChangeCheck() && mat != null )
  161. {
  162. if( mat.HasProperty( WidthPropertyName ) )
  163. {
  164. mat.SetFloat( WidthPropertyName, m_outlineWidth );
  165. }
  166. }
  167. m_noFog = owner.EditorGUILayoutToggle( NoFogStr, m_noFog );
  168. }
  169. EditorGUI.indentLevel -= 1;
  170. EditorGUI.EndDisabledGroup();
  171. EditorGUILayout.Separator();
  172. EditorGUILayout.EndVertical();
  173. }
  174. }
  175. public void UpdateToMaterial( Material mat )
  176. {
  177. if( mat == null )
  178. return;
  179. if( mat.HasProperty( ColorPropertyName ) )
  180. {
  181. mat.SetColor( ColorPropertyName, m_outlineColor );
  182. }
  183. if( mat.HasProperty( WidthPropertyName ) )
  184. {
  185. mat.SetFloat( WidthPropertyName, m_outlineWidth );
  186. }
  187. }
  188. public void ReadFromString( ref uint index, ref string[] nodeParams )
  189. {
  190. m_enabled = Convert.ToBoolean( nodeParams[ index++ ] );
  191. m_outlineWidth = Convert.ToSingle( nodeParams[ index++ ] );
  192. m_outlineColor = IOUtils.StringToColor( nodeParams[ index++ ] );
  193. if( UIUtils.CurrentShaderVersion() > 5004 )
  194. {
  195. m_mode = (OutlineMode)Enum.Parse( typeof( OutlineMode ), nodeParams[ index++ ] );
  196. }
  197. if( UIUtils.CurrentShaderVersion() > 13902 )
  198. {
  199. m_noFog = Convert.ToBoolean( nodeParams[ index++ ] );
  200. }
  201. }
  202. public void WriteToString( ref string nodeInfo )
  203. {
  204. IOUtils.AddFieldValueToString( ref nodeInfo, m_enabled );
  205. IOUtils.AddFieldValueToString( ref nodeInfo, m_outlineWidth );
  206. IOUtils.AddFieldValueToString( ref nodeInfo, IOUtils.ColorToString( m_outlineColor ) );
  207. IOUtils.AddFieldValueToString( ref nodeInfo, m_mode );
  208. IOUtils.AddFieldValueToString( ref nodeInfo, m_noFog );
  209. }
  210. public void AddToDataCollector( ref MasterNodeDataCollector dataCollector )
  211. {
  212. if( !dataCollector.UsingCustomOutlineColor )
  213. dataCollector.AddToProperties( -1, string.Format( ColorPropertyDec, IOUtils.ColorToString( m_outlineColor ) ), -1 );
  214. if( !dataCollector.UsingCustomOutlineWidth )
  215. dataCollector.AddToProperties( -1, string.Format( OutlinePropertyDec, m_outlineWidth ), -1 );
  216. }
  217. public void UpdateFromMaterial( Material mat )
  218. {
  219. if( mat.HasProperty( ColorPropertyName ) )
  220. {
  221. m_outlineColor = mat.GetColor( ColorPropertyName );
  222. }
  223. if( mat.HasProperty( WidthPropertyName ) )
  224. {
  225. m_outlineWidth = mat.GetFloat( WidthPropertyName );
  226. }
  227. }
  228. void AddMultibodyString( string body , List<string> list )
  229. {
  230. body = body.Replace( "\t\t", string.Empty );
  231. string[] strArr = body.Split( '\n' );
  232. for( int i = 0; i < strArr.Length; i++ )
  233. {
  234. list.Add( strArr[ i ] );
  235. }
  236. }
  237. public string[] OutlineFunctionBody( ref MasterNodeDataCollector dataCollector, bool instanced, bool isShadowCaster, string shaderName, string[] billboardInfo, ref TessellationOpHelper tessOpHelper, string target, PrecisionType precision )
  238. {
  239. List<string> body = new List<string>();
  240. body.Add( ModeTags[ dataCollector.CustomOutlineSelectedAlpha ] );
  241. if( !string.IsNullOrEmpty( m_grabPasses ))
  242. body.Add( m_grabPasses.Replace( "\t\t",string.Empty ));
  243. if( m_zWriteMode != 0 )
  244. body.Add( "ZWrite " + ZBufferOpHelper.ZWriteModeValues[ m_zWriteMode ] );
  245. if( m_zTestMode != 0 )
  246. body.Add( "ZTest " + ZBufferOpHelper.ZTestModeValues[ m_zTestMode ] );
  247. body.Add( "Cull " + m_cullMode );
  248. //Color Mask
  249. {
  250. int count = 0;
  251. string colorMask = string.Empty;
  252. for( int i = 0 ; i < m_colorMask.Length ; i++ )
  253. {
  254. if( m_colorMask[ i ] )
  255. {
  256. count++;
  257. colorMask += m_colorMaskChar[ i ];
  258. }
  259. }
  260. if( count != m_colorMask.Length )
  261. {
  262. body.Add( "ColorMask " + ( ( count == 0 ) ? "0" : colorMask ) );
  263. }
  264. }
  265. body.Add( "CGPROGRAM" );
  266. if( tessOpHelper.EnableTesselation )
  267. {
  268. body.Add( "#include \"" + TessellationOpHelper.TessInclude + "\"" );
  269. body.Add( "#pragma target " + target );
  270. }
  271. else
  272. {
  273. body.Add( "#pragma target 3.0" );
  274. }
  275. bool customOutline = dataCollector.UsingCustomOutlineColor || dataCollector.UsingCustomOutlineWidth || dataCollector.UsingCustomOutlineAlpha;
  276. int outlineMode = customOutline ? m_offsetMode : ( m_mode == OutlineMode.VertexOffset ? 0 : 1 );
  277. string extraOptions = ( customOutline ? m_customNoFog : m_noFog ) ? "nofog " : string.Empty;
  278. if( dataCollector.CustomOutlineSelectedAlpha > 0 )
  279. {
  280. extraOptions += ModePragma[ dataCollector.CustomOutlineSelectedAlpha ];
  281. }
  282. string surfConfig = string.Format( OutlineSurfaceConfig, extraOptions );
  283. if( tessOpHelper.EnableTesselation )
  284. tessOpHelper.WriteToOptionalParams( ref surfConfig );
  285. body.Add( surfConfig );
  286. if( !isShadowCaster )
  287. {
  288. AddMultibodyString( m_defines, body );
  289. AddMultibodyString( m_includes, body );
  290. AddMultibodyString( m_pragmas, body );
  291. }
  292. AddMultibodyString( m_standardAdditionalDirectives, body );
  293. //if( instanced )
  294. //{
  295. // body.Add( OutlineInstancedHeader );
  296. //}
  297. if( customOutline )
  298. {
  299. if( isShadowCaster )
  300. {
  301. for( int i = 0; i < InputList.Count; i++ )
  302. {
  303. dataCollector.AddToInput( InputList[ i ].NodeId, InputList[ i ].PropertyName, !InputList[ i ].IsDirective );
  304. }
  305. }
  306. else
  307. {
  308. if( !string.IsNullOrEmpty( m_inputs ) )
  309. body.Add( m_inputs.Trim( '\t', '\n' ) );
  310. }
  311. if( !DirtyInput && !isShadowCaster )
  312. body.Add( OutlineBodyStructDefault );
  313. if( !isShadowCaster )
  314. body.Add( OutlineBodyStructEnd );
  315. }
  316. else if( !isShadowCaster )
  317. {
  318. body.Add( OutlineBodyStructBegin );
  319. body.Add( OutlineBodyStructDefault );
  320. body.Add( OutlineBodyStructEnd );
  321. }
  322. if( instanced )
  323. {
  324. //for( int i = 0; i < OutlineBodyInstancedBegin.Length; i++ )
  325. //{
  326. // body.Add( ( i == 0 ) ? string.Format( OutlineBodyInstancedBegin[ i ], shaderName ) : OutlineBodyInstancedBegin[ i ] );
  327. //}
  328. //if( (object)billboardInfo != null )
  329. //{
  330. // for( int j = 0; j < billboardInfo.Length; j++ )
  331. // {
  332. // body.Add( string.Format( BillboardInstructionFormat, billboardInfo[ j ] ) );
  333. // }
  334. //}
  335. //switch( outlineMode )
  336. //{
  337. // case 0: body.Add( string.Format( OutlineVertexOffsetMode, WidthVariableAccessInstanced ) ); break;
  338. // case 1: body.Add( string.Format( OutlineVertexScaleMode, WidthVariableAccessInstanced ) ); break;
  339. // case 2: body.Add( string.Format( OutlineVertexCustomMode, WidthVariableAccessInstanced ) ); break;
  340. //}
  341. //for( int i = 0; i < OutlineBodyInstancedEnd.Length; i++ )
  342. //{
  343. // body.Add( OutlineBodyInstancedEnd[ i ] );
  344. //}
  345. //Instanced block name must differ from used on main shader so it won't throw a duplicate name error
  346. shaderName = shaderName+ "Outline";
  347. bool openCBuffer = true;
  348. if( customOutline )
  349. {
  350. if( isShadowCaster )
  351. {
  352. for( int i = 0; i < UniformList.Count; i++ )
  353. {
  354. dataCollector.AddToUniforms( UniformList[ i ].NodeId, UniformList[ i ].PropertyName );
  355. }
  356. foreach( KeyValuePair<string, string> kvp in m_localFunctions )
  357. {
  358. dataCollector.AddFunction( kvp.Key, kvp.Value );
  359. }
  360. }
  361. else
  362. {
  363. if( !string.IsNullOrEmpty( Uniforms ) )
  364. body.Add( Uniforms.Trim( '\t', '\n' ) );
  365. openCBuffer = false;
  366. body.Add( string.Format( IOUtils.InstancedPropertiesBegin, shaderName ));
  367. if( !string.IsNullOrEmpty( InstancedProperties ) )
  368. body.Add( InstancedProperties.Trim( '\t', '\n' ) );
  369. }
  370. }
  371. if( openCBuffer)
  372. body.Add( string.Format( IOUtils.InstancedPropertiesBegin, shaderName ) );
  373. if( !dataCollector.UsingCustomOutlineColor )
  374. body.Add( precision == PrecisionType.Float ? OutlineDefaultUniformColorInstanced.Replace( "half", "float" ) : OutlineDefaultUniformColorInstanced );
  375. if( !dataCollector.UsingCustomOutlineWidth )
  376. body.Add( precision == PrecisionType.Float ? OutlineDefaultUniformWidthInstanced.Replace( "half", "float" ) : OutlineDefaultUniformWidthInstanced );
  377. body.Add( IOUtils.InstancedPropertiesEnd );
  378. //Functions
  379. if( customOutline && !isShadowCaster )
  380. body.Add( Functions );
  381. if( tessOpHelper.EnableTesselation && !isShadowCaster )
  382. {
  383. body.Add( tessOpHelper.Uniforms().TrimStart( '\t' ) );
  384. body.Add( tessOpHelper.GetCurrentTessellationFunction( ref dataCollector ).Trim( '\t', '\n' ) + "\n" );
  385. }
  386. if( tessOpHelper.EnableTesselation )
  387. {
  388. body.Add( OutlineTessVertexHeader );
  389. }
  390. else
  391. {
  392. body.Add( OutlineDefaultVertexHeader );
  393. body.Add( OutlineDefaultVertexOutputDeclaration );
  394. }
  395. if( customOutline )
  396. {
  397. if( !string.IsNullOrEmpty( VertexData ) )
  398. body.Add( "\t" + VertexData.Trim( '\t', '\n' ) );
  399. }
  400. if( (object)billboardInfo != null )
  401. {
  402. for( int j = 0; j < billboardInfo.Length; j++ )
  403. {
  404. body.Add( string.Format( BillboardInstructionFormat, billboardInfo[ j ] ) );
  405. }
  406. }
  407. switch( outlineMode )
  408. {
  409. case 0: body.Add( string.Format( OutlineVertexOffsetMode, dataCollector.UsingCustomOutlineWidth ? "outlineVar" : WidthPropertyNameInstanced ) ); break;
  410. case 1: body.Add( string.Format( OutlineVertexScaleMode, dataCollector.UsingCustomOutlineWidth ? "outlineVar" : WidthPropertyNameInstanced ) ); break;
  411. case 2: body.Add( string.Format( OutlineVertexCustomMode, dataCollector.UsingCustomOutlineWidth ? "outlineVar" : WidthPropertyNameInstanced ) ); break;
  412. }
  413. for( int i = 0; i < OutlineBodyDefaultSurfBegin.Length; i++ )
  414. {
  415. body.Add( OutlineBodyDefaultSurfBegin[ i ] );
  416. }
  417. if( dataCollector.UsingCustomOutlineColor || dataCollector.CustomOutlineSelectedAlpha > 0 )
  418. {
  419. body.Add( "\t" + Instructions.Trim( '\t', '\n' ) );
  420. }
  421. else
  422. {
  423. for( int i = 0; i < OutlineSurfBodyInstanced.Length; i++ )
  424. {
  425. body.Add( OutlineSurfBodyInstanced[ i ] );
  426. }
  427. }
  428. for( int i = 0; i < OutlineBodyDefaultSurfEnd.Length; i++ )
  429. {
  430. body.Add( OutlineBodyDefaultSurfEnd[ i ] );
  431. }
  432. }
  433. else
  434. {
  435. if( customOutline )
  436. {
  437. if( isShadowCaster )
  438. {
  439. for( int i = 0; i < UniformList.Count; i++ )
  440. {
  441. dataCollector.AddToUniforms( UniformList[ i ].NodeId, UniformList[ i ].PropertyName );
  442. }
  443. foreach( KeyValuePair<string, string> kvp in m_localFunctions )
  444. {
  445. dataCollector.AddFunction( kvp.Key, kvp.Value );
  446. }
  447. }
  448. else
  449. {
  450. if( !string.IsNullOrEmpty( Uniforms ) )
  451. body.Add( Uniforms.Trim( '\t', '\n' ) );
  452. }
  453. }
  454. if( !dataCollector.UsingCustomOutlineColor )
  455. body.Add( precision == PrecisionType.Float ? OutlineDefaultUniformColor.Replace( "half", "float" ) : OutlineDefaultUniformColor );
  456. if( !dataCollector.UsingCustomOutlineWidth )
  457. body.Add( precision == PrecisionType.Float ? OutlineDefaultUniformWidth.Replace( "half", "float" ) : OutlineDefaultUniformWidth );
  458. //Functions
  459. if( customOutline && !isShadowCaster )
  460. body.Add( Functions );
  461. if( tessOpHelper.EnableTesselation && !isShadowCaster )
  462. {
  463. body.Add( tessOpHelper.Uniforms().TrimStart( '\t' ) );
  464. body.Add( tessOpHelper.GetCurrentTessellationFunction( ref dataCollector ).Trim( '\t', '\n' ) + "\n" );
  465. }
  466. if( tessOpHelper.EnableTesselation )
  467. {
  468. body.Add( OutlineTessVertexHeader );
  469. }
  470. else
  471. {
  472. body.Add( OutlineDefaultVertexHeader );
  473. body.Add( OutlineDefaultVertexOutputDeclaration );
  474. }
  475. if( customOutline )
  476. {
  477. if( !string.IsNullOrEmpty( VertexData ) )
  478. body.Add( "\t" + VertexData.Trim( '\t', '\n' ) );
  479. }
  480. if( (object)billboardInfo != null )
  481. {
  482. for( int j = 0; j < billboardInfo.Length; j++ )
  483. {
  484. body.Add( string.Format( BillboardInstructionFormat, billboardInfo[ j ] ) );
  485. }
  486. }
  487. switch( outlineMode )
  488. {
  489. case 0: body.Add( string.Format( OutlineVertexOffsetMode, dataCollector.UsingCustomOutlineWidth ? "outlineVar" : WidthPropertyName ) ); break;
  490. case 1: body.Add( string.Format( OutlineVertexScaleMode, dataCollector.UsingCustomOutlineWidth ? "outlineVar" : WidthPropertyName ) ); break;
  491. case 2: body.Add( string.Format( OutlineVertexCustomMode, dataCollector.UsingCustomOutlineWidth ? "outlineVar" : WidthPropertyName ) ); break;
  492. }
  493. for( int i = 0; i < OutlineBodyDefaultSurfBegin.Length; i++ )
  494. {
  495. body.Add( OutlineBodyDefaultSurfBegin[ i ] );
  496. }
  497. if( dataCollector.UsingCustomOutlineColor || dataCollector.CustomOutlineSelectedAlpha > 0 )
  498. {
  499. body.Add( "\t" + Instructions.Trim( '\t', '\n' ) );
  500. }
  501. else
  502. {
  503. for( int i = 0; i < OutlineSurfBody.Length; i++ )
  504. {
  505. body.Add( OutlineSurfBody[ i ] );
  506. }
  507. }
  508. for( int i = 0; i < OutlineBodyDefaultSurfEnd.Length; i++ )
  509. {
  510. body.Add( OutlineBodyDefaultSurfEnd[ i ] );
  511. }
  512. }
  513. string[] bodyArr = body.ToArray();
  514. body.Clear();
  515. body = null;
  516. return bodyArr;
  517. }
  518. public void Destroy()
  519. {
  520. m_inputList = null;
  521. m_uniformList = null;
  522. m_instancedPropertiesList = null;
  523. m_localFunctions = null;
  524. }
  525. public bool EnableOutline { get { return m_enabled; } }
  526. public bool UsingCullMode { get { return m_cullMode != CullMode.Front; } }
  527. public bool UsingZWrite { get { return m_zWriteMode != 0; } }
  528. public bool UsingZTest { get { return m_zTestMode != 0; } }
  529. public int ZWriteMode { get { return m_zWriteMode; } set { m_zWriteMode = value; } }
  530. public int ZTestMode { get { return m_zTestMode; } set { m_zTestMode = value; } }
  531. public CullMode OutlineCullMode { get { return m_cullMode; } set { m_cullMode = value; } }
  532. public bool[] ColorMask
  533. {
  534. get { return m_colorMask; }
  535. set
  536. {
  537. if( value.Length == m_colorMask.Length )
  538. {
  539. for( int i = 0 ; i < m_colorMask.Length ; i++ )
  540. {
  541. m_colorMask[i] = value[i];
  542. }
  543. }
  544. }
  545. }
  546. public bool ActiveColorMask
  547. {
  548. get
  549. {
  550. for( int i = 0 ; i < m_colorMask.Length ; i++ )
  551. {
  552. if( !m_colorMask[ i ] )
  553. return true;
  554. }
  555. return false;
  556. }
  557. }
  558. public string Inputs { get { return m_inputs; } set { m_inputs = value; } }
  559. public string Uniforms { get { return m_uniforms; } set { m_uniforms = value; } }
  560. public string InstancedProperties { get { return m_instancedProperties; } set { m_instancedProperties = value; } }
  561. public string Instructions { get { return m_instructions; } set { m_instructions = value; } }
  562. public string Functions { get { return m_functions; } set { m_functions = value; } }
  563. public string Includes { get { return m_includes; } set { m_includes = value; } }
  564. public string Pragmas { get { return m_pragmas; } set { m_pragmas = value; } }
  565. public string Defines { get { return m_defines; } set { m_defines = value; } }
  566. public string StandardAdditionalDirectives { get { return m_standardAdditionalDirectives; } set { m_standardAdditionalDirectives = value; } }
  567. public string VertexData { get { return m_vertexData; } set { m_vertexData = value; } }
  568. public string GrabPasses { get { return m_grabPasses; } set { m_grabPasses = value; } }
  569. public List<PropertyDataCollector> InputList { get { return m_inputList; } set { m_inputList = value; } }
  570. public List<PropertyDataCollector> UniformList { get { return m_uniformList; } set { m_uniformList = value; } }
  571. public List<PropertyDataCollector> InstancedPropertiesList { get { return m_instancedPropertiesList; } set { m_instancedPropertiesList = value; } }
  572. public Dictionary<string, string> LocalFunctions { get { return m_localFunctions; } set { m_localFunctions = value; } }
  573. public bool DirtyInput { get { return m_dirtyInput; } set { m_dirtyInput = value; } }
  574. //public OutlineMode CustomMode { get { return m_customMode; } set { m_customMode = value; } }
  575. public int OffsetMode { get { return m_offsetMode; } set { m_offsetMode = value; } }
  576. public bool CustomNoFog { get { return m_customNoFog; } set { m_customNoFog = value; } }
  577. }
  578. }