using UnityEngine; using UnityEditor; using System; namespace AmplifyShaderEditor { [Serializable] [NodeAttributes( "Parallax Mapping", "UV Coordinates", "Calculates offseted UVs for parallax mapping" )] public sealed class ParallaxMappingNode : ParentNode { private enum ParallaxType { Normal, Planar } [SerializeField] private int m_selectedParallaxTypeInt = 0; [SerializeField] private ParallaxType m_selectedParallaxType = ParallaxType.Normal; private readonly string[] m_parallaxTypeStr = { "Normal", "Planar" }; private int m_cachedPropertyId = -1; private UpperLeftWidgetHelper m_upperLeftWidget = new UpperLeftWidgetHelper(); protected override void CommonInit( int uniqueId ) { base.CommonInit( uniqueId ); AddInputPort( WirePortDataType.FLOAT2, false, "UV" ); AddInputPort( WirePortDataType.FLOAT, false, "Height" ); AddInputPort( WirePortDataType.FLOAT, false, "Scale" ); AddInputPort( WirePortDataType.FLOAT3, false, "ViewDir (tan)" ); AddOutputPort( WirePortDataType.FLOAT2, "Out" ); m_useInternalPortData = true; m_autoDrawInternalPortData = true; m_autoWrapProperties = true; m_textLabelWidth = 105; UpdateTitle(); m_forceDrawPreviewAsPlane = true; m_hasLeftDropdown = true; m_previewShaderGUID = "589f12f68e00ac74286815aa56053fcc"; } public override void Destroy() { base.Destroy(); m_upperLeftWidget = null; } public override void SetPreviewInputs() { base.SetPreviewInputs(); if( m_cachedPropertyId == -1 ) m_cachedPropertyId = Shader.PropertyToID( "_ParallaxType" ); PreviewMaterial.SetFloat( m_cachedPropertyId, ( m_selectedParallaxType == ParallaxType.Normal ? 0 : 1 ) ); } public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) { base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); string textcoords = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); string height = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); string scale = m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector ); string viewDirTan = m_inputPorts[ 3 ].GeneratePortInstructions( ref dataCollector ); string localVarName = "Offset" + OutputId; string calculation = ""; switch( m_selectedParallaxType ) { default: case ParallaxType.Normal: calculation = "( ( " + height + " - 1 ) * " + viewDirTan + ".xy * " + scale + " ) + " + textcoords; break; case ParallaxType.Planar: calculation = "( ( " + height + " - 1 ) * ( " + viewDirTan + ".xy / " + viewDirTan + ".z ) * " + scale + " ) + " + textcoords; break; } dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, m_outputPorts[ 0 ].DataType, localVarName, calculation ); //dataCollector.AddToLocalVariables( UniqueId, m_currentPrecisionType, m_outputPorts[ 0 ].DataType, localVarName, calculation ); return GetOutputVectorItem( 0, outputId, localVarName ); } public override void Draw( DrawInfo drawInfo ) { base.Draw( drawInfo ); EditorGUI.BeginChangeCheck(); m_selectedParallaxTypeInt = m_upperLeftWidget.DrawWidget( this, m_selectedParallaxTypeInt, m_parallaxTypeStr ); if( EditorGUI.EndChangeCheck() ) { switch( m_selectedParallaxTypeInt ) { default: case 0: m_selectedParallaxType = ParallaxType.Normal; break; case 1: m_selectedParallaxType = ParallaxType.Planar; break; } UpdateTitle(); } } public override void DrawProperties() { base.DrawProperties(); EditorGUI.BeginChangeCheck(); m_selectedParallaxTypeInt = EditorGUILayoutPopup( "Parallax Type", m_selectedParallaxTypeInt, m_parallaxTypeStr ); if( EditorGUI.EndChangeCheck() ) { switch( m_selectedParallaxTypeInt ) { default: case 0: m_selectedParallaxType = ParallaxType.Normal; break; case 1: m_selectedParallaxType = ParallaxType.Planar; break; } UpdateTitle(); } EditorGUILayout.HelpBox( "Normal type does a cheaper approximation thats view dependent while Planar is more accurate but generates higher aliasing artifacts at steep angles.", MessageType.None ); } void UpdateTitle() { m_additionalContent.text = string.Format( Constants.SubTitleTypeFormatStr, m_parallaxTypeStr[ m_selectedParallaxTypeInt ] ); } public override void ReadFromString( ref string[] nodeParams ) { base.ReadFromString( ref nodeParams ); m_selectedParallaxType = (ParallaxType)Enum.Parse( typeof( ParallaxType ), GetCurrentParam( ref nodeParams ) ); switch( m_selectedParallaxType ) { default: case ParallaxType.Normal: m_selectedParallaxTypeInt = 0; break; case ParallaxType.Planar: m_selectedParallaxTypeInt = 1; break; } UpdateTitle(); } public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) { base.WriteToString( ref nodeInfo, ref connectionsInfo ); IOUtils.AddFieldValueToString( ref nodeInfo, m_selectedParallaxType ); } } }