public void RegisterCustomInterpolatedData(string name, WirePortDataType dataType, PrecisionType precision, string vertexInstruction, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment)
        {
            MasterNodePortCategory category = useMasterNodeCategory ? m_currentDataCollector.PortCategory : customCategory;

            if (!m_customInterpolatedData.ContainsKey(name))
            {
                m_customInterpolatedData.Add(name, new TemplateCustomData(name, dataType));
            }

            if (!m_customInterpolatedData[name].IsVertex)
            {
                m_customInterpolatedData[name].IsVertex = true;
                m_currentDataCollector.AddToVertexLocalVariables(-1, precision, dataType, name, vertexInstruction);
            }
            if (category == MasterNodePortCategory.Fragment)
            {
                if (!m_customInterpolatedData[name].IsFragment)
                {
                    m_customInterpolatedData[name].IsFragment = true;
                    TemplateVertexData interpData = RequestNewInterpolator(dataType, false);
                    if (interpData == null)
                    {
                        Debug.LogErrorFormat("Could not assign interpolator of type {0} to variable {1}", dataType, name);
                        return;
                    }
                    m_currentDataCollector.AddToVertexLocalVariables(-1, m_currentTemplateData.VertexFunctionData.OutVarName + "." + interpData.VarNameWithSwizzle, name);
                    m_currentDataCollector.AddToLocalVariables(-1, precision, dataType, name, m_currentTemplateData.FragFunctionData.InVarName + "." + interpData.VarNameWithSwizzle);
                }
            }
        }
Exemple #2
0
        public override string GenerateShaderForOutput(int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar)
        {
            if (dataCollector.IsTemplate)
            {
                if (!dataCollector.IsSRP)
                {
                    return(dataCollector.TemplateDataCollectorInstance.GetLightAtten(UniqueId));;
                }
                else
                {
                    if (dataCollector.CurrentSRPType == TemplateSRPType.Lightweight)
                    {
                        if (dataCollector.HasLocalVariable(LightweightLightAttenDecl))
                        {
                            return(ASEAttenVarName);
                        }

                        // Pragmas
                        for (int i = 0; i < LightweightPragmaMultiCompiles.Length; i++)
                        {
                            dataCollector.AddToPragmas(UniqueId, LightweightPragmaMultiCompiles[i]);
                        }

                        // Vertex Instructions
                        TemplateVertexData shadowCoordsData   = dataCollector.TemplateDataCollectorInstance.RequestNewInterpolator(WirePortDataType.FLOAT4, false);
                        string             vertexInterpName   = dataCollector.TemplateDataCollectorInstance.CurrentTemplateData.VertexFunctionData.OutVarName;
                        string             vertexShadowCoords = vertexInterpName + "." + shadowCoordsData.VarNameWithSwizzle;
                        string             vertexPos          = dataCollector.TemplateDataCollectorInstance.GetVertexPosition(WirePortDataType.FLOAT3, PrecisionType.Float, false, MasterNodePortCategory.Vertex);

                        dataCollector.AddToVertexLocalVariables(UniqueId, string.Format(LightweightVertexInstructions[0], vertexPos));
                        dataCollector.AddToVertexLocalVariables(UniqueId, LightweightVertexInstructions[1]);
                        dataCollector.AddToVertexLocalVariables(UniqueId, string.Format(LightweightVertexInstructions[2], vertexShadowCoords));
                        dataCollector.AddToVertexLocalVariables(UniqueId, LightweightVertexInstructions[3]);

                        // Fragment Instructions
                        string fragmentInterpName   = dataCollector.TemplateDataCollectorInstance.CurrentTemplateData.FragmentFunctionData.InVarName;
                        string fragmentShadowCoords = fragmentInterpName + "." + shadowCoordsData.VarNameWithSwizzle;

                        dataCollector.AddLocalVariable(UniqueId, LightweightLightAttenDecl);
                        dataCollector.AddLocalVariable(UniqueId, string.Format(LightweightFragmentInstructions[0], fragmentShadowCoords));
                        dataCollector.AddLocalVariable(UniqueId, LightweightFragmentInstructions[1]);
                        return(ASEAttenVarName);
                    }
                    else
                    {
                        UIUtils.ShowMessage(UniqueId, "Light Attenuation node currently not supported on HDRP");
                        return("1");
                    }
                }
            }

            if (dataCollector.GenType == PortGenType.NonCustomLighting || dataCollector.CurrentCanvasMode != NodeAvailability.CustomLighting)
            {
                UIUtils.ShowMessage(UniqueId, "Light Attenuation node currently not supported on non-custom lighting surface shaders");
                return("1");
            }

            dataCollector.UsingLightAttenuation = true;
            return(ASEAttenVarName);
        }
        TemplateVertexData RegisterOnInterpolator(TemplateSemantics semantics, WirePortDataType dataType)
        {
            TemplateVertexData data = new TemplateVertexData(semantics, dataType, TemplateHelperFunctions.SemanticsDefaultName[semantics]);

            m_interpolatorData.Interpolators.Add(data);
            string interpolator = string.Format(TemplateHelperFunctions.InterpFullSemantic, UIUtils.WirePortToCgType(dataType), data.VarName, data.Semantics);

            m_currentDataCollector.AddToInterpolators(interpolator);
            return(data);
        }
