Example #1
0
        public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
        {
            NodeUtils.SlotConfigurationExceptionIfBadConfiguration(this, new[] { InputSlot1Id, InputSlot2Id }, new[] { OutputSlotId });
            string input1Value = GetSlotValue(InputSlot1Id, generationMode);
            string input2Value = GetSlotValue(InputSlot2Id, generationMode);

            visitor.AddShaderChunk(string.Format("{0} {1} = {2};", NodeUtils.ConvertConcreteSlotValueTypeToString(precision, FindInputSlot <MaterialSlot>(InputSlot2Id).concreteValueType), GetVariableNameForSlot(OutputSlotId), GetFunctionCallBody(input1Value, input2Value)), true);
        }
Example #2
0
        public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
        {
            ValidateChannelCount();
            string inputValue  = GetSlotValue(InputSlotId, generationMode);
            string outputValue = GetSlotValue(OutputSlotId, generationMode);

            visitor.AddShaderChunk(string.Format("{0} {1};", NodeUtils.ConvertConcreteSlotValueTypeToString(precision, FindInputSlot <MaterialSlot>(InputSlotId).concreteValueType), GetVariableNameForSlot(OutputSlotId)), true);
            visitor.AddShaderChunk(GetFunctionCallBody(inputValue, outputValue), true);
        }
        public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
        {
            if (referencedGraph == null)
            {
                return;
            }

            foreach (var outSlot in referencedGraph.graphOutputs)
            {
                visitor.AddShaderChunk(string.Format("{0} {1};", NodeUtils.ConvertConcreteSlotValueTypeToString(precision, outSlot.concreteValueType), GetVariableNameForSlot(outSlot.id)), true);
            }

            var arguments = new List <string>();

            foreach (var prop in referencedGraph.graphInputs)
            {
                var inSlotId = prop.guid.GetHashCode();

                if (prop is TextureShaderProperty)
                {
                    arguments.Add(string.Format("TEXTURE2D_PARAM({0}, sampler{0})", GetSlotValue(inSlotId, generationMode)));
                }
                if (prop is Texture2DArrayShaderProperty)
                {
                    arguments.Add(string.Format("TEXTURE2D_PARAM({0}, sampler{0})", GetSlotValue(inSlotId, generationMode)));
                }
                if (prop is Texture3DShaderProperty)
                {
                    arguments.Add(string.Format("TEXTURE3D_PARAM({0}, sampler{0})", GetSlotValue(inSlotId, generationMode)));
                }
                else if (prop is CubemapShaderProperty)
                {
                    arguments.Add(string.Format("TEXTURECUBE_PARAM({0}, sampler{0})", GetSlotValue(inSlotId, generationMode)));
                }
                else
                {
                    arguments.Add(GetSlotValue(inSlotId, generationMode));
                }
            }

            // pass surface inputs through
            arguments.Add("IN");

            foreach (var outSlot in referencedGraph.graphOutputs)
            {
                arguments.Add(GetVariableNameForSlot(outSlot.id));
            }

            visitor.AddShaderChunk(
                string.Format("{0}({1});"
                              , SubGraphFunctionName()
                              , arguments.Aggregate((current, next) => string.Format("{0}, {1}", current, next)))
                , false);
        }
 public static void GenerateVertexDescriptionStruct(ShaderStringBuilder builder, List <MaterialSlot> slots)
 {
     builder.AppendLine("struct {0}", k_VertexDescriptionStructName);
     using (builder.BlockSemicolonScope())
     {
         foreach (var slot in slots)
         {
             builder.AppendLine("{0} {1};", NodeUtils.ConvertConcreteSlotValueTypeToString(AbstractMaterialNode.OutputPrecision.@float, slot.concreteValueType), NodeUtils.GetHLSLSafeName(slot.shaderOutputName));
         }
     }
 }
