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); }
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)); } } }
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); }
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)); }
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))); }
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); }
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;"); } } }
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); }
public static string ToString(this ConcreteSlotValueType type, AbstractMaterialNode.OutputPrecision precision) { return(NodeUtils.ConvertConcreteSlotValueTypeToString(precision, type)); }
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); }
string GetFunctionName() { return("Unity_Flip_" + NodeUtils.ConvertConcreteSlotValueTypeToString(precision, FindOutputSlot <MaterialSlot>(OutputSlotId).concreteValueType)); }
private string GetParamTypeName(MaterialSlot slot) { return(NodeUtils.ConvertConcreteSlotValueTypeToString(precision, slot.concreteValueType)); }
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)))); }
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)); }
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); }
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); }