Exemple #4
0
 public TemplateVertexData(TemplateVertexData other)
 {
     m_semantics          = other.m_semantics;
     m_dataType           = other.m_dataType;
     m_varName            = other.m_varName;
     m_dataInfo           = other.m_dataInfo;
     m_dataSwizzle        = other.m_dataSwizzle;
     m_available          = other.m_available;
     m_varNameWithSwizzle = other.m_varNameWithSwizzle;
 }
        public static List <TemplateVertexData> CreateVertexDataList(string vertexData, string parametersBody)
        {
            List <TemplateVertexData> vertexDataList = null;
            Dictionary <TemplateSemantics, TemplateVertexData> vertexDataDict = null;

            foreach (Match match in Regex.Matches(vertexData, VertexDataPattern))
            {
                if (match.Groups.Count > 1)
                {
                    if (vertexDataList == null)
                    {
                        vertexDataList = new List <TemplateVertexData>();
                        vertexDataDict = new Dictionary <TemplateSemantics, TemplateVertexData>();
                    }

                    WirePortDataType   dataType           = CgToWirePortType[match.Groups[1].Value];
                    string             varName            = match.Groups[2].Value;
                    TemplateSemantics  semantics          = (TemplateSemantics)Enum.Parse(typeof(TemplateSemantics), match.Groups[3].Value);
                    TemplateVertexData templateVertexData = new TemplateVertexData(semantics, dataType, varName);
                    vertexDataList.Add(templateVertexData);
                    vertexDataDict.Add(semantics, templateVertexData);
                }
            }

            string[] paramsArray = parametersBody.Split(IOUtils.FIELD_SEPARATOR);
            if (paramsArray.Length > 0)
            {
                for (int i = 0; i < paramsArray.Length; i++)
                {
                    string[] paramDataArr = paramsArray[i].Split(IOUtils.VALUE_SEPARATOR);
                    if (paramDataArr.Length == 2)
                    {
                        string[]          swizzleInfoArr = paramDataArr[1].Split(IOUtils.FLOAT_SEPARATOR);
                        TemplateSemantics semantic       = ShortcutToSemantic[swizzleInfoArr[0]];
                        if (vertexDataDict.ContainsKey(semantic))
                        {
                            TemplateVertexData templateVertexData = vertexDataDict[semantic];
                            if (templateVertexData != null)
                            {
                                if (swizzleInfoArr.Length > 1)
                                {
                                    templateVertexData.DataSwizzle = "." + swizzleInfoArr[1];
                                }
                                templateVertexData.DataInfo  = ShortcutToInfo[paramDataArr[0]];
                                templateVertexData.Available = true;
                            }
                        }
                    }
                }
            }

            vertexDataDict.Clear();
            vertexDataDict = null;
            return(vertexDataList);
        }
 public TemplateVertexData(TemplateVertexData other)
 {
     m_semantics          = other.m_semantics;
     m_dataType           = other.m_dataType;
     m_varName            = other.m_varName;
     m_dataInfo           = other.m_dataInfo;
     m_dataSwizzle        = other.m_dataSwizzle;
     m_available          = other.m_available;
     m_varNameWithSwizzle = other.m_varNameWithSwizzle;
     m_isSingleComponent  = other.IsSingleComponent;
     for (int i = 0; i < 4; i++)
     {
         m_components[i] = other.Components[i];
     }
 }
 public TemplateVertexData RequestNewInterpolator(WirePortDataType dataType, bool isColor)
 {
     for (int i = 0; i < m_interpolatorData.AvailableInterpolators.Count; i++)
     {
         if (!m_interpolatorData.AvailableInterpolators[i].IsFull)
         {
             TemplateVertexData data = m_interpolatorData.AvailableInterpolators[i].RequestChannels(dataType, isColor);
             if (data != null)
             {
                 if (m_interpolatorData.AvailableInterpolators[i].Usage == 1)
                 {
                     // First time using this interpolator, so we need to register it
                     string interpolator = string.Format(TemplateHelperFunctions.TexFullSemantic,
                                                         data.VarName, data.Semantics);
                     m_currentDataCollector.AddToInterpolators(interpolator);
                 }
                 return(data);
             }
         }
     }
     return(null);
 }
        public static TemplateInterpData CreateInterpDataList(string interpData, string fullLine)
        {
            TemplateInterpData        interpDataObj  = null;
            List <TemplateVertexData> interpDataList = null;
            Dictionary <TemplateSemantics, TemplateVertexData> interpDataDict = null;
            Match rangeMatch = Regex.Match(fullLine, InterpRangePattern);

            if (rangeMatch.Groups.Count > 0)
            {
                interpDataObj = new TemplateInterpData();
                // Get range of available interpolators
                int minVal = 0;
                int maxVal = 0;
                try
                {
                    string[] minValArgs = rangeMatch.Groups[1].Value.Split(IOUtils.FLOAT_SEPARATOR);
                    minVal = Convert.ToInt32(minValArgs[0]);
                    maxVal = Convert.ToInt32(rangeMatch.Groups[2].Value);
                    if (minVal > maxVal)
                    {
                        int aux = minVal;
                        minVal = maxVal;
                        maxVal = aux;
                    }
                    for (int i = minVal; i <= maxVal; i++)
                    {
                        interpDataObj.AvailableInterpolators.Add(new TemplateInterpElement(IntToSemantic[i]));
                    }
                    if (minValArgs.Length > 1)
                    {
                        interpDataObj.AvailableInterpolators[0].SetAvailableChannelsFromString(minValArgs[1]);
                    }
                }
                catch (Exception e)
                {
                    Debug.LogException(e);
                }

                //Get Current interpolators
                int    parametersBeginIdx = fullLine.IndexOf(":") + 1;
                int    parametersEnd      = fullLine.IndexOf(TemplatesManager.TemplateEndOfLine);
                string parametersBody     = fullLine.Substring(parametersBeginIdx, parametersEnd - parametersBeginIdx);

                foreach (Match match in Regex.Matches(interpData, VertexDataPattern))
                {
                    if (match.Groups.Count > 1)
                    {
                        if (interpDataList == null)
                        {
                            interpDataList = new List <TemplateVertexData>();
                            interpDataDict = new Dictionary <TemplateSemantics, TemplateVertexData>();
                        }

                        WirePortDataType   dataType           = CgToWirePortType[match.Groups[1].Value];
                        string             varName            = match.Groups[2].Value;
                        TemplateSemantics  semantics          = (TemplateSemantics)Enum.Parse(typeof(TemplateSemantics), match.Groups[3].Value);
                        TemplateVertexData templateVertexData = new TemplateVertexData(semantics, dataType, varName);
                        //interpDataList.Add( templateVertexData );
                        interpDataDict.Add(semantics, templateVertexData);
                        //Check if they are also on the free channels list and update their names
                        interpDataObj.ReplaceNameOnInterpolator(semantics, varName);
                    }
                }

                // Get info for available interpolators
                string[] paramsArray = parametersBody.Split(IOUtils.FIELD_SEPARATOR);
                if (paramsArray.Length > 0)
                {
                    for (int i = 0; i < paramsArray.Length; i++)
                    {
                        string[] paramDataArr = paramsArray[i].Split(IOUtils.VALUE_SEPARATOR);
                        if (paramDataArr.Length == 2)
                        {
                            string[]          swizzleInfoArr = paramDataArr[1].Split(IOUtils.FLOAT_SEPARATOR);
                            TemplateSemantics semantic       = ShortcutToSemantic[swizzleInfoArr[0]];
                            if (interpDataDict.ContainsKey(semantic))
                            {
                                if (interpDataDict[semantic] != null)
                                {
                                    TemplateVertexData templateVertexData = new TemplateVertexData(interpDataDict[semantic]);
                                    if (swizzleInfoArr.Length > 1)
                                    {
                                        templateVertexData.DataSwizzle = "." + swizzleInfoArr[1];
                                    }
                                    templateVertexData.DataInfo  = ShortcutToInfo[paramDataArr[0]];
                                    templateVertexData.Available = true;
                                    interpDataList.Add(templateVertexData);
                                }
                            }
                        }
                    }
                }

                /*TODO:
                 * 1) Remove interpDataList.Add( templateVertexData ); from initial foreach
                 * 2) When looping though each foreach array element, create a new TemplateVertexData
                 * from the one containted on the interpDataDict and add it to interpDataList
                 */

                interpDataObj.Interpolators = interpDataList;
                interpDataDict.Clear();
                interpDataDict = null;
            }
            return(interpDataObj);
        }
        public TemplateVertexData RequestChannels(WirePortDataType type, bool isColor, string customName = null)
        {
            if (IsFull)
            {
                return(null);
            }

            int channelsRequired = TemplateHelperFunctions.DataTypeChannelUsage[type];

            if (channelsRequired == 0)
            {
                return(null);
            }

            int firstChannel = -1;

            for (int i = 0; i < AvailableChannels.Length; i++)
            {
                if (AvailableChannels[i])
                {
                    if (firstChannel < 0)
                    {
                        firstChannel = i;
                    }
                    channelsRequired -= 1;
                    if (channelsRequired == 0)
                    {
                        break;
                    }
                }
            }

            //did not found enough channels to fill request
            if (channelsRequired > 0)
            {
                return(null);
            }

            if (Usage == 0 && customName != null)
            {
                Name = customName;
            }

            Usage += 1;
            TemplateVertexData data = null;

            if (type == WirePortDataType.COLOR || type == WirePortDataType.FLOAT4)
            {
                // Automatically lock all channels
                for (int i = firstChannel; i < (firstChannel + channelsRequired); i++)
                {
                    AvailableChannels[i] = false;
                }
                IsFull = true;
                data   = new TemplateVertexData(Semantic, type, Name);
            }
            else
            {
                string[] swizzleArray = (isColor) ? TemplateHelperFunctions.ColorSwizzle : TemplateHelperFunctions.VectorSwizzle;
                string   channels     = ".";
                int      count        = firstChannel + TemplateHelperFunctions.DataTypeChannelUsage[type];
                for (int i = firstChannel; i < count; i++)
                {
                    AvailableChannels[i] = false;
                    channels            += swizzleArray[i];
                    if (i == (AvailableChannels.Length - 1))
                    {
                        IsFull = true;
                    }
                }

                data = new TemplateVertexData(Semantic, type, Name, channels);
            }
            return(data);
        }