Example #5
0
        public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
        {
            var sb          = new ShaderStringBuilder();
            var input1Value = GetSlotValue(Input1SlotId, generationMode);
            var input2Value = GetSlotValue(Input2SlotId, generationMode);
            var outputValue = GetSlotValue(OutputSlotId, generationMode);

            sb.AppendLine("{0} {1};", NodeUtils.ConvertConcreteSlotValueTypeToString(precision, FindOutputSlot <MaterialSlot>(OutputSlotId).concreteValueType), GetVariableNameForSlot(OutputSlotId));
            sb.AppendLine("{0}({1}, {2}, {3});", GetFunctionHeader(), input1Value, input2Value, outputValue);

            visitor.AddShaderChunk(sb.ToString(), false);
        }
Example #6
0
 public void CanConvertConcreteSlotValueTypeToOutputChunkProperly()
 {
     Assert.AreEqual("float", NodeUtils.ConvertConcreteSlotValueTypeToString(AbstractMaterialNode.OutputPrecision.@float, ConcreteSlotValueType.Vector1));
     Assert.AreEqual("float", NodeUtils.ConvertConcreteSlotValueTypeToString(AbstractMaterialNode.OutputPrecision.@float, ConcreteSlotValueType.Boolean));
     Assert.AreEqual("float2", NodeUtils.ConvertConcreteSlotValueTypeToString(AbstractMaterialNode.OutputPrecision.@float, ConcreteSlotValueType.Vector2));
     Assert.AreEqual("float3", NodeUtils.ConvertConcreteSlotValueTypeToString(AbstractMaterialNode.OutputPrecision.@float, ConcreteSlotValueType.Vector3));
     Assert.AreEqual("float4", NodeUtils.ConvertConcreteSlotValueTypeToString(AbstractMaterialNode.OutputPrecision.@float, ConcreteSlotValueType.Vector4));
     Assert.AreEqual("Texture2D", NodeUtils.ConvertConcreteSlotValueTypeToString(AbstractMaterialNode.OutputPrecision.@float, ConcreteSlotValueType.Texture2D));
     Assert.AreEqual("float2x2", NodeUtils.ConvertConcreteSlotValueTypeToString(AbstractMaterialNode.OutputPrecision.@float, ConcreteSlotValueType.Matrix2));
     Assert.AreEqual("float3x3", NodeUtils.ConvertConcreteSlotValueTypeToString(AbstractMaterialNode.OutputPrecision.@float, ConcreteSlotValueType.Matrix3));
     Assert.AreEqual("float4x4", NodeUtils.ConvertConcreteSlotValueTypeToString(AbstractMaterialNode.OutputPrecision.@float, ConcreteSlotValueType.Matrix4));
     Assert.AreEqual("SamplerState", NodeUtils.ConvertConcreteSlotValueTypeToString(AbstractMaterialNode.OutputPrecision.@float, ConcreteSlotValueType.SamplerState));
     Assert.AreEqual("Cubemap", NodeUtils.ConvertConcreteSlotValueTypeToString(AbstractMaterialNode.OutputPrecision.@float, ConcreteSlotValueType.Cubemap));
 }
Example #7
0
        string GetFunctionName()
        {
            string channelSum = "None";

            if (channelMask != 0)
            {
                bool red   = (channelMask & 1) != 0;
                bool green = (channelMask & 2) != 0;
                bool blue  = (channelMask & 4) != 0;
                bool alpha = (channelMask & 8) != 0;
                channelSum = string.Format("{0}{1}{2}{3}", red ? "Red" : "", green ? "Green" : "", blue ? "Blue" : "", alpha ? "Alpha" : "");
            }
            return(string.Format("Unity_ChannelMask_{0}_{1}", channelSum, NodeUtils.ConvertConcreteSlotValueTypeToString(precision, FindOutputSlot <MaterialSlot>(OutputSlotId).concreteValueType)));
        }
