You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

859 lines
39 KiB

  1. // Amplify Shader Editor - Visual Shader Editing Tool
  2. // Copyright (c) Amplify Creations, Lda <info@amplify.pt>
  3. namespace AmplifyShaderEditor
  4. {
  5. public static class GeneratorUtils
  6. {
  7. public const string ObjectScaleStr = "ase_objectScale";
  8. public const string ScreenDepthStr = "ase_screenDepth";
  9. public const string ViewPositionStr = "ase_viewPos";
  10. public const string WorldViewDirectionStr = "ase_worldViewDir";
  11. public const string TangentViewDirectionStr = "ase_tanViewDir";
  12. public const string NormalizedViewDirStr = "ase_normViewDir";
  13. public const string ClipPositionStr = "ase_clipPos";
  14. public const string VertexPosition3Str = "ase_vertex3Pos";
  15. public const string VertexPosition4Str = "ase_vertex4Pos";
  16. public const string VertexNormalStr = "ase_vertexNormal";
  17. public const string VertexTangentStr = "ase_vertexTangent";
  18. public const string VertexTangentSignStr = "ase_vertexTangentSign";
  19. public const string VertexBitangentStr = "ase_vertexBitangent";
  20. public const string ScreenPositionStr = "ase_screenPos";
  21. public const string NormalizedScreenPosFormat = "float4 {0} = {1} / {1}.w;";
  22. public const string ScreenPositionNormalizedStr = "ase_screenPosNorm";
  23. public const string GrabScreenPositionStr = "ase_grabScreenPos";
  24. public const string GrabScreenPositionNormalizedStr = "ase_grabScreenPosNorm";
  25. public const string WorldPositionStr = "ase_worldPos";
  26. public const string RelativeWorldPositionStr = "ase_relWorldPos";
  27. public const string WorldLightDirStr = "ase_worldlightDir";
  28. public const string ObjectLightDirStr = "ase_objectlightDir";
  29. public const string WorldNormalStr = "ase_worldNormal";
  30. public const string NormalizedWorldNormalStr = "ase_normWorldNormal";
  31. public const string WorldReflectionStr = "ase_worldReflection";
  32. public const string WorldTangentStr = "ase_worldTangent";
  33. public const string WorldBitangentStr = "ase_worldBitangent";
  34. public const string WorldToTangentStr = "ase_worldToTangent";
  35. public const string ObjectToTangentStr = "ase_objectToTangent";
  36. public const string TangentToWorldPreciseStr = "ase_tangentToWorldPrecise";
  37. public const string TangentToWorldFastStr = "ase_tangentToWorldFast";
  38. public const string TangentToObjectStr = "ase_tangentToObject";
  39. public const string TangentToObjectFastStr = "ase_tangentToObjectFast";
  40. private const string Float3Format = "float3 {0} = {1};";
  41. private const string Float4Format = "float4 {0} = {1};";
  42. private const string GrabFunctionHeader = "inline float4 ASE_ComputeGrabScreenPos( float4 pos )";
  43. private const string GrabFunctionCall = "ASE_ComputeGrabScreenPos( {0} )";
  44. private static readonly string[] GrabFunctionBody = {
  45. "#if UNITY_UV_STARTS_AT_TOP",
  46. "float scale = -1.0;",
  47. "#else",
  48. "float scale = 1.0;",
  49. "#endif",
  50. "float4 o = pos;",
  51. "o.y = pos.w * 0.5f;",
  52. "o.y = ( pos.y - o.y ) * _ProjectionParams.x * scale + o.y;",
  53. "return o;"
  54. };
  55. // OBJECT SCALE
  56. static public string GenerateObjectScale( ref MasterNodeDataCollector dataCollector, int uniqueId )
  57. {
  58. if( dataCollector.IsTemplate )
  59. return dataCollector.TemplateDataCollectorInstance.GenerateObjectScale( ref dataCollector, uniqueId );
  60. //string value= "1/float3( length( unity_WorldToObject[ 0 ].xyz ), length( unity_WorldToObject[ 1 ].xyz ), length( unity_WorldToObject[ 2 ].xyz ) );";
  61. string value = "float3( length( unity_ObjectToWorld[ 0 ].xyz ), length( unity_ObjectToWorld[ 1 ].xyz ), length( unity_ObjectToWorld[ 2 ].xyz ) )";
  62. dataCollector.AddLocalVariable( uniqueId, PrecisionType.Float, WirePortDataType.FLOAT3, ObjectScaleStr, value );
  63. return ObjectScaleStr;
  64. }
  65. // WORLD POSITION
  66. static public string GenerateWorldPosition( ref MasterNodeDataCollector dataCollector, int uniqueId )
  67. {
  68. if( dataCollector.IsTemplate )
  69. return dataCollector.TemplateDataCollectorInstance.GetWorldPos();
  70. dataCollector.AddToInput( -1, SurfaceInputs.WORLD_POS );
  71. string result = Constants.InputVarStr + ".worldPos";
  72. if( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation )
  73. result = "mul( unity_ObjectToWorld, " + Constants.VertexShaderInputStr + ".vertex )";
  74. dataCollector.AddToLocalVariables( dataCollector.PortCategory, uniqueId, string.Format( Float3Format, WorldPositionStr, result ) );
  75. return WorldPositionStr;
  76. }
  77. // WORLD REFLECTION
  78. static public string GenerateWorldReflection( ref MasterNodeDataCollector dataCollector, int uniqueId, bool normalize = false )
  79. {
  80. if( dataCollector.IsTemplate )
  81. return dataCollector.TemplateDataCollectorInstance.GetWorldReflection( UIUtils.CurrentWindow.CurrentGraph.CurrentPrecision, true, MasterNodePortCategory.Fragment, normalize );
  82. string precisionType = UIUtils.PrecisionWirePortToCgType( UIUtils.CurrentWindow.CurrentGraph.CurrentPrecision, WirePortDataType.FLOAT3 );
  83. string result = string.Empty;
  84. if( !dataCollector.DirtyNormal )
  85. result = Constants.InputVarStr + ".worldRefl";
  86. else
  87. result = "WorldReflectionVector( " + Constants.InputVarStr + ", " + precisionType + "( 0, 0, 1 ) )";
  88. if( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation )
  89. result = "UnityObjectToWorldNormal( " + Constants.VertexShaderInputStr + ".normal )";
  90. if( normalize )
  91. {
  92. result = string.Format( "normalize( {0} )", result );
  93. }
  94. dataCollector.AddToLocalVariables( dataCollector.PortCategory, uniqueId, string.Concat( precisionType, " ", WorldReflectionStr, " = ", result, ";" ) );
  95. return WorldReflectionStr;
  96. }
  97. // WORLD NORMAL
  98. static public string GenerateWorldNormal( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precisionType, string normal, string outputId )
  99. {
  100. if( dataCollector.IsTemplate )
  101. return dataCollector.TemplateDataCollectorInstance.GetWorldNormal( uniqueId, precisionType, normal, outputId );
  102. string tanToWorld = GenerateTangentToWorldMatrixFast( ref dataCollector, uniqueId, precisionType );
  103. return string.Format( "mul({0},{1})", tanToWorld, normal );
  104. }
  105. static public string GenerateWorldNormal( ref MasterNodeDataCollector dataCollector, int uniqueId, bool normalize = false )
  106. {
  107. if( dataCollector.IsTemplate )
  108. return dataCollector.TemplateDataCollectorInstance.GetWorldNormal( UIUtils.CurrentWindow.CurrentGraph.CurrentPrecision, true, MasterNodePortCategory.Fragment, normalize );
  109. string precisionType = UIUtils.PrecisionWirePortToCgType( UIUtils.CurrentWindow.CurrentGraph.CurrentPrecision, WirePortDataType.FLOAT3 );
  110. string result = string.Empty;
  111. if( !dataCollector.DirtyNormal )
  112. result = Constants.InputVarStr + ".worldNormal";
  113. else
  114. result = "WorldNormalVector( " + Constants.InputVarStr + ", " + precisionType + "( 0, 0, 1 ) )";
  115. if( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation )
  116. result = "UnityObjectToWorldNormal( " + Constants.VertexShaderInputStr + ".normal )";
  117. dataCollector.AddToLocalVariables( dataCollector.PortCategory, uniqueId, string.Concat( precisionType, " ", WorldNormalStr, " = ", result, ";" ) );
  118. if( normalize )
  119. {
  120. dataCollector.AddToLocalVariables( dataCollector.PortCategory, uniqueId, string.Concat( precisionType, " ", NormalizedWorldNormalStr, " = normalize( ", WorldNormalStr, " );" ) );
  121. return NormalizedWorldNormalStr;
  122. }
  123. return WorldNormalStr;
  124. }
  125. // WORLD TANGENT
  126. static public string GenerateWorldTangent( ref MasterNodeDataCollector dataCollector, int uniqueId )
  127. {
  128. if( dataCollector.IsTemplate )
  129. return dataCollector.TemplateDataCollectorInstance.GetWorldTangent( UIUtils.CurrentWindow.CurrentGraph.CurrentPrecision );
  130. string precisionType = UIUtils.PrecisionWirePortToCgType( UIUtils.CurrentWindow.CurrentGraph.CurrentPrecision, WirePortDataType.FLOAT3 );
  131. string result = "WorldNormalVector( " + Constants.InputVarStr + ", " + precisionType + "( 1, 0, 0 ) )";
  132. if( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation )
  133. result = "UnityObjectToWorldDir( " + Constants.VertexShaderInputStr + ".tangent.xyz )";
  134. dataCollector.AddToLocalVariables( dataCollector.PortCategory, uniqueId, string.Concat( precisionType, " ", WorldTangentStr, " = ", result, ";" ) );
  135. return WorldTangentStr;
  136. }
  137. // WORLD BITANGENT
  138. static public string GenerateWorldBitangent( ref MasterNodeDataCollector dataCollector, int uniqueId )
  139. {
  140. if( dataCollector.IsTemplate )
  141. return dataCollector.TemplateDataCollectorInstance.GetWorldBinormal( UIUtils.CurrentWindow.CurrentGraph.CurrentPrecision );
  142. string precisionType = UIUtils.PrecisionWirePortToCgType( UIUtils.CurrentWindow.CurrentGraph.CurrentPrecision, WirePortDataType.FLOAT3 );
  143. string result = "WorldNormalVector( " + Constants.InputVarStr + ", " + precisionType + "( 0, 1, 0 ) )";
  144. if( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation )
  145. {
  146. string worldNormal = GenerateWorldNormal( ref dataCollector, uniqueId );
  147. string worldTangent = GenerateWorldTangent( ref dataCollector, uniqueId );
  148. dataCollector.AddToVertexLocalVariables( uniqueId, string.Format( "half tangentSign = {0}.tangent.w * unity_WorldTransformParams.w;", Constants.VertexShaderInputStr ) );
  149. result = "cross( " + worldNormal + ", " + worldTangent + " ) * tangentSign";
  150. }
  151. dataCollector.AddToLocalVariables( dataCollector.PortCategory, uniqueId, string.Concat( precisionType, " ", WorldBitangentStr, " = ", result, ";" ) );
  152. return WorldBitangentStr;
  153. }
  154. // OBJECT TO TANGENT MATRIX
  155. static public string GenerateObjectToTangentMatrix( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision )
  156. {
  157. string normal = GenerateVertexNormal( ref dataCollector, uniqueId, precision );
  158. string tangent = GenerateVertexTangent( ref dataCollector, uniqueId, precision, WirePortDataType.FLOAT3 );
  159. string bitangen = GenerateVertexBitangent( ref dataCollector, uniqueId, precision );
  160. dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT3x3, ObjectToTangentStr, "float3x3( " + tangent + ", " + bitangen + ", " + normal + " )" );
  161. return ObjectToTangentStr;
  162. }
  163. // TANGENT TO OBJECT
  164. //static public string GenerateTangentToObjectMatrixFast( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision )
  165. //{
  166. // string normal = GenerateVertexNormal( ref dataCollector, uniqueId, precision );
  167. // string tangent = GenerateVertexTangent( ref dataCollector, uniqueId, precision );
  168. // string bitangent = GenerateVertexBitangent( ref dataCollector, uniqueId, precision );
  169. // string result = string.Format( "float3x3({0}.x,{1}.x,{2}.x,{0}.y,{1}.y,{2}.y,{0}.z,{1}.z,{2}.z)",tangent,bitangent,normal );
  170. // dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT3x3, TangentToObjectFastStr, result );
  171. // return TangentToObjectFastStr;
  172. //}
  173. //static public string GenerateTangentToObjectMatrixPrecise( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision )
  174. //{
  175. // string objectToTangent = GenerateObjectToTangentMatrix( ref dataCollector, uniqueId, precision );
  176. // Add3x3InverseFunction( ref dataCollector, UIUtils.PrecisionWirePortToCgType( precision, WirePortDataType.FLOAT ) );
  177. // dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT3x3, TangentToObjectStr, string.Format( Inverse3x3Header, objectToTangent ) );
  178. // return TangentToObjectStr;
  179. //}
  180. // WORLD TO TANGENT MATRIX
  181. static public string GenerateWorldToTangentMatrix( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision )
  182. {
  183. if( dataCollector.IsTemplate )
  184. return dataCollector.TemplateDataCollectorInstance.GetWorldToTangentMatrix( precision );
  185. if( dataCollector.IsFragmentCategory )
  186. {
  187. dataCollector.ForceNormal = true;
  188. dataCollector.AddToInput( -1, SurfaceInputs.WORLD_NORMAL, precision );
  189. dataCollector.AddToInput( -1, SurfaceInputs.INTERNALDATA, addSemiColon: false );
  190. }
  191. string worldNormal = GenerateWorldNormal( ref dataCollector, uniqueId );
  192. string worldTangent = GenerateWorldTangent( ref dataCollector, uniqueId );
  193. string worldBitangent = GenerateWorldBitangent( ref dataCollector, uniqueId );
  194. dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT3x3, WorldToTangentStr, "float3x3( " + worldTangent + ", " + worldBitangent + ", " + worldNormal + " )" );
  195. return WorldToTangentStr;
  196. }
  197. // TANGENT TO WORLD
  198. static public string GenerateTangentToWorldMatrixFast( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision )
  199. {
  200. if( dataCollector.IsTemplate )
  201. return dataCollector.TemplateDataCollectorInstance.GetTangentToWorldMatrixFast( precision );
  202. if( dataCollector.IsFragmentCategory )
  203. {
  204. dataCollector.ForceNormal = true;
  205. dataCollector.AddToInput( -1, SurfaceInputs.WORLD_NORMAL, precision );
  206. dataCollector.AddToInput( -1, SurfaceInputs.INTERNALDATA, addSemiColon: false );
  207. }
  208. string worldNormal = GenerateWorldNormal( ref dataCollector, uniqueId );
  209. string worldTangent = GenerateWorldTangent( ref dataCollector, uniqueId );
  210. string worldBitangent = GenerateWorldBitangent( ref dataCollector, uniqueId );
  211. string result = string.Format( "float3x3({0}.x,{1}.x,{2}.x,{0}.y,{1}.y,{2}.y,{0}.z,{1}.z,{2}.z)", worldTangent, worldBitangent, worldNormal );
  212. dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT3x3, TangentToWorldFastStr, result );
  213. return TangentToWorldFastStr;
  214. }
  215. static public string GenerateTangentToWorldMatrixPrecise( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision )
  216. {
  217. if( dataCollector.IsTemplate )
  218. return dataCollector.TemplateDataCollectorInstance.GetTangentToWorldMatrixPrecise( precision );
  219. if( dataCollector.IsFragmentCategory )
  220. {
  221. dataCollector.ForceNormal = true;
  222. dataCollector.AddToInput( -1, SurfaceInputs.WORLD_NORMAL, precision );
  223. dataCollector.AddToInput( -1, SurfaceInputs.INTERNALDATA, addSemiColon: false );
  224. }
  225. string worldToTangent = GenerateWorldToTangentMatrix( ref dataCollector, uniqueId, precision );
  226. Add3x3InverseFunction( ref dataCollector, UIUtils.PrecisionWirePortToCgType( precision, WirePortDataType.FLOAT ) );
  227. dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT3x3, TangentToWorldPreciseStr, string.Format( Inverse3x3Header, worldToTangent ) );
  228. return TangentToWorldPreciseStr;
  229. }
  230. // AUTOMATIC UVS
  231. static public string GenerateAutoUVs( ref MasterNodeDataCollector dataCollector, int uniqueId, int index, string propertyName = null, WirePortDataType size = WirePortDataType.FLOAT2, string scale = null, string offset = null, string outputId = null )
  232. {
  233. string result = string.Empty;
  234. string varName = string.Empty;
  235. if( !dataCollector.IsTemplate && index > 3 )
  236. {
  237. string texCoordName = TemplateHelperFunctions.BaseInterpolatorName + index;
  238. if( dataCollector.IsFragmentCategory )
  239. {
  240. GenerateValueInVertex( ref dataCollector,uniqueId, size,PrecisionType.Float, Constants.VertexShaderInputStr + "." + texCoordName, texCoordName, true );
  241. result = Constants.InputVarStr + "." + texCoordName;
  242. }
  243. else
  244. {
  245. result = Constants.VertexShaderInputStr + "." + texCoordName;
  246. }
  247. if( !string.IsNullOrEmpty( propertyName ) )
  248. {
  249. dataCollector.AddToUniforms( uniqueId, "uniform float4 " + propertyName + "_ST;" );
  250. if( size > WirePortDataType.FLOAT2 )
  251. {
  252. dataCollector.UsingHigherSizeTexcoords = true;
  253. dataCollector.AddToLocalVariables( dataCollector.PortCategory, uniqueId, PrecisionType.Float, size, "uv" + propertyName, result );
  254. dataCollector.AddToLocalVariables( dataCollector.PortCategory, uniqueId, "uv" + propertyName + ".xy = " + result + ".xy * " + propertyName + "_ST.xy + " + propertyName + "_ST.zw;" );
  255. }
  256. else
  257. {
  258. dataCollector.AddToLocalVariables( dataCollector.PortCategory, uniqueId, PrecisionType.Float, size, "uv" + propertyName, result + " * " + propertyName + "_ST.xy + " + propertyName + "_ST.zw" );
  259. }
  260. result = "uv" + propertyName;
  261. }
  262. return result;
  263. }
  264. string indexStr = index > 0 ? ( index + 1 ).ToString() : "";
  265. if( dataCollector.PortCategory == MasterNodePortCategory.Fragment || dataCollector.PortCategory == MasterNodePortCategory.Debug )
  266. {
  267. string sizeDif = string.Empty;
  268. if( size == WirePortDataType.FLOAT3 )
  269. sizeDif = "3";
  270. else if( size == WirePortDataType.FLOAT4 )
  271. sizeDif = "4";
  272. string dummyPropUV = "_tex" + sizeDif + "coord" + indexStr;
  273. string dummyUV = "uv" + indexStr + dummyPropUV;
  274. dataCollector.AddToProperties( uniqueId, "[HideInInspector] " + dummyPropUV + "( \"\", 2D ) = \"white\" {}", 100 );
  275. dataCollector.AddToInput( uniqueId, dummyUV, size );
  276. result = Constants.InputVarStr + "." + dummyUV;
  277. }
  278. else
  279. {
  280. result = Constants.VertexShaderInputStr + ".texcoord";
  281. if( index > 0 )
  282. {
  283. result += index.ToString();
  284. }
  285. switch( size )
  286. {
  287. default:
  288. case WirePortDataType.FLOAT2:
  289. {
  290. result += ".xy";
  291. }
  292. break;
  293. case WirePortDataType.FLOAT3:
  294. {
  295. result += ".xyz";
  296. }
  297. break;
  298. case WirePortDataType.FLOAT4: break;
  299. }
  300. }
  301. varName = "uv" + indexStr + "_TexCoord" + outputId;
  302. if( !string.IsNullOrEmpty( propertyName ) )
  303. {
  304. dataCollector.AddToUniforms( uniqueId, "uniform float4 " + propertyName + "_ST;" );
  305. if( size > WirePortDataType.FLOAT2 )
  306. {
  307. dataCollector.UsingHigherSizeTexcoords = true;
  308. dataCollector.AddToLocalVariables( dataCollector.PortCategory, uniqueId, PrecisionType.Float, size, "uv" + propertyName, result );
  309. dataCollector.AddToLocalVariables( dataCollector.PortCategory, uniqueId, "uv" + propertyName + ".xy = " + result + ".xy * " + propertyName + "_ST.xy + " + propertyName + "_ST.zw;" );
  310. }
  311. else
  312. {
  313. dataCollector.AddToLocalVariables( dataCollector.PortCategory, uniqueId, PrecisionType.Float, size, "uv" + propertyName, result + " * " + propertyName + "_ST.xy + " + propertyName + "_ST.zw" );
  314. }
  315. result = "uv" + propertyName;
  316. }
  317. else if( !string.IsNullOrEmpty( scale ) || !string.IsNullOrEmpty( offset ) )
  318. {
  319. if( size > WirePortDataType.FLOAT2 )
  320. {
  321. dataCollector.UsingHigherSizeTexcoords = true;
  322. dataCollector.AddToLocalVariables( dataCollector.PortCategory, uniqueId, PrecisionType.Float, size, varName, result );
  323. dataCollector.AddToLocalVariables( dataCollector.PortCategory, uniqueId, varName + ".xy = " + result + ".xy" + ( string.IsNullOrEmpty( scale ) ? "" : " * " + scale ) + ( string.IsNullOrEmpty( offset ) ? "" : " + " + offset ) + ";" );
  324. }
  325. else
  326. {
  327. dataCollector.AddToLocalVariables( dataCollector.PortCategory, uniqueId, PrecisionType.Float, size, varName, result + ( string.IsNullOrEmpty( scale ) ? "" : " * " + scale ) + ( string.IsNullOrEmpty( offset ) ? "" : " + " + offset ) );
  328. }
  329. result = varName;
  330. }
  331. else if( dataCollector.PortCategory == MasterNodePortCategory.Fragment )
  332. {
  333. if( size > WirePortDataType.FLOAT2 )
  334. dataCollector.UsingHigherSizeTexcoords = true;
  335. }
  336. return result;
  337. }
  338. // SCREEN POSITION NORMALIZED
  339. static public string GenerateScreenPositionNormalizedForValue( string customVertexPos, string outputId, ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision, bool addInput = true )
  340. {
  341. string stringPosVar = GenerateScreenPositionForValue( customVertexPos, outputId, ref dataCollector, uniqueId, precision, addInput );
  342. string varName = ScreenPositionNormalizedStr + uniqueId;
  343. dataCollector.AddLocalVariable( uniqueId, string.Format( NormalizedScreenPosFormat, varName, stringPosVar ) );
  344. dataCollector.AddLocalVariable( uniqueId, varName + ".z = ( UNITY_NEAR_CLIP_VALUE >= 0 ) ? " + varName + ".z : " + varName + ".z * 0.5 + 0.5;" );
  345. return varName;
  346. }
  347. static public string GenerateScreenPositionNormalized( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision, bool addInput = true )
  348. {
  349. string stringPosVar = GenerateScreenPosition( ref dataCollector, uniqueId, precision, addInput );
  350. dataCollector.AddLocalVariable( uniqueId, string.Format( NormalizedScreenPosFormat, ScreenPositionNormalizedStr, stringPosVar ) );
  351. dataCollector.AddLocalVariable( uniqueId, ScreenPositionNormalizedStr + ".z = ( UNITY_NEAR_CLIP_VALUE >= 0 ) ? " + ScreenPositionNormalizedStr + ".z : " + ScreenPositionNormalizedStr + ".z * 0.5 + 0.5;" );
  352. return ScreenPositionNormalizedStr;
  353. }
  354. // SCREEN POSITION
  355. static public string GenerateScreenPositionForValue( string customVertexPosition, string outputId, ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision, bool addInput = true )
  356. {
  357. if( dataCollector.IsTemplate )
  358. return dataCollector.TemplateDataCollectorInstance.GetScreenPosForValue( customVertexPosition, outputId );
  359. string value = GenerateVertexScreenPositionForValue( customVertexPosition, outputId, ref dataCollector, uniqueId, precision );
  360. string screenPosVarName = "screenPosition" + outputId;
  361. dataCollector.AddToInput( uniqueId, screenPosVarName, WirePortDataType.FLOAT4, precision );
  362. dataCollector.AddToVertexLocalVariables( uniqueId, Constants.VertexShaderOutputStr + "." + screenPosVarName + " = " + value + ";" );
  363. string screenPosVarNameOnFrag = ScreenPositionStr + outputId;
  364. string globalResult = Constants.InputVarStr + "." + screenPosVarName;
  365. dataCollector.AddLocalVariable( uniqueId, string.Format( "float4 {0} = {1};", screenPosVarNameOnFrag, globalResult ) );
  366. return screenPosVarNameOnFrag;
  367. }
  368. static public string GenerateScreenPosition( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision, bool addInput = true )
  369. {
  370. if( dataCollector.UsingCustomScreenPos && dataCollector.IsFragmentCategory )
  371. {
  372. string value = GenerateVertexScreenPosition( ref dataCollector, uniqueId, precision );
  373. dataCollector.AddToInput( uniqueId, "screenPosition", WirePortDataType.FLOAT4, precision );
  374. dataCollector.AddToVertexLocalVariables( uniqueId, Constants.VertexShaderOutputStr + ".screenPosition = " + value + ";" );
  375. string globalResult = Constants.InputVarStr + ".screenPosition";
  376. dataCollector.AddLocalVariable( uniqueId, string.Format( "float4 {0} = {1};", ScreenPositionStr, globalResult ) );
  377. return ScreenPositionStr;
  378. }
  379. else
  380. {
  381. if( !dataCollector.IsFragmentCategory )
  382. return GenerateVertexScreenPosition( ref dataCollector, uniqueId, precision );
  383. if( dataCollector.IsTemplate )
  384. return dataCollector.TemplateDataCollectorInstance.GetScreenPos();
  385. }
  386. if( addInput )
  387. dataCollector.AddToInput( uniqueId, SurfaceInputs.SCREEN_POS, precision );
  388. string result = Constants.InputVarStr + ".screenPos";
  389. dataCollector.AddLocalVariable( uniqueId, string.Format( "float4 {0} = float4( {1}.xyz , {1}.w + 0.00000000001 );", ScreenPositionStr, result ) );
  390. return ScreenPositionStr;
  391. }
  392. // GRAB SCREEN POSITION
  393. static public string GenerateGrabScreenPosition( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision, bool addInput = true, string customScreenPos = null )
  394. {
  395. string screenPos = string.Empty;
  396. if( string.IsNullOrEmpty( customScreenPos ) )
  397. screenPos = GenerateScreenPosition( ref dataCollector, uniqueId, precision, addInput );
  398. else
  399. screenPos = customScreenPos;
  400. string computeBody = string.Empty;
  401. IOUtils.AddFunctionHeader( ref computeBody, GrabFunctionHeader );
  402. foreach( string line in GrabFunctionBody )
  403. IOUtils.AddFunctionLine( ref computeBody, line );
  404. IOUtils.CloseFunctionBody( ref computeBody );
  405. string functionResult = dataCollector.AddFunctions( GrabFunctionCall, computeBody, screenPos );
  406. dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT4, GrabScreenPositionStr, functionResult );
  407. return GrabScreenPositionStr;
  408. }
  409. // GRAB SCREEN POSITION NORMALIZED
  410. static public string GenerateGrabScreenPositionNormalized( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision, bool addInput = true, string customScreenPos = null )
  411. {
  412. string stringPosVar = GenerateGrabScreenPosition( ref dataCollector, uniqueId, precision, addInput, customScreenPos );
  413. dataCollector.AddLocalVariable( uniqueId, string.Format( "float4 {0} = {1} / {1}.w;", GrabScreenPositionNormalizedStr, stringPosVar ) );
  414. return GrabScreenPositionNormalizedStr;
  415. }
  416. // SCREEN POSITION ON VERT
  417. static public string GenerateVertexScreenPositionForValue( string customVertexPosition, string outputId, ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision )
  418. {
  419. if( dataCollector.IsTemplate )
  420. return dataCollector.TemplateDataCollectorInstance.GetScreenPosForValue( customVertexPosition, outputId );
  421. string screenPosVarName = ScreenPositionStr + outputId;
  422. string value = string.Format( "ComputeScreenPos( UnityObjectToClipPos( {0} ) )", customVertexPosition );
  423. dataCollector.AddToVertexLocalVariables( uniqueId, precision, WirePortDataType.FLOAT4, screenPosVarName, value );
  424. return screenPosVarName;
  425. }
  426. static public string GenerateVertexScreenPosition( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision )
  427. {
  428. if( dataCollector.IsTemplate )
  429. return dataCollector.TemplateDataCollectorInstance.GetScreenPos();
  430. string value = string.Format( "ComputeScreenPos( UnityObjectToClipPos( {0}.vertex ) )", Constants.VertexShaderInputStr );
  431. dataCollector.AddToVertexLocalVariables( uniqueId, precision, WirePortDataType.FLOAT4, ScreenPositionStr, value );
  432. return ScreenPositionStr;
  433. }
  434. // VERTEX POSITION
  435. static public string GenerateVertexPosition( ref MasterNodeDataCollector dataCollector, int uniqueId, WirePortDataType size )
  436. {
  437. string value = Constants.VertexShaderInputStr + ".vertex";
  438. if( size == WirePortDataType.FLOAT3 )
  439. value += ".xyz";
  440. if( dataCollector.PortCategory == MasterNodePortCategory.Fragment || dataCollector.PortCategory == MasterNodePortCategory.Debug )
  441. {
  442. dataCollector.AddToInput( uniqueId, SurfaceInputs.WORLD_POS );
  443. dataCollector.AddToIncludes( uniqueId, Constants.UnityShaderVariables );
  444. value = "mul( unity_WorldToObject, float4( " + Constants.InputVarStr + ".worldPos , 1 ) )";
  445. }
  446. string varName = VertexPosition4Str;
  447. if( size == WirePortDataType.FLOAT3 )
  448. varName = VertexPosition3Str;
  449. dataCollector.AddLocalVariable( uniqueId, PrecisionType.Float, size, varName, value );
  450. return varName;
  451. }
  452. // VERTEX NORMAL
  453. static public string GenerateVertexNormal( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision )
  454. {
  455. if( dataCollector.MasterNodeCategory == AvailableShaderTypes.Template )
  456. {
  457. return dataCollector.TemplateDataCollectorInstance.GetVertexNormal( UIUtils.CurrentWindow.CurrentGraph.CurrentPrecision );
  458. }
  459. string value = Constants.VertexShaderInputStr + ".normal.xyz";
  460. if( dataCollector.PortCategory == MasterNodePortCategory.Fragment || dataCollector.PortCategory == MasterNodePortCategory.Debug )
  461. {
  462. GenerateWorldNormal( ref dataCollector, uniqueId );
  463. dataCollector.AddToLocalVariables( uniqueId, precision, WirePortDataType.FLOAT3, VertexNormalStr, "mul( unity_WorldToObject, float4( " + WorldNormalStr + ", 0 ) )" );
  464. }
  465. else
  466. {
  467. dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT3, VertexNormalStr, value );
  468. }
  469. return VertexNormalStr;
  470. }
  471. // VERTEX TANGENT
  472. static public string GenerateVertexTangent( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision, WirePortDataType size )
  473. {
  474. if( dataCollector.MasterNodeCategory == AvailableShaderTypes.Template )
  475. {
  476. return dataCollector.TemplateDataCollectorInstance.GetVertexTangent( UIUtils.CurrentWindow.CurrentGraph.CurrentPrecision );
  477. }
  478. if( dataCollector.PortCategory == MasterNodePortCategory.Fragment || dataCollector.PortCategory == MasterNodePortCategory.Debug )
  479. {
  480. GenerateWorldTangent( ref dataCollector, uniqueId );
  481. dataCollector.AddToLocalVariables( uniqueId, precision, WirePortDataType.FLOAT4, VertexTangentStr, "mul( unity_WorldToObject, float4( " + WorldTangentStr + ", 0 ) )" );
  482. }
  483. else
  484. {
  485. string value = Constants.VertexShaderInputStr + ".tangent";
  486. dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT4, VertexTangentStr, value );
  487. }
  488. return (size== WirePortDataType.FLOAT4)?VertexTangentStr: VertexTangentStr+".xyz";
  489. }
  490. // VERTEX TANGENT SIGN
  491. static public string GenerateVertexTangentSign( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision )
  492. {
  493. if( dataCollector.MasterNodeCategory == AvailableShaderTypes.Template )
  494. {
  495. return dataCollector.TemplateDataCollectorInstance.GetTangentSign( UIUtils.CurrentWindow.CurrentGraph.CurrentPrecision );
  496. }
  497. string value = Constants.VertexShaderInputStr + ".tangent.w";
  498. if( dataCollector.IsFragmentCategory )
  499. {
  500. dataCollector.AddToInput( uniqueId, VertexTangentSignStr, WirePortDataType.FLOAT, PrecisionType.Half );
  501. dataCollector.AddToVertexLocalVariables( uniqueId, Constants.VertexShaderOutputStr + "." + VertexTangentSignStr + " = " + Constants.VertexShaderInputStr + ".tangent.w;" );
  502. return Constants.InputVarStr + "." + VertexTangentSignStr;
  503. }
  504. else
  505. {
  506. dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT, VertexTangentSignStr, value );
  507. }
  508. return VertexTangentSignStr;
  509. }
  510. // VERTEX BITANGENT
  511. static public string GenerateVertexBitangent( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision )
  512. {
  513. if( dataCollector.MasterNodeCategory == AvailableShaderTypes.Template )
  514. {
  515. return dataCollector.TemplateDataCollectorInstance.GetVertexBitangent( UIUtils.CurrentWindow.CurrentGraph.CurrentPrecision );
  516. }
  517. if( dataCollector.PortCategory == MasterNodePortCategory.Fragment || dataCollector.PortCategory == MasterNodePortCategory.Debug )
  518. {
  519. GenerateWorldBitangent( ref dataCollector, uniqueId );
  520. dataCollector.AddToLocalVariables( uniqueId, precision, WirePortDataType.FLOAT3, VertexBitangentStr, "mul( unity_WorldToObject, float4( " + WorldBitangentStr + ", 0 ) )" );
  521. }
  522. else
  523. {
  524. GenerateVertexNormal( ref dataCollector, uniqueId, precision );
  525. GenerateVertexTangent( ref dataCollector, uniqueId, precision , WirePortDataType.FLOAT3 );
  526. dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT3, VertexBitangentStr, "cross( " + VertexNormalStr + ", " + VertexTangentStr + ") * " + Constants.VertexShaderInputStr + ".tangent.w * unity_WorldTransformParams.w" );
  527. }
  528. return VertexBitangentStr;
  529. }
  530. // VERTEX POSITION ON FRAG
  531. static public string GenerateVertexPositionOnFrag( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision )
  532. {
  533. dataCollector.AddToInput( uniqueId, SurfaceInputs.WORLD_POS );
  534. dataCollector.AddToIncludes( uniqueId, Constants.UnityShaderVariables );
  535. string value = "mul( unity_WorldToObject, float4( " + Constants.InputVarStr + ".worldPos , 1 ) )";
  536. dataCollector.AddToLocalVariables( uniqueId, precision, WirePortDataType.FLOAT4, VertexPosition4Str, value );
  537. return VertexPosition4Str;
  538. }
  539. // CLIP POSITION ON FRAG
  540. static public string GenerateClipPositionOnFrag( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision )
  541. {
  542. if( dataCollector.IsTemplate )
  543. return dataCollector.TemplateDataCollectorInstance.GetClipPos();
  544. string vertexName = GenerateVertexPositionOnFrag( ref dataCollector, uniqueId, precision );
  545. string value = string.Format( "ComputeScreenPos( UnityObjectToClipPos( {0} ) )", vertexName );
  546. dataCollector.AddToLocalVariables( uniqueId, precision, WirePortDataType.FLOAT4, ClipPositionStr, value );
  547. return ClipPositionStr;
  548. }
  549. // VIEW DIRECTION
  550. static public string GenerateViewDirection( ref MasterNodeDataCollector dataCollector, int uniqueId, ViewSpace space = ViewSpace.World )
  551. {
  552. if( dataCollector.IsTemplate )
  553. return ( space == ViewSpace.Tangent ) ? dataCollector.TemplateDataCollectorInstance.GetTangentViewDir( UIUtils.CurrentWindow.CurrentGraph.CurrentPrecision ) : dataCollector.TemplateDataCollectorInstance.GetViewDir();
  554. PrecisionType precision = UIUtils.CurrentWindow.CurrentGraph.CurrentPrecision;
  555. string worldPos = GenerateWorldPosition( ref dataCollector, uniqueId );
  556. string safeNormalizeInstruction = string.Empty;
  557. if( dataCollector.SafeNormalizeViewDir )
  558. {
  559. if( dataCollector.IsTemplate && dataCollector.IsSRP )
  560. {
  561. safeNormalizeInstruction = "SafeNormalize";
  562. }
  563. else
  564. {
  565. if( dataCollector.IsTemplate )
  566. dataCollector.AddToIncludes( -1, Constants.UnityBRDFLib );
  567. safeNormalizeInstruction = "Unity_SafeNormalize";
  568. }
  569. }
  570. dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT3, WorldViewDirectionStr, ( dataCollector.SafeNormalizeViewDir ? safeNormalizeInstruction : "normalize" ) + "( UnityWorldSpaceViewDir( " + worldPos + " ) )" );
  571. if( space == ViewSpace.Tangent )
  572. {
  573. string worldToTangent = GenerateWorldToTangentMatrix( ref dataCollector, uniqueId, precision );
  574. dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT3, TangentViewDirectionStr, "mul( " + worldToTangent + ", " + WorldViewDirectionStr + " )" );
  575. return TangentViewDirectionStr;
  576. }
  577. else
  578. {
  579. return WorldViewDirectionStr;
  580. }
  581. }
  582. // VIEW POS
  583. static public string GenerateViewPositionOnFrag( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision )
  584. {
  585. if( dataCollector.IsTemplate )
  586. UnityEngine.Debug.LogWarning( "View Pos not implemented on Templates" );
  587. string vertexName = GenerateVertexPositionOnFrag( ref dataCollector, uniqueId, precision );
  588. string value = string.Format( "UnityObjectToViewPos( {0} )", vertexName );
  589. dataCollector.AddToLocalVariables( uniqueId, precision, WirePortDataType.FLOAT3, ViewPositionStr, value );
  590. return ViewPositionStr;
  591. }
  592. // SCREEN DEPTH
  593. static public string GenerateScreenDepthOnFrag( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision )
  594. {
  595. if( dataCollector.IsTemplate )
  596. UnityEngine.Debug.LogWarning( "Screen Depth not implemented on Templates" );
  597. string viewPos = GenerateViewPositionOnFrag( ref dataCollector, uniqueId, precision );
  598. string value = string.Format( "-{0}.z", viewPos );
  599. dataCollector.AddToLocalVariables( uniqueId, precision, WirePortDataType.FLOAT, ScreenDepthStr, value );
  600. return ScreenDepthStr;
  601. }
  602. // LIGHT DIRECTION WORLD
  603. static public string GenerateWorldLightDirection( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision )
  604. {
  605. dataCollector.AddToIncludes( uniqueId, Constants.UnityCgLibFuncs );
  606. string worldPos = GeneratorUtils.GenerateWorldPosition( ref dataCollector, uniqueId );
  607. dataCollector.AddLocalVariable( uniqueId, "#if defined(LIGHTMAP_ON) && UNITY_VERSION < 560 //aseld" );
  608. dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT3, WorldLightDirStr, "0" );
  609. dataCollector.AddLocalVariable( uniqueId, "#else //aseld" );
  610. dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT3, WorldLightDirStr, ( dataCollector.SafeNormalizeLightDir ? "Unity_SafeNormalize" : "normalize" ) + "( UnityWorldSpaceLightDir( " + worldPos + " ) )" );
  611. dataCollector.AddLocalVariable( uniqueId, "#endif //aseld" );
  612. return WorldLightDirStr;
  613. }
  614. // LIGHT DIRECTION Object
  615. static public string GenerateObjectLightDirection( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision, string vertexPos )
  616. {
  617. dataCollector.AddToIncludes( uniqueId, Constants.UnityCgLibFuncs );
  618. dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT3, ObjectLightDirStr, "normalize( ObjSpaceLightDir( " + vertexPos + " ) )" );
  619. return ObjectLightDirStr;
  620. }
  621. //MATRIX INVERSE
  622. // 3x3
  623. public static string Inverse3x3Header = "Inverse3x3( {0} )";
  624. public static string[] Inverse3x3Function =
  625. {
  626. "{0}3x3 Inverse3x3({0}3x3 input)\n",
  627. "{\n",
  628. "\t{0}3 a = input._11_21_31;\n",
  629. "\t{0}3 b = input._12_22_32;\n",
  630. "\t{0}3 c = input._13_23_33;\n",
  631. "\treturn {0}3x3(cross(b,c), cross(c,a), cross(a,b)) * (1.0 / dot(a,cross(b,c)));\n",
  632. "}\n"
  633. };
  634. public static bool[] Inverse3x3FunctionFlags =
  635. {
  636. true,
  637. false,
  638. true,
  639. true,
  640. true,
  641. true,
  642. false
  643. };
  644. public static void Add3x3InverseFunction( ref MasterNodeDataCollector dataCollector, string precisionString )
  645. {
  646. if( !dataCollector.HasFunction( Inverse3x3Header ) )
  647. {
  648. //Hack to be used util indent is properly used
  649. int currIndent = UIUtils.ShaderIndentLevel;
  650. if( dataCollector.IsTemplate )
  651. {
  652. UIUtils.ShaderIndentLevel = 0;
  653. }
  654. else
  655. {
  656. UIUtils.ShaderIndentLevel = 1;
  657. UIUtils.ShaderIndentLevel++;
  658. }
  659. string finalFunction = string.Empty;
  660. for( int i = 0; i < Inverse3x3Function.Length; i++ )
  661. {
  662. finalFunction += UIUtils.ShaderIndentTabs + ( Inverse3x3FunctionFlags[ i ] ? string.Format( Inverse3x3Function[ i ], precisionString ) : Inverse3x3Function[ i ] );
  663. }
  664. UIUtils.ShaderIndentLevel = currIndent;
  665. dataCollector.AddFunction( Inverse3x3Header, finalFunction );
  666. }
  667. }
  668. public static string GenerateValueInVertex( ref MasterNodeDataCollector dataCollector, int uniqueId, WirePortDataType dataType, PrecisionType currentPrecisionType, string dataValue, string dataName, bool createInterpolator )
  669. {
  670. if( !dataCollector.IsFragmentCategory )
  671. return dataValue;
  672. //TEMPLATES
  673. if( dataCollector.IsTemplate )
  674. {
  675. if( createInterpolator && dataCollector.TemplateDataCollectorInstance.HasCustomInterpolatedData( dataName ) )
  676. return dataName;
  677. MasterNodePortCategory category = dataCollector.PortCategory;
  678. dataCollector.PortCategory = MasterNodePortCategory.Vertex;
  679. dataCollector.PortCategory = category;
  680. if( createInterpolator )
  681. {
  682. dataCollector.TemplateDataCollectorInstance.RegisterCustomInterpolatedData( dataName, dataType, currentPrecisionType, dataValue );
  683. }
  684. else
  685. {
  686. dataCollector.AddToVertexLocalVariables( -1, currentPrecisionType, dataType, dataName, dataValue );
  687. }
  688. return dataName;
  689. }
  690. //SURFACE
  691. {
  692. if( dataCollector.TesselationActive )
  693. {
  694. UIUtils.ShowMessage( "Unable to use Vertex to Frag when Tessellation is active" );
  695. switch( dataType )
  696. {
  697. case WirePortDataType.FLOAT2:
  698. {
  699. return "(0).xx";
  700. }
  701. case WirePortDataType.FLOAT3:
  702. {
  703. return "(0).xxx";
  704. }
  705. case WirePortDataType.FLOAT4:
  706. case WirePortDataType.COLOR:
  707. {
  708. return "(0).xxxx";
  709. }
  710. }
  711. return "0";
  712. }
  713. if( createInterpolator )
  714. dataCollector.AddToInput( uniqueId, dataName, dataType, currentPrecisionType );
  715. MasterNodePortCategory portCategory = dataCollector.PortCategory;
  716. dataCollector.PortCategory = MasterNodePortCategory.Vertex;
  717. if( createInterpolator )
  718. {
  719. dataCollector.AddLocalVariable( uniqueId, Constants.VertexShaderOutputStr + "." + dataName, dataValue + ";" );
  720. }
  721. else
  722. {
  723. dataCollector.AddLocalVariable( uniqueId, currentPrecisionType, dataType, dataName, dataValue );
  724. }
  725. dataCollector.PortCategory = portCategory;
  726. return createInterpolator ? Constants.InputVarStr + "." + dataName : dataName;
  727. }
  728. }
  729. }
  730. }