Exemple #10
0
        public override string GenerateShaderForOutput(int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar)
        {
            if (dataCollector.IsTemplate && dataCollector.IsFragmentCategory)
            {
                dataCollector.AddToIncludes(UniqueId, Constants.UnityLightingLib);

                string texcoord1 = string.Empty;
                string texcoord2 = string.Empty;

                if (dataCollector.TemplateDataCollectorInstance.HasInfo(TemplateInfoOnSematics.TEXTURE_COORDINATES1, false, MasterNodePortCategory.Vertex))
                {
                    texcoord1 = dataCollector.TemplateDataCollectorInstance.GetInfo(TemplateInfoOnSematics.TEXTURE_COORDINATES1, false, MasterNodePortCategory.Vertex).VarName;
                }
                else
                {
                    texcoord1 = dataCollector.TemplateDataCollectorInstance.RegisterInfoOnSemantic(MasterNodePortCategory.Vertex, TemplateInfoOnSematics.TEXTURE_COORDINATES1, TemplateSemantics.TEXCOORD1, "texcoord1", WirePortDataType.FLOAT4, PrecisionType.Float, false);
                }

                if (dataCollector.TemplateDataCollectorInstance.HasInfo(TemplateInfoOnSematics.TEXTURE_COORDINATES2, false, MasterNodePortCategory.Vertex))
                {
                    texcoord2 = dataCollector.TemplateDataCollectorInstance.GetInfo(TemplateInfoOnSematics.TEXTURE_COORDINATES2, false, MasterNodePortCategory.Vertex).VarName;
                }
                else
                {
                    texcoord2 = dataCollector.TemplateDataCollectorInstance.RegisterInfoOnSemantic(MasterNodePortCategory.Vertex, TemplateInfoOnSematics.TEXTURE_COORDINATES2, TemplateSemantics.TEXCOORD2, "texcoord2", WirePortDataType.FLOAT4, PrecisionType.Float, false);
                }

                string             vOutName = dataCollector.TemplateDataCollectorInstance.CurrentTemplateData.VertexFunctionData.OutVarName;
                string             fInName  = dataCollector.TemplateDataCollectorInstance.CurrentTemplateData.FragmentFunctionData.InVarName;
                TemplateVertexData data     = dataCollector.TemplateDataCollectorInstance.RequestNewInterpolator(WirePortDataType.FLOAT4, false, "ase_lmap");

                string varName = "ase_lmap";
                if (data != null)
                {
                    varName = data.VarName;
                }

                dataCollector.AddToVertexLocalVariables(UniqueId, "#ifdef DYNAMICLIGHTMAP_ON //dynlm");
                dataCollector.AddToVertexLocalVariables(UniqueId, vOutName + "." + varName + ".zw = " + texcoord2 + ".xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw;");
                dataCollector.AddToVertexLocalVariables(UniqueId, "#endif //dynlm");
                dataCollector.AddToVertexLocalVariables(UniqueId, "#ifdef LIGHTMAP_ON //stalm");
                dataCollector.AddToVertexLocalVariables(UniqueId, vOutName + "." + varName + ".xy = " + texcoord1 + ".xy * unity_LightmapST.xy + unity_LightmapST.zw;");
                dataCollector.AddToVertexLocalVariables(UniqueId, "#endif //stalm");

                TemplateVertexData shdata      = dataCollector.TemplateDataCollectorInstance.RequestNewInterpolator(WirePortDataType.FLOAT3, false, "ase_sh");
                string             worldPos    = dataCollector.TemplateDataCollectorInstance.GetWorldPos(false, MasterNodePortCategory.Vertex);
                string             worldNormal = dataCollector.TemplateDataCollectorInstance.GetWorldNormal(PrecisionType.Float, false, MasterNodePortCategory.Vertex);
                //Debug.Log( shdata );
                string shVarName = "ase_sh";
                if (shdata != null)
                {
                    shVarName = shdata.VarName;
                }
                string outSH = vOutName + "." + shVarName + ".xyz";
                dataCollector.AddToVertexLocalVariables(UniqueId, "#ifndef LIGHTMAP_ON //nstalm");
                dataCollector.AddToVertexLocalVariables(UniqueId, "#if UNITY_SHOULD_SAMPLE_SH //sh");
                dataCollector.AddToVertexLocalVariables(UniqueId, outSH + " = 0;");
                dataCollector.AddToVertexLocalVariables(UniqueId, "#ifdef VERTEXLIGHT_ON //vl");
                dataCollector.AddToVertexLocalVariables(UniqueId, outSH + " += Shade4PointLights (");
                dataCollector.AddToVertexLocalVariables(UniqueId, "unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,");
                dataCollector.AddToVertexLocalVariables(UniqueId, "unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb,");
                dataCollector.AddToVertexLocalVariables(UniqueId, "unity_4LightAtten0, " + worldPos + ", " + worldNormal + ");");
                dataCollector.AddToVertexLocalVariables(UniqueId, "#endif //vl");
                dataCollector.AddToVertexLocalVariables(UniqueId, outSH + " = ShadeSHPerVertex (" + worldNormal + ", " + outSH + ");");
                dataCollector.AddToVertexLocalVariables(UniqueId, "#endif //sh");
                dataCollector.AddToVertexLocalVariables(UniqueId, "#endif //nstalm");

                string fragWorldNormal = string.Empty;
                if (m_inputPorts[0].IsConnected)
                {
                    if (m_normalSpace == ViewSpace.Tangent)
                    {
                        fragWorldNormal = dataCollector.TemplateDataCollectorInstance.GetWorldNormal(UniqueId, m_currentPrecisionType, m_inputPorts[0].GeneratePortInstructions(ref dataCollector), OutputId);
                    }
                    else
                    {
                        fragWorldNormal = m_inputPorts[0].GeneratePortInstructions(ref dataCollector);
                    }
                }
                else
                {
                    fragWorldNormal = dataCollector.TemplateDataCollectorInstance.GetWorldNormal(PrecisionType.Float, false, MasterNodePortCategory.Fragment);
                }

                dataCollector.AddLocalVariable(UniqueId, "UnityGIInput data" + OutputId + ";");
                dataCollector.AddLocalVariable(UniqueId, "UNITY_INITIALIZE_OUTPUT( UnityGIInput, data" + OutputId + " );");

                dataCollector.AddLocalVariable(UniqueId, "#if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON) //dylm" + OutputId);
                dataCollector.AddLocalVariable(UniqueId, "data" + OutputId + ".lightmapUV = " + fInName + "." + varName + ";");
                dataCollector.AddLocalVariable(UniqueId, "#endif //dylm" + OutputId);

                dataCollector.AddLocalVariable(UniqueId, "#if UNITY_SHOULD_SAMPLE_SH //fsh" + OutputId);
                dataCollector.AddLocalVariable(UniqueId, "data" + OutputId + ".ambient = " + fInName + "." + shVarName + ";");
                dataCollector.AddLocalVariable(UniqueId, "#endif //fsh" + OutputId);

                dataCollector.AddToLocalVariables(UniqueId, "UnityGI gi" + OutputId + " = UnityGI_Base(data" + OutputId + ", 1, " + fragWorldNormal + ");");

                return("gi" + OutputId + ".indirect.diffuse");
            }

            if (dataCollector.GenType == PortGenType.NonCustomLighting || dataCollector.CurrentCanvasMode != NodeAvailability.CustomLighting)
            {
                return("float3(0,0,0)");
            }

            string normal = string.Empty;

            if (m_inputPorts[0].IsConnected)
            {
                dataCollector.AddToInput(UniqueId, SurfaceInputs.WORLD_NORMAL, m_currentPrecisionType);
                dataCollector.AddToInput(UniqueId, SurfaceInputs.INTERNALDATA, addSemiColon: false);
                dataCollector.ForceNormal = true;

                normal = m_inputPorts[0].GeneratePortInstructions(ref dataCollector);
                if (m_normalSpace == ViewSpace.Tangent)
                {
                    normal = "WorldNormalVector( " + Constants.InputVarStr + " , " + normal + " )";
                }
            }
            else
            {
                if (dataCollector.IsFragmentCategory)
                {
                    dataCollector.AddToInput(UniqueId, SurfaceInputs.WORLD_NORMAL, m_currentPrecisionType);
                    if (dataCollector.DirtyNormal)
                    {
                        dataCollector.AddToInput(UniqueId, SurfaceInputs.INTERNALDATA, addSemiColon: false);
                        dataCollector.ForceNormal = true;
                    }
                }

                normal = GeneratorUtils.GenerateWorldNormal(ref dataCollector, UniqueId);
            }


            if (dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation)
            {
                dataCollector.AddLocalVariable(UniqueId, m_currentPrecisionType, WirePortDataType.FLOAT3, "indirectDiffuse" + OutputId, "ShadeSH9( float4( " + normal + ", 1 ) )");
            }
            else
            {
                dataCollector.AddLocalVariable(UniqueId, "UnityGI gi" + OutputId + " = gi;");
                dataCollector.AddLocalVariable(UniqueId, PrecisionType.Float, WirePortDataType.FLOAT3, "diffNorm" + OutputId, normal);
                dataCollector.AddLocalVariable(UniqueId, "gi" + OutputId + " = UnityGI_Base( data, 1, diffNorm" + OutputId + " );");
                dataCollector.AddLocalVariable(UniqueId, m_currentPrecisionType, WirePortDataType.FLOAT3, "indirectDiffuse" + OutputId, "gi" + OutputId + ".indirect.diffuse + diffNorm" + OutputId + " * 0.0001");
            }

            return("indirectDiffuse" + OutputId);
        }
        // This should only be used to semantics outside the text coord set
        public string RegisterInfoOnSemantic(MasterNodePortCategory portCategory, TemplateInfoOnSematics info, TemplateSemantics semantic, string name, WirePortDataType dataType, bool requestNewInterpolator)
        {
            if (portCategory == MasterNodePortCategory.Vertex)
            {
                if (m_vertexDataDict.ContainsKey(semantic))
                {
                    return(m_vertexDataDict[semantic].VarName);
                }

                m_availableVertData.Add(info,
                                        new InterpDataHelper(WirePortDataType.FLOAT4,
                                                             string.Format(TemplateHelperFunctions.TemplateVarFormat,
                                                                           m_currentTemplateData.VertexFunctionData.InVarName,
                                                                           name)));

                m_currentDataCollector.AddToVertexInput(
                    string.Format(TemplateHelperFunctions.TexFullSemantic,
                                  name,
                                  semantic));
                RegisterOnVertexData(semantic, dataType, name);
                return(m_availableVertData[info].VarName);
            }
            else
            {
                //search if the correct vertex data is set ...
                TemplateSemantics vertexSemantics = TemplateSemantics.NONE;
                foreach (KeyValuePair <TemplateSemantics, TemplateVertexData> kvp in m_vertexDataDict)
                {
                    if (kvp.Value.DataInfo == info)
                    {
                        vertexSemantics = kvp.Key;
                        break;
                    }
                }

                // if not, add vertex data and create interpolator
                if (vertexSemantics == TemplateSemantics.NONE)
                {
                    vertexSemantics = semantic;

                    if (!m_vertexDataDict.ContainsKey(vertexSemantics))
                    {
                        m_availableVertData.Add(info,
                                                new InterpDataHelper(WirePortDataType.FLOAT4,
                                                                     string.Format(TemplateHelperFunctions.TemplateVarFormat,
                                                                                   m_currentTemplateData.VertexFunctionData.InVarName,
                                                                                   name)));

                        m_currentDataCollector.AddToVertexInput(
                            string.Format(TemplateHelperFunctions.TexFullSemantic,
                                          name,
                                          vertexSemantics));
                        RegisterOnVertexData(vertexSemantics, dataType, name);
                    }
                }

                // either way create interpolator

                TemplateVertexData availableInterp = null;
                if (requestNewInterpolator || IsSemanticUsedOnInterpolator(semantic))
                {
                    availableInterp = RequestNewInterpolator(dataType, false);
                }
                else
                {
                    availableInterp = RegisterOnInterpolator(semantic, dataType);
                }

                if (availableInterp != null)
                {
                    string interpVarName = m_currentTemplateData.VertexFunctionData.OutVarName + "." + availableInterp.VarNameWithSwizzle;
                    string interpDecl    = string.Format(TemplateHelperFunctions.TemplateVariableDecl, interpVarName, TemplateHelperFunctions.AutoSwizzleData(m_availableVertData[info].VarName, m_availableVertData[info].VarType, dataType));
                    m_currentDataCollector.AddToVertexInterpolatorsDecl(interpDecl);
                    string finalVarName = m_currentTemplateData.FragFunctionData.InVarName + "." + availableInterp.VarNameWithSwizzle;
                    m_availableFragData.Add(info, new InterpDataHelper(dataType, finalVarName));
                    return(finalVarName);
                }
            }
            return(string.Empty);
        }
        public string RegisterUV(int UVChannel)
        {
            if (m_currentDataCollector.PortCategory == MasterNodePortCategory.Vertex)
            {
                TemplateSemantics semantic = TemplateHelperFunctions.IntToSemantic[UVChannel];

                if (m_vertexDataDict.ContainsKey(semantic))
                {
                    return(m_vertexDataDict[semantic].VarName);
                }

                string varName = TemplateHelperFunctions.BaseInterpolatorName + ((UVChannel > 0) ? UVChannel.ToString() : string.Empty);
                m_availableVertData.Add(TemplateHelperFunctions.IntToUVChannelInfo[UVChannel],
                                        new InterpDataHelper(WirePortDataType.FLOAT4,
                                                             string.Format(TemplateHelperFunctions.TemplateVarFormat,
                                                                           m_currentTemplateData.VertexFunctionData.InVarName,
                                                                           varName)));

                m_currentDataCollector.AddToVertexInput(
                    string.Format(TemplateHelperFunctions.TexFullSemantic,
                                  varName,
                                  semantic));
                RegisterOnVertexData(semantic, WirePortDataType.FLOAT2, varName);
                return(m_availableVertData[TemplateHelperFunctions.IntToUVChannelInfo[UVChannel]].VarName);
            }
            else
            {
                //search if the correct vertex data is set ...
                TemplateInfoOnSematics info            = TemplateHelperFunctions.IntToInfo[UVChannel];
                TemplateSemantics      vertexSemantics = TemplateSemantics.NONE;
                foreach (KeyValuePair <TemplateSemantics, TemplateVertexData> kvp in m_vertexDataDict)
                {
                    if (kvp.Value.DataInfo == info)
                    {
                        vertexSemantics = kvp.Key;
                        break;
                    }
                }

                // if not, add vertex data and create interpolator
                if (vertexSemantics == TemplateSemantics.NONE)
                {
                    vertexSemantics = TemplateHelperFunctions.IntToSemantic[UVChannel];

                    if (!m_vertexDataDict.ContainsKey(vertexSemantics))
                    {
                        string varName = TemplateHelperFunctions.BaseInterpolatorName + ((UVChannel > 0) ? UVChannel.ToString() : string.Empty);
                        m_availableVertData.Add(TemplateHelperFunctions.IntToUVChannelInfo[UVChannel],
                                                new InterpDataHelper(WirePortDataType.FLOAT4,
                                                                     string.Format(TemplateHelperFunctions.TemplateVarFormat,
                                                                                   m_currentTemplateData.VertexFunctionData.InVarName,
                                                                                   varName)));

                        m_currentDataCollector.AddToVertexInput(
                            string.Format(TemplateHelperFunctions.TexFullSemantic,
                                          varName,
                                          vertexSemantics));
                        RegisterOnVertexData(vertexSemantics, WirePortDataType.FLOAT2, varName);
                    }
                }

                // either way create interpolator
                TemplateVertexData availableInterp = RequestNewInterpolator(WirePortDataType.FLOAT2, false);
                if (availableInterp != null)
                {
                    string           interpVarName = m_currentTemplateData.VertexFunctionData.OutVarName + "." + availableInterp.VarNameWithSwizzle;
                    InterpDataHelper vertInfo      = m_availableVertData[TemplateHelperFunctions.IntToUVChannelInfo[UVChannel]];
                    string           interpDecl    = string.Format(TemplateHelperFunctions.TemplateVariableDecl, interpVarName, TemplateHelperFunctions.AutoSwizzleData(vertInfo.VarName, vertInfo.VarType, WirePortDataType.FLOAT2));
                    m_currentDataCollector.AddToVertexInterpolatorsDecl(interpDecl);
                    string finalVarName = m_currentTemplateData.FragFunctionData.InVarName + "." + availableInterp.VarNameWithSwizzle;
                    m_availableFragData.Add(TemplateHelperFunctions.IntToUVChannelInfo[UVChannel], new InterpDataHelper(WirePortDataType.FLOAT2, finalVarName));
                    return(finalVarName);
                }
            }
            return(string.Empty);
        }
        public override string GenerateShaderForOutput(int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar)
        {
            if (m_outputPorts[0].IsLocalValue(dataCollector.PortCategory))
            {
                return(m_outputPorts[0].LocalValue(dataCollector.PortCategory));
            }
            string finalValue = string.Empty;

            if (dataCollector.IsTemplate && dataCollector.IsFragmentCategory)
            {
                if (!dataCollector.IsSRP)
                {
                    dataCollector.AddToIncludes(UniqueId, Constants.UnityLightingLib);

                    string texcoord1 = string.Empty;
                    string texcoord2 = string.Empty;

                    if (dataCollector.TemplateDataCollectorInstance.HasInfo(TemplateInfoOnSematics.TEXTURE_COORDINATES1, false, MasterNodePortCategory.Vertex))
                    {
                        texcoord1 = dataCollector.TemplateDataCollectorInstance.GetInfo(TemplateInfoOnSematics.TEXTURE_COORDINATES1, false, MasterNodePortCategory.Vertex).VarName;
                    }
                    else
                    {
                        texcoord1 = dataCollector.TemplateDataCollectorInstance.RegisterInfoOnSemantic(MasterNodePortCategory.Vertex, TemplateInfoOnSematics.TEXTURE_COORDINATES1, TemplateSemantics.TEXCOORD1, "texcoord1", WirePortDataType.FLOAT4, PrecisionType.Float, false);
                    }

                    if (dataCollector.TemplateDataCollectorInstance.HasInfo(TemplateInfoOnSematics.TEXTURE_COORDINATES2, false, MasterNodePortCategory.Vertex))
                    {
                        texcoord2 = dataCollector.TemplateDataCollectorInstance.GetInfo(TemplateInfoOnSematics.TEXTURE_COORDINATES2, false, MasterNodePortCategory.Vertex).VarName;
                    }
                    else
                    {
                        texcoord2 = dataCollector.TemplateDataCollectorInstance.RegisterInfoOnSemantic(MasterNodePortCategory.Vertex, TemplateInfoOnSematics.TEXTURE_COORDINATES2, TemplateSemantics.TEXCOORD2, "texcoord2", WirePortDataType.FLOAT4, PrecisionType.Float, false);
                    }

                    string             vOutName = dataCollector.TemplateDataCollectorInstance.CurrentTemplateData.VertexFunctionData.OutVarName;
                    string             fInName  = dataCollector.TemplateDataCollectorInstance.CurrentTemplateData.FragmentFunctionData.InVarName;
                    TemplateVertexData data     = dataCollector.TemplateDataCollectorInstance.RequestNewInterpolator(WirePortDataType.FLOAT4, false, "ase_lmap");

                    string varName = "ase_lmap";
                    if (data != null)
                    {
                        varName = data.VarName;
                    }

                    dataCollector.AddToVertexLocalVariables(UniqueId, "#ifdef DYNAMICLIGHTMAP_ON //dynlm");
                    dataCollector.AddToVertexLocalVariables(UniqueId, vOutName + "." + varName + ".zw = " + texcoord2 + ".xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw;");
                    dataCollector.AddToVertexLocalVariables(UniqueId, "#endif //dynlm");
                    dataCollector.AddToVertexLocalVariables(UniqueId, "#ifdef LIGHTMAP_ON //stalm");
                    dataCollector.AddToVertexLocalVariables(UniqueId, vOutName + "." + varName + ".xy = " + texcoord1 + ".xy * unity_LightmapST.xy + unity_LightmapST.zw;");
                    dataCollector.AddToVertexLocalVariables(UniqueId, "#endif //stalm");

                    TemplateVertexData shdata      = dataCollector.TemplateDataCollectorInstance.RequestNewInterpolator(WirePortDataType.FLOAT3, false, "ase_sh");
                    string             worldPos    = dataCollector.TemplateDataCollectorInstance.GetWorldPos(false, MasterNodePortCategory.Vertex);
                    string             worldNormal = dataCollector.TemplateDataCollectorInstance.GetWorldNormal(PrecisionType.Float, false, MasterNodePortCategory.Vertex);
                    //Debug.Log( shdata );
                    string shVarName = "ase_sh";
                    if (shdata != null)
                    {
                        shVarName = shdata.VarName;
                    }
                    string outSH = vOutName + "." + shVarName + ".xyz";
                    dataCollector.AddToVertexLocalVariables(UniqueId, "#ifndef LIGHTMAP_ON //nstalm");
                    dataCollector.AddToVertexLocalVariables(UniqueId, "#if UNITY_SHOULD_SAMPLE_SH //sh");
                    dataCollector.AddToVertexLocalVariables(UniqueId, outSH + " = 0;");
                    dataCollector.AddToVertexLocalVariables(UniqueId, "#ifdef VERTEXLIGHT_ON //vl");
                    dataCollector.AddToVertexLocalVariables(UniqueId, outSH + " += Shade4PointLights (");
                    dataCollector.AddToVertexLocalVariables(UniqueId, "unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,");
                    dataCollector.AddToVertexLocalVariables(UniqueId, "unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb,");
                    dataCollector.AddToVertexLocalVariables(UniqueId, "unity_4LightAtten0, " + worldPos + ", " + worldNormal + ");");
                    dataCollector.AddToVertexLocalVariables(UniqueId, "#endif //vl");
                    dataCollector.AddToVertexLocalVariables(UniqueId, outSH + " = ShadeSHPerVertex (" + worldNormal + ", " + outSH + ");");
                    dataCollector.AddToVertexLocalVariables(UniqueId, "#endif //sh");
                    dataCollector.AddToVertexLocalVariables(UniqueId, "#endif //nstalm");

                    //dataCollector.AddToPragmas( UniqueId, "multi_compile_fwdbase" );

                    string fragWorldNormal = string.Empty;
                    if (m_inputPorts[0].IsConnected)
                    {
                        if (m_normalSpace == ViewSpace.Tangent)
                        {
                            fragWorldNormal = dataCollector.TemplateDataCollectorInstance.GetWorldNormal(UniqueId, CurrentPrecisionType, m_inputPorts[0].GeneratePortInstructions(ref dataCollector), OutputId);
                        }
                        else
                        {
                            fragWorldNormal = m_inputPorts[0].GeneratePortInstructions(ref dataCollector);
                        }
                    }
                    else
                    {
                        fragWorldNormal = dataCollector.TemplateDataCollectorInstance.GetWorldNormal(PrecisionType.Float, false, MasterNodePortCategory.Fragment);
                    }

                    dataCollector.AddLocalVariable(UniqueId, "UnityGIInput data" + OutputId + ";");
                    dataCollector.AddLocalVariable(UniqueId, "UNITY_INITIALIZE_OUTPUT( UnityGIInput, data" + OutputId + " );");

                    dataCollector.AddLocalVariable(UniqueId, "#if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON) //dylm" + OutputId);
                    dataCollector.AddLocalVariable(UniqueId, "data" + OutputId + ".lightmapUV = " + fInName + "." + varName + ";");
                    dataCollector.AddLocalVariable(UniqueId, "#endif //dylm" + OutputId);

                    dataCollector.AddLocalVariable(UniqueId, "#if UNITY_SHOULD_SAMPLE_SH //fsh" + OutputId);
                    dataCollector.AddLocalVariable(UniqueId, "data" + OutputId + ".ambient = " + fInName + "." + shVarName + ";");
                    dataCollector.AddLocalVariable(UniqueId, "#endif //fsh" + OutputId);

                    dataCollector.AddToLocalVariables(UniqueId, "UnityGI gi" + OutputId + " = UnityGI_Base(data" + OutputId + ", 1, " + fragWorldNormal + ");");

                    finalValue = "gi" + OutputId + ".indirect.diffuse";
                    m_outputPorts[0].SetLocalValue(finalValue, dataCollector.PortCategory);
                    return(finalValue);
                }
                else
                {
                    if (dataCollector.CurrentSRPType == TemplateSRPType.Lightweight)
                    {
                        string texcoord1 = string.Empty;

                        if (dataCollector.TemplateDataCollectorInstance.HasInfo(TemplateInfoOnSematics.TEXTURE_COORDINATES1, false, MasterNodePortCategory.Vertex))
                        {
                            texcoord1 = dataCollector.TemplateDataCollectorInstance.GetInfo(TemplateInfoOnSematics.TEXTURE_COORDINATES1, false, MasterNodePortCategory.Vertex).VarName;
                        }
                        else
                        {
                            texcoord1 = dataCollector.TemplateDataCollectorInstance.RegisterInfoOnSemantic(MasterNodePortCategory.Vertex, TemplateInfoOnSematics.TEXTURE_COORDINATES1, TemplateSemantics.TEXCOORD1, "texcoord1", WirePortDataType.FLOAT4, PrecisionType.Float, false);
                        }

                        string vOutName = dataCollector.TemplateDataCollectorInstance.CurrentTemplateData.VertexFunctionData.OutVarName;
                        string fInName  = dataCollector.TemplateDataCollectorInstance.CurrentTemplateData.FragmentFunctionData.InVarName;


                        if (!dataCollector.TemplateDataCollectorInstance.HasRawInterpolatorOfName("lightmapUVOrVertexSH"))
                        {
                            string worldNormal = dataCollector.TemplateDataCollectorInstance.GetWorldNormal(PrecisionType.Float, false, MasterNodePortCategory.Vertex);
                            dataCollector.TemplateDataCollectorInstance.RequestNewInterpolator(WirePortDataType.FLOAT4, false, "lightmapUVOrVertexSH");

                            dataCollector.AddToVertexLocalVariables(UniqueId, "OUTPUT_LIGHTMAP_UV( " + texcoord1 + ", unity_LightmapST, " + vOutName + ".lightmapUVOrVertexSH.xy );");
                            dataCollector.AddToVertexLocalVariables(UniqueId, "OUTPUT_SH( " + worldNormal + ", " + vOutName + ".lightmapUVOrVertexSH.xyz );");

                            dataCollector.AddToPragmas(UniqueId, "multi_compile _ DIRLIGHTMAP_COMBINED");
                            dataCollector.AddToPragmas(UniqueId, "multi_compile _ LIGHTMAP_ON");
                        }

                        string fragWorldNormal = string.Empty;
                        if (m_inputPorts[0].IsConnected)
                        {
                            if (m_normalSpace == ViewSpace.Tangent)
                            {
                                fragWorldNormal = dataCollector.TemplateDataCollectorInstance.GetWorldNormal(UniqueId, CurrentPrecisionType, m_inputPorts[0].GeneratePortInstructions(ref dataCollector), OutputId);
                            }
                            else
                            {
                                fragWorldNormal = m_inputPorts[0].GeneratePortInstructions(ref dataCollector);
                            }
                        }
                        else
                        {
                            fragWorldNormal = dataCollector.TemplateDataCollectorInstance.GetWorldNormal(PrecisionType.Float, false, MasterNodePortCategory.Fragment);
                        }

                        //SAMPLE_GI

                        //This function may not do full pixel and does not behave correctly with given normal thus is commented out
                        //dataCollector.AddLocalVariable( UniqueId, "float3 bakedGI" + OutputId + " = SAMPLE_GI( " + fInName + ".lightmapUVOrVertexSH.xy, " + fInName + ".lightmapUVOrVertexSH.xyz, " + fragWorldNormal + " );" );
                        dataCollector.AddFunction(LWIndirectDiffuseBody[0], LWIndirectDiffuseBody, false);
                        finalValue = "bakedGI" + OutputId;
                        string result = string.Format(LWIndirectDiffuseHeader, fInName + ".lightmapUVOrVertexSH.xy", fragWorldNormal);
                        dataCollector.AddLocalVariable(UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT3, finalValue, result);

                        m_outputPorts[0].SetLocalValue(finalValue, dataCollector.PortCategory);
                        return(finalValue);
                    }
                    else if (dataCollector.CurrentSRPType == TemplateSRPType.HD)
                    {
                        string texcoord1 = string.Empty;
                        string texcoord2 = string.Empty;

                        if (dataCollector.TemplateDataCollectorInstance.HasInfo(TemplateInfoOnSematics.TEXTURE_COORDINATES1, false, MasterNodePortCategory.Vertex))
                        {
                            texcoord1 = dataCollector.TemplateDataCollectorInstance.GetInfo(TemplateInfoOnSematics.TEXTURE_COORDINATES1, false, MasterNodePortCategory.Vertex).VarName;
                        }
                        else
                        {
                            texcoord1 = dataCollector.TemplateDataCollectorInstance.RegisterInfoOnSemantic(MasterNodePortCategory.Vertex, TemplateInfoOnSematics.TEXTURE_COORDINATES1, TemplateSemantics.TEXCOORD1, "texcoord1", WirePortDataType.FLOAT4, PrecisionType.Float, false);
                        }

                        if (dataCollector.TemplateDataCollectorInstance.HasInfo(TemplateInfoOnSematics.TEXTURE_COORDINATES2, false, MasterNodePortCategory.Vertex))
                        {
                            texcoord2 = dataCollector.TemplateDataCollectorInstance.GetInfo(TemplateInfoOnSematics.TEXTURE_COORDINATES2, false, MasterNodePortCategory.Vertex).VarName;
                        }
                        else
                        {
                            texcoord2 = dataCollector.TemplateDataCollectorInstance.RegisterInfoOnSemantic(MasterNodePortCategory.Vertex, TemplateInfoOnSematics.TEXTURE_COORDINATES2, TemplateSemantics.TEXCOORD2, "texcoord2", WirePortDataType.FLOAT4, PrecisionType.Float, false);
                        }

                        dataCollector.TemplateDataCollectorInstance.RequestNewInterpolator(WirePortDataType.FLOAT4, false, "ase_lightmapUVs");

                        string vOutName = dataCollector.TemplateDataCollectorInstance.CurrentTemplateData.VertexFunctionData.OutVarName;
                        string fInName  = dataCollector.TemplateDataCollectorInstance.CurrentTemplateData.FragmentFunctionData.InVarName;

                        dataCollector.AddToVertexLocalVariables(UniqueId, vOutName + ".ase_lightmapUVs.xy = " + texcoord1 + ".xy * unity_LightmapST.xy + unity_LightmapST.zw;");
                        dataCollector.AddToVertexLocalVariables(UniqueId, vOutName + ".ase_lightmapUVs.zw = " + texcoord2 + ".xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw;");

                        string worldPos = dataCollector.TemplateDataCollectorInstance.GetWorldPos(false, MasterNodePortCategory.Fragment);

                        dataCollector.AddToPragmas(UniqueId, "multi_compile _ LIGHTMAP_ON");
                        dataCollector.AddToPragmas(UniqueId, "multi_compile _ DIRLIGHTMAP_COMBINED");
                        dataCollector.AddToPragmas(UniqueId, "multi_compile _ DYNAMICLIGHTMAP_ON");

                        string fragWorldNormal = string.Empty;
                        if (m_inputPorts[0].IsConnected)
                        {
                            if (m_normalSpace == ViewSpace.Tangent)
                            {
                                fragWorldNormal = dataCollector.TemplateDataCollectorInstance.GetWorldNormal(UniqueId, CurrentPrecisionType, m_inputPorts[0].GeneratePortInstructions(ref dataCollector), OutputId);
                            }
                            else
                            {
                                fragWorldNormal = m_inputPorts[0].GeneratePortInstructions(ref dataCollector);
                            }
                        }
                        else
                        {
                            fragWorldNormal = dataCollector.TemplateDataCollectorInstance.GetWorldNormal(PrecisionType.Float, false, MasterNodePortCategory.Fragment);
                        }

                        //SAMPLE_GI
                        dataCollector.AddLocalVariable(UniqueId, "float3 bakedGI" + OutputId + " = SampleBakedGI( " + worldPos + ", " + fragWorldNormal + ", " + fInName + ".ase_lightmapUVs.xy, " + fInName + ".ase_lightmapUVs.zw );");
                        finalValue = "bakedGI" + OutputId;
                        m_outputPorts[0].SetLocalValue(finalValue, dataCollector.PortCategory);
                        return(finalValue);
                    }
                }
            }
            if (dataCollector.GenType == PortGenType.NonCustomLighting || dataCollector.CurrentCanvasMode != NodeAvailability.CustomLighting)
            {
                return("float3(0,0,0)");
            }

            string normal = string.Empty;

            if (m_inputPorts[0].IsConnected)
            {
                dataCollector.AddToInput(UniqueId, SurfaceInputs.WORLD_NORMAL, CurrentPrecisionType);
                dataCollector.AddToInput(UniqueId, SurfaceInputs.INTERNALDATA, addSemiColon: false);
                dataCollector.ForceNormal = true;

                normal = m_inputPorts[0].GeneratePortInstructions(ref dataCollector);
                if (m_normalSpace == ViewSpace.Tangent)
                {
                    normal = "WorldNormalVector( " + Constants.InputVarStr + " , " + normal + " )";
                }
            }
            else
            {
                if (dataCollector.IsFragmentCategory)
                {
                    dataCollector.AddToInput(UniqueId, SurfaceInputs.WORLD_NORMAL, CurrentPrecisionType);
                    if (dataCollector.DirtyNormal)
                    {
                        dataCollector.AddToInput(UniqueId, SurfaceInputs.INTERNALDATA, addSemiColon: false);
                        dataCollector.ForceNormal = true;
                    }
                }

                normal = GeneratorUtils.GenerateWorldNormal(ref dataCollector, UniqueId);
            }


            if (dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation)
            {
                dataCollector.AddLocalVariable(UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT3, "indirectDiffuse" + OutputId, "ShadeSH9( float4( " + normal + ", 1 ) )");
            }
            else
            {
                dataCollector.AddLocalVariable(UniqueId, "UnityGI gi" + OutputId + " = gi;");
                dataCollector.AddLocalVariable(UniqueId, PrecisionType.Float, WirePortDataType.FLOAT3, "diffNorm" + OutputId, normal);
                dataCollector.AddLocalVariable(UniqueId, "gi" + OutputId + " = UnityGI_Base( data, 1, diffNorm" + OutputId + " );");
                dataCollector.AddLocalVariable(UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT3, "indirectDiffuse" + OutputId, "gi" + OutputId + ".indirect.diffuse + diffNorm" + OutputId + " * 0.0001");
            }

            finalValue = "indirectDiffuse" + OutputId;
            m_outputPorts[0].SetLocalValue(finalValue, dataCollector.PortCategory);
            return(finalValue);
        }
		public TemplateVertexData RequestChannels( WirePortDataType type, bool isColor, string customName = null )
		{
			if ( IsFull )
				return null:

			int channelsRequired = TemplateHelperFunctions.DataTypeChannelUsage[ type ]:
			if ( channelsRequired == 0 )
				return null:

			int firstChannel = -1:
			for ( int i = 0: i < AvailableChannels.Length: i++ )
			{
				if ( AvailableChannels[ i ] )
				{
					if ( firstChannel < 0 )
					{
						firstChannel = i:
					}
					channelsRequired -= 1:
					if ( channelsRequired == 0 )
						break:
				}
			}

			//did not found enough channels to fill request
			if ( channelsRequired > 0 )
				return null:

			if( Usage == 0 && customName != null )
			{
				Name = customName:
			}

			Usage += 1:
			TemplateVertexData data = null:

			if ( type == WirePortDataType.COLOR || type == WirePortDataType.FLOAT4 )
			{
				// Automatically lock all channels
				for ( int i = firstChannel: i < ( firstChannel + channelsRequired ): i++ )
				{
					AvailableChannels[ i ] = false:
				}
				IsFull = true:
				data = new TemplateVertexData( Semantic, type, Name ):
			}
			else
			{
				string[] swizzleArray = ( isColor ) ? TemplateHelperFunctions.ColorSwizzle : TemplateHelperFunctions.VectorSwizzle:
				string channels = ".":
				int count = firstChannel + TemplateHelperFunctions.DataTypeChannelUsage[ type ]:
				for ( int i = firstChannel: i < count: i++ )
				{
					AvailableChannels[ i ] = false:
					channels += swizzleArray[ i ]:
					if ( i == ( AvailableChannels.Length - 1 ) )
					{
						IsFull = true:
					}
				}

				data = new TemplateVertexData( Semantic, type, Name, channels ):
			}
			return data:
		}