Example #8
0
        public void GenerateNodeCode(ShaderGenerator visitor, GraphContext graphContext, GenerationMode generationMode)
        {
            var sb          = new ShaderStringBuilder();
            var inputValue  = GetSlotValue(InputSlotId, generationMode);
            var outputValue = GetSlotValue(OutputSlotId, generationMode);

            sb.AppendLine("{0} {1};", NodeUtils.ConvertConcreteSlotValueTypeToString(precision, FindInputSlot <MaterialSlot>(InputSlotId).concreteValueType), GetVariableNameForSlot(OutputSlotId));
            if (!generationMode.IsPreview())
            {
                sb.AppendLine("{0}3 _{1}_Red = {0}3 ({2}, {3}, {4});", precision, GetVariableNameForNode(), channelMixer.outRed[0], channelMixer.outRed[1], channelMixer.outRed[2]);
                sb.AppendLine("{0}3 _{1}_Green = {0}3 ({2}, {3}, {4});", precision, GetVariableNameForNode(), channelMixer.outGreen[0], channelMixer.outGreen[1], channelMixer.outGreen[2]);
                sb.AppendLine("{0}3 _{1}_Blue = {0}3 ({2}, {3}, {4});", precision, GetVariableNameForNode(), channelMixer.outBlue[0], channelMixer.outBlue[1], channelMixer.outBlue[2]);
            }
            sb.AppendLine("{0}({1}, _{2}_Red, _{2}_Green, _{2}_Blue, {3});", GetFunctionName(), inputValue, GetVariableNameForNode(), outputValue);

            visitor.AddShaderChunk(sb.ToString(), false);
        }
Example #9
0
        public void GenerateNodeCode(ShaderGenerator visitor, GraphContext graphContext, GenerationMode generationMode)
        {
            var sb          = new ShaderStringBuilder();
            var uvValue     = GetSlotValue(UVSlotId, generationMode);
            var widthValue  = GetSlotValue(WidthSlotId, generationMode);
            var heightValue = GetSlotValue(HeightSlotId, generationMode);
            var tileValue   = GetSlotValue(TileSlotId, generationMode);
            var outputValue = GetSlotValue(OutputSlotId, generationMode);

            sb.AppendLine("{0} {1};", NodeUtils.ConvertConcreteSlotValueTypeToString(precision, FindOutputSlot <MaterialSlot>(OutputSlotId).concreteValueType), GetVariableNameForSlot(OutputSlotId));
            if (!generationMode.IsPreview())
            {
                sb.AppendLine("{0}2 _{1}_Invert = {0}2 ({2}, {3});", precision, GetVariableNameForNode(), invertX.isOn ? 1 : 0, invertY.isOn ? 1 : 0);
            }
            sb.AppendLine("{0}({1}, {2}, {3}, {4}, _{5}_Invert, {6});", GetFunctionName(), uvValue, widthValue, heightValue, tileValue, GetVariableNameForNode(), outputValue);

            visitor.AddShaderChunk(sb.ToString(), false);
        }
 public static void GenerateSurfaceDescriptionStruct(ShaderStringBuilder surfaceDescriptionStruct, List <MaterialSlot> slots, bool isMaster)
 {
     surfaceDescriptionStruct.AppendLine("struct SurfaceDescription");
     using (surfaceDescriptionStruct.BlockSemicolonScope())
     {
         if (isMaster)
         {
             foreach (var slot in slots)
             {
                 surfaceDescriptionStruct.AppendLine("{0} {1};",
                                                     NodeUtils.ConvertConcreteSlotValueTypeToString(AbstractMaterialNode.OutputPrecision.@float, slot.concreteValueType),
                                                     NodeUtils.GetHLSLSafeName(slot.shaderOutputName));
             }
             //surfaceDescriptionStruct.Deindent();
         }
         else
         {
             surfaceDescriptionStruct.AppendLine("float4 PreviewOutput;");
         }
     }
 }
