diff options
Diffstat (limited to 'Assets/ThirdParty/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/BillboardOpHelper.cs')
-rw-r--r-- | Assets/ThirdParty/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/BillboardOpHelper.cs | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/Assets/ThirdParty/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/BillboardOpHelper.cs b/Assets/ThirdParty/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/BillboardOpHelper.cs new file mode 100644 index 00000000..d1391d95 --- /dev/null +++ b/Assets/ThirdParty/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/BillboardOpHelper.cs @@ -0,0 +1,242 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda <info@amplify.pt> + +// Billboard based on: +// https://gist.github.com/renaudbedard/7a90ec4a5a7359712202 +using System; +using UnityEngine; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + public enum BillboardType + { + Cylindrical, + Spherical + } + + [Serializable] + public class BillboardOpHelper + { + public static readonly string BillboardTitleStr = " Billboard"; + public static readonly string BillboardTypeStr = "Type"; + public static readonly string BillboardRotIndStr = "Ignore Rotation"; + + public static readonly string[] BillboardCylindricalInstructions = { "//Calculate new billboard vertex position and normal", + "float3 upCamVec = float3( 0, 1, 0 )"}; + + public static readonly string[] BillboardSphericalInstructions = { "//Calculate new billboard vertex position and normal", + "float3 upCamVec = normalize ( UNITY_MATRIX_V._m10_m11_m12 )"}; + + + public static readonly string[] BillboardCommonInstructions = { "float3 forwardCamVec = -normalize ( UNITY_MATRIX_V._m20_m21_m22 )", + "float3 rightCamVec = normalize( UNITY_MATRIX_V._m00_m01_m02 )", + "float4x4 rotationCamMatrix = float4x4( rightCamVec, 0, upCamVec, 0, forwardCamVec, 0, 0, 0, 0, 1 )", + "{0} = normalize( mul( float4( {0} , 0 ), rotationCamMatrix )).xyz"}; + + public static readonly string[] BillboardRotDependent = { "//This unfortunately must be made to take non-uniform scaling into account", + "//Transform to world coords, apply rotation and transform back to local", + "{0} = mul( {1} , unity_ObjectToWorld ){2}", + "{0} = mul( {1} , rotationCamMatrix ){2}", + "{0} = mul( {1} , unity_WorldToObject ){2}"}; + + + public static readonly string[] BillboardRotIndependent = { "{0}.x *= length( unity_ObjectToWorld._m00_m10_m20 )", + "{0}.y *= length( unity_ObjectToWorld._m01_m11_m21 )", + "{0}.z *= length( unity_ObjectToWorld._m02_m12_m22 )", + "{0} = mul( {0}, rotationCamMatrix )", + "{0}.xyz += unity_ObjectToWorld._m03_m13_m23", + "//Need to nullify rotation inserted by generated surface shader", + "{0} = mul( unity_WorldToObject, {0} )"}; + + + + public static readonly string[] BillboardHDRotDependent = { "//This unfortunately must be made to take non-uniform scaling into account", + "//Transform to world coords, apply rotation and transform back to local", + "{0} = mul( {1} , GetObjectToWorldMatrix() ){2}", + "{0} = mul( {1} , rotationCamMatrix ){2}", + "{0} = mul( {1} , GetWorldToObjectMatrix() ){2}"}; + + + public static readonly string[] BillboardHDRotIndependent = { "{0}.x *= length( GetObjectToWorldMatrix()._m00_m10_m20 )", + "{0}.y *= length( GetObjectToWorldMatrix()._m01_m11_m21 )", + "{0}.z *= length( GetObjectToWorldMatrix()._m02_m12_m22 )", + "{0} = mul( {0}, rotationCamMatrix )", + "{0}.xyz += GetObjectToWorldMatrix()._m03_m13_m23", + "//Need to nullify rotation inserted by generated surface shader", + "{0} = mul( GetWorldToObjectMatrix(), {0} )"}; + + + [SerializeField] + private bool m_isBillboard = false; + + [SerializeField] + private BillboardType m_billboardType = BillboardType.Cylindrical; + + [SerializeField] + private bool m_rotationIndependent = false; + + public void Draw( ParentNode owner ) + { + bool visible = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedVertexOptions; + bool enabled = m_isBillboard; + NodeUtils.DrawPropertyGroup( owner, ref visible, ref m_isBillboard, BillboardTitleStr, () => + { + m_billboardType = (BillboardType)owner.EditorGUILayoutEnumPopup( BillboardTypeStr, m_billboardType ); + m_rotationIndependent = owner.EditorGUILayoutToggle( BillboardRotIndStr, m_rotationIndependent ); + } ); + + owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedVertexOptions = visible; + if( m_isBillboard != enabled ) + { + UIUtils.RequestSave(); + } + } + public void FillDataCollectorWithInternalData( ref MasterNodeDataCollector dataCollector ) + { + if( m_isBillboard ) + { + FillDataCollector( ref dataCollector, m_billboardType, m_rotationIndependent, "v.vertex", "v.normal", false ); + } + } + // This should be called after the Vertex Offset and Vertex Normal ports are analised + public static void FillDataCollector( ref MasterNodeDataCollector dataCollector, BillboardType billboardType, bool rotationIndependent, string vertexPosValue, string vertexNormalValue, bool vertexIsFloat3 ) + { + switch( billboardType ) + { + case BillboardType.Cylindrical: + { + for( int i = 0; i < BillboardCylindricalInstructions.Length; i++ ) + { + dataCollector.AddVertexInstruction( BillboardCylindricalInstructions[ i ] + ( dataCollector.IsTemplate ? ";" : string.Empty ), -1, true ); + } + } + break; + + case BillboardType.Spherical: + { + for( int i = 0; i < BillboardCylindricalInstructions.Length; i++ ) + { + dataCollector.AddVertexInstruction( BillboardSphericalInstructions[ i ] + ( dataCollector.IsTemplate ? ";" : string.Empty ), -1, true ); + } + } + break; + } + + for( int i = 0; i < BillboardCommonInstructions.Length; i++ ) + { + string value = ( i == 3 ) ? string.Format( BillboardCommonInstructions[ i ], vertexNormalValue ) : BillboardCommonInstructions[ i ]; + dataCollector.AddVertexInstruction( value + ( dataCollector.IsTemplate ? ";" : string.Empty ), -1, true ); + } + + if( rotationIndependent ) + { + for( int i = 0; i < BillboardRotIndependent.Length; i++ ) + { + string value = string.Empty; + if( dataCollector.IsTemplate && dataCollector.TemplateDataCollectorInstance.CurrentSRPType != TemplateSRPType.BuiltIn ) + { + value = ( i != 5 ) ? string.Format( BillboardHDRotIndependent[ i ], vertexPosValue ) : BillboardHDRotIndependent[ i ]; + } + else + { + value = ( i != 5 ) ? string.Format( BillboardRotIndependent[ i ], vertexPosValue ) : BillboardRotIndependent[ i ]; + } + dataCollector.AddVertexInstruction( value + ( dataCollector.IsTemplate ? ";" : string.Empty ), -1, true ); + } + } + else + { + string vertexPosConverted = vertexIsFloat3 ? string.Format( "float4({0},0)", vertexPosValue ) : vertexPosValue; + for( int i = 0; i < BillboardRotDependent.Length; i++ ) + { + string value = string.Empty; + if( dataCollector.IsTemplate && dataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.HD ) + { + value = ( i > 1 ) ? string.Format( BillboardHDRotDependent[ i ], vertexPosValue, vertexPosConverted, ( vertexIsFloat3 ? ".xyz" : string.Empty ) ) : BillboardHDRotDependent[ i ]; + } + else + { + value = ( i > 1 ) ? string.Format( BillboardRotDependent[ i ], vertexPosValue, vertexPosConverted, ( vertexIsFloat3 ? ".xyz" : string.Empty ) ) : BillboardRotDependent[ i ]; + } + dataCollector.AddVertexInstruction( value + ( dataCollector.IsTemplate ? ";" : string.Empty ), -1, true ); + } + } + } + + public string[] GetInternalMultilineInstructions() + { + // This method is only used on Surface ... no HD variation is needed + return GetMultilineInstructions( m_billboardType, m_rotationIndependent, "v.vertex", "v.normal" ); + } + + public static string[] GetMultilineInstructions( BillboardType billboardType, bool rotationIndependent, string vertexPosValue, string vertexNormalValue ) + { + // This method is only used on Surface ... no HD variation is needed + List<string> body = new List<string>(); + switch( billboardType ) + { + case BillboardType.Cylindrical: + { + for( int i = 0; i < BillboardCylindricalInstructions.Length; i++ ) + { + body.Add( BillboardCylindricalInstructions[ i ] ); + } + } + break; + + case BillboardType.Spherical: + { + for( int i = 0; i < BillboardCylindricalInstructions.Length; i++ ) + { + body.Add( BillboardSphericalInstructions[ i ] ); + } + } + break; + } + + for( int i = 0; i < BillboardCommonInstructions.Length; i++ ) + { + string value = ( i == 3 ) ? string.Format( BillboardCommonInstructions[ i ], vertexNormalValue ) : BillboardCommonInstructions[ i ]; + body.Add( value ); + } + + if( rotationIndependent ) + { + for( int i = 0; i < BillboardRotIndependent.Length; i++ ) + { + string value = ( i != 5 ) ? string.Format( BillboardRotIndependent[ i ], vertexPosValue ) : BillboardRotIndependent[ i ]; + body.Add( value ); + } + } + else + { + for( int i = 0; i < BillboardRotDependent.Length; i++ ) + { + string value = ( i > 1 ) ? string.Format( BillboardRotDependent[ i ], vertexPosValue ) : BillboardRotDependent[ i ]; + body.Add( value ); + } + } + return body.ToArray(); + } + + public void ReadFromString( ref uint index, ref string[] nodeParams ) + { + m_isBillboard = Convert.ToBoolean( nodeParams[ index++ ] ); + m_billboardType = (BillboardType)Enum.Parse( typeof( BillboardType ), nodeParams[ index++ ] ); + if( UIUtils.CurrentShaderVersion() > 11007 ) + { + m_rotationIndependent = Convert.ToBoolean( nodeParams[ index++ ] ); + } + } + + public void WriteToString( ref string nodeInfo ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_isBillboard ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_billboardType ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_rotationIndependent ); + } + + public bool IsBillboard { get { return m_isBillboard; } } + } +} |