Example #11
0
        public void GenerateNodeCode(ShaderGenerator visitor, GraphContext graphContext, GenerationMode generationMode)
        {
            var sb           = new ShaderStringBuilder();
            var inputM0Value = GetSlotValue(InputSlotM0Id, generationMode);
            var inputM1Value = GetSlotValue(InputSlotM1Id, generationMode);
            var inputM2Value = GetSlotValue(InputSlotM2Id, generationMode);
            var inputM3Value = GetSlotValue(InputSlotM3Id, generationMode);

            sb.AppendLine("{0} {1};", NodeUtils.ConvertConcreteSlotValueTypeToString(precision, FindOutputSlot <MaterialSlot>(Output4x4SlotId).concreteValueType), GetVariableNameForSlot(Output4x4SlotId));
            sb.AppendLine("{0} {1};", NodeUtils.ConvertConcreteSlotValueTypeToString(precision, FindOutputSlot <MaterialSlot>(Output3x3SlotId).concreteValueType), GetVariableNameForSlot(Output3x3SlotId));
            sb.AppendLine("{0} {1};", NodeUtils.ConvertConcreteSlotValueTypeToString(precision, FindOutputSlot <MaterialSlot>(Output2x2SlotId).concreteValueType), GetVariableNameForSlot(Output2x2SlotId));
            sb.AppendLine("{0}({1}, {2}, {3}, {4}, {5}, {6}, {7});",
                          GetFunctionName(),
                          inputM0Value,
                          inputM1Value,
                          inputM2Value,
                          inputM3Value,
                          GetVariableNameForSlot(Output4x4SlotId),
                          GetVariableNameForSlot(Output3x3SlotId),
                          GetVariableNameForSlot(Output2x2SlotId));

            visitor.AddShaderChunk(sb.ToString(), false);
        }
Example #12
0
 public static string ToString(this ConcreteSlotValueType type, AbstractMaterialNode.OutputPrecision precision)
 {
     return(NodeUtils.ConvertConcreteSlotValueTypeToString(precision, type));
 }
Example #13
0
        public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
        {
            NodeUtils.SlotConfigurationExceptionIfBadConfiguration(this, new[] { InputSlotId }, new[] { OutputSlotId });
            string inputValue                        = string.Format("{0}.xyz", GetSlotValue(InputSlotId, generationMode));
            string targetTransformString             = "tangentTransform_" + conversion.from.ToString();
            string transposeTargetTransformString    = "transposeTangent";
            string transformString                   = "";
            string tangentTransformSpace             = conversion.from.ToString();
            bool   requiresTangentTransform          = false;
            bool   requiresTransposeTangentTransform = false;

            if (conversion.from == CoordinateSpace.World)
            {
                if (conversion.to == CoordinateSpace.World)
                {
                    transformString = inputValue;
                }
                else if (conversion.to == CoordinateSpace.Object)
                {
                    transformString = string.Format("TransformWorldToObject({0})", inputValue);
                }
                else if (conversion.to == CoordinateSpace.Tangent)
                {
                    requiresTangentTransform = true;
                    transformString          = string.Format("TransformWorldToTangent({0}, {1})", inputValue, targetTransformString);
                }
                else if (conversion.to == CoordinateSpace.View)
                {
                    transformString = string.Format("TransformWorldToView({0})", inputValue);
                }
            }
            else if (conversion.from == CoordinateSpace.Object)
            {
                if (conversion.to == CoordinateSpace.World)
                {
                    transformString = string.Format("TransformObjectToWorld({0})", inputValue);
                }
                else if (conversion.to == CoordinateSpace.Object)
                {
                    transformString = inputValue;
                }
                else if (conversion.to == CoordinateSpace.Tangent)
                {
                    requiresTangentTransform = true;
                    transformString          = string.Format("TransformWorldToTangent(TransformObjectToWorld({0}), {1})", inputValue, targetTransformString);
                }
                else if (conversion.to == CoordinateSpace.View)
                {
                    transformString = string.Format("TransformWorldToView(TransformObjectToWorld({0}))", inputValue);
                }
            }
            else if (conversion.from == CoordinateSpace.Tangent)
            {
                if (conversion.to == CoordinateSpace.World)
                {
                    requiresTransposeTangentTransform = true;
                    transformString = string.Format("mul({0}, {1}).xyz", inputValue, transposeTargetTransformString);
                }
                else if (conversion.to == CoordinateSpace.Object)
                {
                    requiresTransposeTangentTransform = true;
                    transformString = string.Format("TransformWorldToObject(mul({0}, {1}).xyz)", inputValue, transposeTargetTransformString);
                }
                else if (conversion.to == CoordinateSpace.Tangent)
                {
                    transformString = inputValue;
                }
                else if (conversion.to == CoordinateSpace.View)
                {
                    requiresTransposeTangentTransform = true;
                    transformString = string.Format("TransformWorldToView(mul({0}, {1}).xyz)", inputValue, transposeTargetTransformString);
                }
            }
            else if (conversion.from == CoordinateSpace.View)
            {
                if (conversion.to == CoordinateSpace.World)
                {
                    transformString = string.Format("mul(UNITY_MATRIX_I_V, float4({0}, 1)).xyz", inputValue);
                }
                else if (conversion.to == CoordinateSpace.Object)
                {
                    transformString = string.Format("TransformWorldToObject(mul(UNITY_MATRIX_I_V, float4({0}, 1) ).xyz)", inputValue);
                }
                else if (conversion.to == CoordinateSpace.Tangent)
                {
                    requiresTangentTransform = true;
                    tangentTransformSpace    = CoordinateSpace.World.ToString();
                    transformString          = string.Format("TransformWorldToTangent(mul(UNITY_MATRIX_I_V, float4({0}, 1) ).xyz, {1})", inputValue, targetTransformString);
                }
                else if (conversion.to == CoordinateSpace.View)
                {
                    transformString = inputValue;
                }
            }
            if (requiresTransposeTangentTransform)
            {
                visitor.AddShaderChunk(string.Format("float3x3 {0} = transpose(float3x3(IN.{1}SpaceTangent, IN.{1}SpaceBiTangent, IN.{1}SpaceNormal));", transposeTargetTransformString, CoordinateSpace.World.ToString()), true);
            }
            else if (requiresTangentTransform)
            {
                visitor.AddShaderChunk(string.Format("float3x3 {0} = float3x3(IN.{1}SpaceTangent, IN.{1}SpaceBiTangent, IN.{1}SpaceNormal);", targetTransformString, tangentTransformSpace), true);
            }
            visitor.AddShaderChunk(string.Format("{0} {1} = {2};", NodeUtils.ConvertConcreteSlotValueTypeToString(precision, FindOutputSlot <MaterialSlot>(OutputSlotId).concreteValueType),
                                                 GetVariableNameForSlot(OutputSlotId),
                                                 transformString), true);
        }
Example #14
0
 string GetFunctionName()
 {
     return("Unity_Flip_" + NodeUtils.ConvertConcreteSlotValueTypeToString(precision, FindOutputSlot <MaterialSlot>(OutputSlotId).concreteValueType));
 }
 private string GetParamTypeName(MaterialSlot slot)
 {
     return(NodeUtils.ConvertConcreteSlotValueTypeToString(precision, slot.concreteValueType));
 }
Example #16
0
        public void GenerateNodeCode(ShaderGenerator visitor, GraphContext graphContext, GenerationMode generationMode)
        {
            var sb = new ShaderStringBuilder();

            if (subGraphData == null || hasError)
            {
                var outputSlots = new List <MaterialSlot>();
                GetOutputSlots(outputSlots);
                foreach (var slot in outputSlots)
                {
                    visitor.AddShaderChunk($"{NodeUtils.ConvertConcreteSlotValueTypeToString(precision, slot.concreteValueType)} {GetVariableNameForSlot(slot.id)} = {slot.GetDefaultValue(GenerationMode.ForReals)};");
                }

                return;
            }

            var inputVariableName = $"_{GetVariableNameForNode()}";

            GraphUtil.GenerateSurfaceInputTransferCode(sb, subGraphData.requirements, subGraphData.inputStructName, inputVariableName);

            visitor.AddShaderChunk(sb.ToString());

            foreach (var outSlot in subGraphData.outputs)
            {
                visitor.AddShaderChunk(string.Format("{0} {1};", NodeUtils.ConvertConcreteSlotValueTypeToString(precision, outSlot.concreteValueType), GetVariableNameForSlot(outSlot.id)));
            }

            var arguments = new List <string>();

            foreach (var prop in subGraphData.inputs)
            {
                var inSlotId = m_PropertyIds[m_PropertyGuids.IndexOf(prop.guid.ToString())];

                if (prop is TextureShaderProperty)
                {
                    arguments.Add(string.Format("TEXTURE2D_ARGS({0}, sampler{0})", GetSlotValue(inSlotId, generationMode)));
                }
                else if (prop is Texture2DArrayShaderProperty)
                {
                    arguments.Add(string.Format("TEXTURE2D_ARRAY_ARGS({0}, sampler{0})", GetSlotValue(inSlotId, generationMode)));
                }
                else if (prop is Texture3DShaderProperty)
                {
                    arguments.Add(string.Format("TEXTURE3D_ARGS({0}, sampler{0})", GetSlotValue(inSlotId, generationMode)));
                }
                else if (prop is CubemapShaderProperty)
                {
                    arguments.Add(string.Format("TEXTURECUBE_ARGS({0}, sampler{0})", GetSlotValue(inSlotId, generationMode)));
                }
                else
                {
                    arguments.Add(GetSlotValue(inSlotId, generationMode));
                }
            }

            // pass surface inputs through
            arguments.Add(inputVariableName);

            foreach (var outSlot in subGraphData.outputs)
            {
                arguments.Add(GetVariableNameForSlot(outSlot.id));
            }

            visitor.AddShaderChunk(
                string.Format("{0}({1});"
                              , subGraphData.functionName
                              , arguments.Aggregate((current, next) => string.Format("{0}, {1}", current, next))));
        }
Example #17
0
 string GetFunctionPrototype(string argIn, string argOut)
 {
     return(string.Format("void {0} ({1} {2}, out {3} {4})", GetFunctionName(), NodeUtils.ConvertConcreteSlotValueTypeToString(precision, FindInputSlot <DynamicVectorMaterialSlot>(InputSlotId).concreteValueType), argIn, NodeUtils.ConvertConcreteSlotValueTypeToString(precision, FindOutputSlot <DynamicVectorMaterialSlot>(OutputSlotId).concreteValueType), argOut));
 }
Example #18
0
 protected string GetFunctionPrototype(string arg1Name, string arg2Name)
 {
     return(string.Format("inline {0} {1} ({2} {3}, {4} {5})", NodeUtils.ConvertConcreteSlotValueTypeToString(precision, FindInputSlot <MaterialSlot>(InputSlot2Id).concreteValueType), GetFunctionName(), NodeUtils.ConvertConcreteSlotValueTypeToString(precision, FindInputSlot <MaterialSlot>(InputSlot1Id).concreteValueType), arg1Name, NodeUtils.ConvertConcreteSlotValueTypeToString(precision, FindInputSlot <MaterialSlot>(InputSlot2Id).concreteValueType), arg2Name));
 }
 internal static void GenerateSurfaceDescriptionStruct(ShaderGenerator surfaceDescriptionStruct, List <MaterialSlot> slots, bool isMaster)
 {
     surfaceDescriptionStruct.AddShaderChunk("struct SurfaceDescription{", false);
     surfaceDescriptionStruct.Indent();
     if (isMaster)
     {
         foreach (var slot in slots)
         {
             surfaceDescriptionStruct.AddShaderChunk(String.Format("{0} {1};", NodeUtils.ConvertConcreteSlotValueTypeToString(AbstractMaterialNode.OutputPrecision.@float, slot.concreteValueType), NodeUtils.GetHLSLSafeName(slot.shaderOutputName)), false);
         }
         surfaceDescriptionStruct.Deindent();
     }
     else
     {
         surfaceDescriptionStruct.AddShaderChunk("float4 PreviewOutput;", false);
     }
     surfaceDescriptionStruct.Deindent();
     surfaceDescriptionStruct.AddShaderChunk("};", false);
 }
Example #20
0
        public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
        {
            NodeUtils.SlotConfigurationExceptionIfBadConfiguration(this, new[] { InputSlotId }, new[] { OutputSlotId });
            string inputValue                        = string.Format("{0}.xyz", GetSlotValue(InputSlotId, generationMode));
            string targetTransformString             = "tangentTransform_" + conversion.from.ToString();
            string transposeTargetTransformString    = "transposeTangent";
            string transformString                   = "";
            string tangentTransformSpace             = conversion.from.ToString();
            bool   requiresTangentTransform          = false;
            bool   requiresTransposeTangentTransform = false;

            if (conversion.from == CoordinateSpace.World)
            {
                if (conversion.to == CoordinateSpace.World)
                {
                    transformString = inputValue;
                }
                else if (conversion.to == CoordinateSpace.Object)
                {
                    transformString = "mul(unity_WorldToObject, float4(" + inputValue + ", 0)).xyz";
                }
                else if (conversion.to == CoordinateSpace.Tangent)
                {
                    requiresTangentTransform = true;
                    transformString          = "mul(" + inputValue + ", " + targetTransformString + ").xyz";
                }
                else if (conversion.to == CoordinateSpace.View)
                {
                    transformString = "mul( UNITY_MATRIX_V, float4(" + inputValue + ", 0)).xyz";
                }
            }
            else if (conversion.from == CoordinateSpace.Object)
            {
                if (conversion.to == CoordinateSpace.World)
                {
                    transformString = "mul(unity_ObjectToWorld, float4(" + inputValue + ", 0)).xyz";
                }
                else if (conversion.to == CoordinateSpace.Object)
                {
                    transformString = inputValue;
                }
                else if (conversion.to == CoordinateSpace.Tangent)
                {
                    requiresTangentTransform = true;
                    transformString          = "mul(float4(" + inputValue + ", 0).xyz, " + targetTransformString + ").xyz";
                }
                else if (conversion.to == CoordinateSpace.View)
                {
                    transformString = "mul( UNITY_MATRIX_MV, float4(" + inputValue + ", 0)).xyz";
                }
            }
            else if (conversion.from == CoordinateSpace.Tangent)
            {
                if (conversion.to == CoordinateSpace.World)
                {
                    requiresTransposeTangentTransform = true;
                    transformString = "mul( " + inputValue + ", " + transposeTargetTransformString + " ).xyz";
                }
                else if (conversion.to == CoordinateSpace.Object)
                {
                    requiresTransposeTangentTransform = true;
                    transformString = "mul( unity_WorldToObject, float4(mul(" + inputValue + ", " + transposeTargetTransformString + " ),0) ).xyz";
                }
                else if (conversion.to == CoordinateSpace.Tangent)
                {
                    transformString = inputValue;
                }
                else if (conversion.to == CoordinateSpace.View)
                {
                    requiresTransposeTangentTransform = true;
                    transformString = "mul( UNITY_MATRIX_V, float4(mul(" + inputValue + ", " + transposeTargetTransformString + " ),0) ).xyz";
                }
            }
            else if (conversion.from == CoordinateSpace.View)
            {
                if (conversion.to == CoordinateSpace.World)
                {
                    transformString = "mul( float4(" + inputValue + ", 0), UNITY_MATRIX_V ).xyz";
                }
                else if (conversion.to == CoordinateSpace.Object)
                {
                    transformString = "mul( float4(" + inputValue + ", 0), UNITY_MATRIX_MV ).xyz";
                }
                else if (conversion.to == CoordinateSpace.Tangent)
                {
                    requiresTangentTransform = true;
                    tangentTransformSpace    = CoordinateSpace.World.ToString();
                    transformString          = "mul( mul( float4(" + inputValue + ", 0), UNITY_MATRIX_V ).xyz, " + targetTransformString + ").xyz";
                }
                else if (conversion.to == CoordinateSpace.View)
                {
                    transformString = inputValue;
                }
            }

            if (requiresTransposeTangentTransform)
            {
                visitor.AddShaderChunk("float3x3 " + transposeTargetTransformString + " = transpose(float3x3(" + CoordinateSpace.World.ToString() + "SpaceTangent, " + CoordinateSpace.World.ToString() + "SpaceBiTangent, " + CoordinateSpace.World.ToString() + "SpaceNormal));", true);
            }
            else if (requiresTangentTransform)
            {
                visitor.AddShaderChunk("float3x3 " + targetTransformString + " = float3x3(" + tangentTransformSpace + "SpaceTangent, " + tangentTransformSpace + "SpaceBiTangent, " + tangentTransformSpace + "SpaceNormal);", true);
            }

            visitor.AddShaderChunk(string.Format("{0} {1} = {2};", NodeUtils.ConvertConcreteSlotValueTypeToString(precision, FindOutputSlot <MaterialSlot>(OutputSlotId).concreteValueType),
                                                 GetVariableNameForSlot(OutputSlotId),
                                                 transformString), true);
        }