Example #1
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} = CreateWorldToTangent(IN.{1}SpaceNormal, IN.{1}SpaceTangent, 1);", targetTransformString, tangentTransformSpace), true);
            }
            visitor.AddShaderChunk(string.Format("{0} {1} = {2};", NodeUtils.ConvertConcreteSlotValueTypeToString(precision, FindOutputSlot <MaterialSlot>(OutputSlotId).concreteValueType),
                                                 GetVariableNameForSlot(OutputSlotId),
                                                 transformString), true);
        }
Example #2
0
        /// <summary>
        /// Called when Enter Sketch is pressed. If a node is selected in the tree or a shape is selected on the drawing stage,
        /// the sketch containing that node/shape is selected for editing, otherwise a new sketch will be created in OnMouseDownAction
        /// </summary>
        public override void OnActivate()
        {
            base.OnActivate();
            if (Document.Root.Children.Count > 0)
            {
                Inputs[InputNames.SelectionContainerPipe].Send(NotificationNames.SwitchSelectionMode,
                                                               TopAbsShapeEnum.TopAbs_FACE);
            }
            else
            {
                Inputs[InputNames.SelectionContainerPipe].Send(NotificationNames.SwitchSelectionMode,
                                                               TopAbsShapeEnum.TopAbs_SOLID);
            }
            ActionsGraph[InputNames.CoordinateParser].Send(CoordinatateParserNames.SetStage, ParserStage.Unknown);
            Inputs[InputNames.SelectionContainerPipe].Send(NotificationNames.Enable);
            Inputs[InputNames.FacePickerPlane].Send(NotificationNames.Disable);
            Reset();
            ShowHint(ModelingResources.StartSketch);
            Inputs[InputNames.GeometricSolverPipe].Send(NotificationNames.DisableAll);
            var uiBuilder     = ActionsGraph[InputNames.UiBuilderInput].Get <UiBuilder>();
            var sketchControl = uiBuilder.GetItemAtPath("Ribbon/Modelling/Sketch/Sketch");

            _sketchButton = (ISketchButton)sketchControl;
            var  selected = Inputs[InputNames.SelectionContainerPipe].GetData(NotificationNames.GetEntities).Get <List <SceneSelectedEntity> >();
            Node node     = null;

            if (selected.Count > 0)
            {
                node = selected[0].Node;
            }
            else
            {
                node = Inputs[InputNames.NodeSelect].GetData(NotificationNames.GetValue).Get <Node>();
            }
            if (node != null)
            {
                Node sketchNode = AutoGroupLogic.FindSketchNode(node);

                if (sketchNode != null)
                {
                    Document.Transact();
                    Document.Root.Get <DocumentContextInterpreter>().ActiveSketch = sketchNode.Index;
                    NodeUtils.SetSketchTransparency(Document, sketchNode, 0);
                    Inputs[InputNames.Mouse3DEventsPipe].Send(NotificationNames.Resume);
                    var axis  = new NodeBuilder(sketchNode)[0].TransformedAxis3D;
                    var plane = new gpPln(new gpAx3(axis.Location, axis.Direction));
                    Inputs[InputNames.Mouse3DEventsPipe].Send(NotificationNames.SetPlane, plane);
                    //if (Inputs[InputNames.Mouse3DEventsPipe].GetData(NotificationNames.GetPlane).Data == null)
                    //{
                    //    var plane = new gpPln(new gpAx3());
                    //    Inputs[InputNames.Mouse3DEventsPipe].Send(NotificationNames.SetPlane, plane);
                    //    //ActionsGraph[InputNames.View].Send(NotificationNames.SwitchView, plane);
                    //}
                    _sketchButton.Block();
                    HighlightCurrentSketchNodes(sketchNode);
                    Document.Commit("Started editing sketch");
                    BackToNeutralModifier();

                    Log.Info("StartSketch - current sketch exists");
                    _sketchButton.Block();
                    return;
                }
            }
            if (Document.Root.Children.Count == 0)
            {
                CreatePlane(new Point3D(-20, -10, 0), new Point3D(20, -10, 0),
                            new Point3D(20, 10, 0), new Point3D(-20, 10, 0), "Top");
                CreatePlane(new Point3D(-20, 0, -10), new Point3D(20, 0, -10),
                            new Point3D(20, 0, 10), new Point3D(-20, 0, 10), "Right");
                CreatePlane(new Point3D(0, -20, -10), new Point3D(0, 20, -10),
                            new Point3D(0, 20, 10), new Point3D(0, -20, 10), "Front");
                Document.Commit("Default planes created");
            }
            Inputs[InputNames.FacePickerPlane].Send(NotificationNames.Enable);
            Inputs[InputNames.SelectionContainerPipe].Send(NotificationNames.SwitchSelectionMode,
                                                           TopAbsShapeEnum.TopAbs_FACE);
            Inputs[InputNames.Mouse3DEventsPipe].Send(NotificationNames.Resume);
            var sketchCreator = new SketchCreator(Document, false);

            if (sketchCreator.CurrentSketch == null)
            {
                ShowHint(ModelingResources.StartSketch);
                Log.Info("StartSketch - no current sketch");
            }
        }
Example #3
0
 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 #4
0
        // TODO: Fix this
        static ShaderGraphVfxAsset GenerateVfxShaderGraphAsset(GraphData graph)
        {
            var target = graph.activeTargets.FirstOrDefault(x => x is VFXTarget) as VFXTarget;

            if (target == null)
            {
                return(null);
            }

            var nl     = Environment.NewLine;
            var indent = new string(' ', 4);
            var asset  = ScriptableObject.CreateInstance <ShaderGraphVfxAsset>();
            var result = asset.compilationResult = new GraphCompilationResult();
            var mode   = GenerationMode.ForReals;

            asset.lit           = target.lit;
            asset.alphaClipping = target.alphaTest;

            var assetGuid = graph.assetGuid;
            var assetPath = AssetDatabase.GUIDToAssetPath(assetGuid);
            var hlslName  = NodeUtils.GetHLSLSafeName(Path.GetFileNameWithoutExtension(assetPath));

            var ports = new List <MaterialSlot>();
            var nodes = new List <AbstractMaterialNode>();

            foreach (var vertexBlock in graph.vertexContext.blocks)
            {
                vertexBlock.value.GetInputSlots(ports);
                NodeUtils.DepthFirstCollectNodesFromNode(nodes, vertexBlock);
            }

            foreach (var fragmentBlock in graph.fragmentContext.blocks)
            {
                fragmentBlock.value.GetInputSlots(ports);
                NodeUtils.DepthFirstCollectNodesFromNode(nodes, fragmentBlock);
            }

            //Remove inactive blocks from generation
            {
                var tmpCtx = new TargetActiveBlockContext(new List <BlockFieldDescriptor>(), null);
                target.GetActiveBlocks(ref tmpCtx);
                ports.RemoveAll(materialSlot =>
                {
                    return(!tmpCtx.activeBlocks.Any(o => materialSlot.RawDisplayName() == o.displayName));
                });
            }

            var bodySb   = new ShaderStringBuilder(1);
            var registry = new FunctionRegistry(new ShaderStringBuilder(), true);

            foreach (var properties in graph.properties)
            {
                properties.ValidateConcretePrecision(graph.concretePrecision);
            }

            foreach (var node in nodes)
            {
                if (node is IGeneratesBodyCode bodyGenerator)
                {
                    bodySb.currentNode = node;
                    bodyGenerator.GenerateNodeCode(bodySb, mode);
                    bodySb.ReplaceInCurrentMapping(PrecisionUtil.Token, node.concretePrecision.ToShaderString());
                }

                if (node is IGeneratesFunction generatesFunction)
                {
                    registry.builder.currentNode = node;
                    generatesFunction.GenerateNodeFunction(registry, mode);
                }
            }
            bodySb.currentNode = null;

            var portNodeSets = new HashSet <AbstractMaterialNode> [ports.Count];

            for (var portIndex = 0; portIndex < ports.Count; portIndex++)
            {
                var port    = ports[portIndex];
                var nodeSet = new HashSet <AbstractMaterialNode>();
                NodeUtils.CollectNodeSet(nodeSet, port);
                portNodeSets[portIndex] = nodeSet;
            }

            var portPropertySets = new HashSet <string> [ports.Count];

            for (var portIndex = 0; portIndex < ports.Count; portIndex++)
            {
                portPropertySets[portIndex] = new HashSet <string>();
            }

            foreach (var node in nodes)
            {
                if (!(node is PropertyNode propertyNode))
                {
                    continue;
                }

                for (var portIndex = 0; portIndex < ports.Count; portIndex++)
                {
                    var portNodeSet = portNodeSets[portIndex];
                    if (portNodeSet.Contains(node))
                    {
                        portPropertySets[portIndex].Add(propertyNode.property.objectId);
                    }
                }
            }

            var shaderProperties = new PropertyCollector();

            foreach (var node in nodes)
            {
                node.CollectShaderProperties(shaderProperties, GenerationMode.ForReals);
            }

            asset.SetTextureInfos(shaderProperties.GetConfiguredTexutres());

            var codeSnippets      = new List <string>();
            var portCodeIndices   = new List <int> [ports.Count];
            var sharedCodeIndices = new List <int>();

            for (var i = 0; i < portCodeIndices.Length; i++)
            {
                portCodeIndices[i] = new List <int>();
            }

            sharedCodeIndices.Add(codeSnippets.Count);
            codeSnippets.Add($"#include \"Packages/com.unity.shadergraph/ShaderGraphLibrary/Functions.hlsl\"{nl}");

            for (var registryIndex = 0; registryIndex < registry.names.Count; registryIndex++)
            {
                var name      = registry.names[registryIndex];
                var source    = registry.sources[name];
                var precision = source.nodes.First().concretePrecision;

                var hasPrecisionMismatch = false;
                var nodeNames            = new HashSet <string>();
                foreach (var node in source.nodes)
                {
                    nodeNames.Add(node.name);
                    if (node.concretePrecision != precision)
                    {
                        hasPrecisionMismatch = true;
                        break;
                    }
                }

                if (hasPrecisionMismatch)
                {
                    var message = new StringBuilder($"Precision mismatch for function {name}:");
                    foreach (var node in source.nodes)
                    {
                        message.AppendLine($"{node.name} ({node.objectId}): {node.concretePrecision}");
                    }
                    throw new InvalidOperationException(message.ToString());
                }

                var code = source.code.Replace(PrecisionUtil.Token, precision.ToShaderString());
                code = $"// Node: {string.Join(", ", nodeNames)}{nl}{code}";
                var codeIndex = codeSnippets.Count;
                codeSnippets.Add(code + nl);
                for (var portIndex = 0; portIndex < ports.Count; portIndex++)
                {
                    var portNodeSet = portNodeSets[portIndex];
                    foreach (var node in source.nodes)
                    {
                        if (portNodeSet.Contains(node))
                        {
                            portCodeIndices[portIndex].Add(codeIndex);
                            break;
                        }
                    }
                }
            }

            foreach (var property in graph.properties)
            {
                if (property.isExposable && property.generatePropertyBlock)
                {
                    continue;
                }

                for (var portIndex = 0; portIndex < ports.Count; portIndex++)
                {
                    var portPropertySet = portPropertySets[portIndex];
                    if (portPropertySet.Contains(property.objectId))
                    {
                        portCodeIndices[portIndex].Add(codeSnippets.Count);
                    }
                }

                codeSnippets.Add($"// Property: {property.displayName}{nl}{property.GetPropertyDeclarationString()}{nl}{nl}");
            }



            var inputStructName        = $"SG_Input_{assetGuid}";
            var outputStructName       = $"SG_Output_{assetGuid}";
            var evaluationFunctionName = $"SG_Evaluate_{assetGuid}";

            #region Input Struct

            sharedCodeIndices.Add(codeSnippets.Count);
            codeSnippets.Add($"struct {inputStructName}{nl}{{{nl}");

            #region Requirements

            var portRequirements = new ShaderGraphRequirements[ports.Count];
            for (var portIndex = 0; portIndex < ports.Count; portIndex++)
            {
                var requirementsNodes = portNodeSets[portIndex].ToList();
                requirementsNodes.Add(ports[portIndex].owner);
                portRequirements[portIndex] = ShaderGraphRequirements.FromNodes(requirementsNodes, ports[portIndex].stageCapability);
            }

            var portIndices = new List <int>();
            portIndices.Capacity = ports.Count;

            void AddRequirementsSnippet(Func <ShaderGraphRequirements, bool> predicate, string snippet)
            {
                portIndices.Clear();
                for (var portIndex = 0; portIndex < ports.Count; portIndex++)
                {
                    if (predicate(portRequirements[portIndex]))
                    {
                        portIndices.Add(portIndex);
                    }
                }

                if (portIndices.Count > 0)
                {
                    foreach (var portIndex in portIndices)
                    {
                        portCodeIndices[portIndex].Add(codeSnippets.Count);
                    }

                    codeSnippets.Add($"{indent}{snippet};{nl}");
                }
            }

            void AddCoordinateSpaceSnippets(InterpolatorType interpolatorType, Func <ShaderGraphRequirements, NeededCoordinateSpace> selector)
            {
                foreach (var space in EnumInfo <CoordinateSpace> .values)
                {
                    var neededSpace = space.ToNeededCoordinateSpace();
                    AddRequirementsSnippet(r => (selector(r) & neededSpace) > 0, $"float3 {space.ToVariableName(interpolatorType)}");
                }
            }

            // TODO: Rework requirements system to make this better
            AddCoordinateSpaceSnippets(InterpolatorType.Normal, r => r.requiresNormal);
            AddCoordinateSpaceSnippets(InterpolatorType.Tangent, r => r.requiresTangent);
            AddCoordinateSpaceSnippets(InterpolatorType.BiTangent, r => r.requiresBitangent);
            AddCoordinateSpaceSnippets(InterpolatorType.ViewDirection, r => r.requiresViewDir);
            AddCoordinateSpaceSnippets(InterpolatorType.Position, r => r.requiresPosition);

            AddRequirementsSnippet(r => r.requiresVertexColor, $"float4 {ShaderGeneratorNames.VertexColor}");
            AddRequirementsSnippet(r => r.requiresScreenPosition, $"float4 {ShaderGeneratorNames.ScreenPosition}");
            AddRequirementsSnippet(r => r.requiresFaceSign, $"float4 {ShaderGeneratorNames.FaceSign}");

            foreach (var uvChannel in EnumInfo <UVChannel> .values)
            {
                AddRequirementsSnippet(r => r.requiresMeshUVs.Contains(uvChannel), $"half4 {uvChannel.GetUVName()}");
            }

            AddRequirementsSnippet(r => r.requiresTime, $"float3 {ShaderGeneratorNames.TimeParameters}");

            #endregion

            sharedCodeIndices.Add(codeSnippets.Count);
            codeSnippets.Add($"}};{nl}{nl}");

            #endregion

            // VFX Code heavily relies on the slotId from the original MasterNodes
            // Since we keep these around for upgrades anyway, for now it is simpler to use them
            // Therefore we remap the output blocks back to the original Ids here
            var originialPortIds = new int[ports.Count];
            for (int i = 0; i < originialPortIds.Length; i++)
            {
                if (!VFXTarget.s_BlockMap.TryGetValue((ports[i].owner as BlockNode).descriptor, out var originalId))
                {
                    continue;
                }

                // In Master Nodes we had a different BaseColor/Color slot id between Unlit/Lit
                // In the stack we use BaseColor for both cases. Catch this here.
                if (asset.lit && originalId == ShaderGraphVfxAsset.ColorSlotId)
                {
                    originalId = ShaderGraphVfxAsset.BaseColorSlotId;
                }

                originialPortIds[i] = originalId;
            }

            #region Output Struct

            sharedCodeIndices.Add(codeSnippets.Count);
            codeSnippets.Add($"struct {outputStructName}{nl}{{");

            for (var portIndex = 0; portIndex < ports.Count; portIndex++)
            {
                var port = ports[portIndex];
                portCodeIndices[portIndex].Add(codeSnippets.Count);
                codeSnippets.Add($"{nl}{indent}{port.concreteValueType.ToShaderString(graph.concretePrecision)} {port.shaderOutputName}_{originialPortIds[portIndex]};");
            }

            sharedCodeIndices.Add(codeSnippets.Count);
            codeSnippets.Add($"{nl}}};{nl}{nl}");

            #endregion

            #region Graph Function

            sharedCodeIndices.Add(codeSnippets.Count);
            codeSnippets.Add($"{outputStructName} {evaluationFunctionName}({nl}{indent}{inputStructName} IN");

            var inputProperties     = new List <AbstractShaderProperty>();
            var portPropertyIndices = new List <int> [ports.Count];
            for (var portIndex = 0; portIndex < ports.Count; portIndex++)
            {
                portPropertyIndices[portIndex] = new List <int>();
            }

            foreach (var property in graph.properties)
            {
                if (!property.isExposable || !property.generatePropertyBlock)
                {
                    continue;
                }

                var propertyIndex = inputProperties.Count;
                var codeIndex     = codeSnippets.Count;

                for (var portIndex = 0; portIndex < ports.Count; portIndex++)
                {
                    var portPropertySet = portPropertySets[portIndex];
                    if (portPropertySet.Contains(property.objectId))
                    {
                        portCodeIndices[portIndex].Add(codeIndex);
                        portPropertyIndices[portIndex].Add(propertyIndex);
                    }
                }

                inputProperties.Add(property);
                codeSnippets.Add($",{nl}{indent}/* Property: {property.displayName} */ {property.GetPropertyAsArgumentString()}");
            }

            sharedCodeIndices.Add(codeSnippets.Count);
            codeSnippets.Add($"){nl}{{");

            #region Node Code

            for (var mappingIndex = 0; mappingIndex < bodySb.mappings.Count; mappingIndex++)
            {
                var mapping = bodySb.mappings[mappingIndex];
                var code    = bodySb.ToString(mapping.startIndex, mapping.count);
                if (string.IsNullOrWhiteSpace(code))
                {
                    continue;
                }

                code = $"{nl}{indent}// Node: {mapping.node.name}{nl}{code}";
                var codeIndex = codeSnippets.Count;
                codeSnippets.Add(code);
                for (var portIndex = 0; portIndex < ports.Count; portIndex++)
                {
                    var portNodeSet = portNodeSets[portIndex];
                    if (portNodeSet.Contains(mapping.node))
                    {
                        portCodeIndices[portIndex].Add(codeIndex);
                    }
                }
            }

            #endregion

            #region Output Mapping

            sharedCodeIndices.Add(codeSnippets.Count);
            codeSnippets.Add($"{nl}{indent}// VFXMasterNode{nl}{indent}{outputStructName} OUT;{nl}");

            // Output mapping
            for (var portIndex = 0; portIndex < ports.Count; portIndex++)
            {
                var port = ports[portIndex];
                portCodeIndices[portIndex].Add(codeSnippets.Count);
                codeSnippets.Add($"{indent}OUT.{port.shaderOutputName}_{originialPortIds[portIndex]} = {port.owner.GetSlotValue(port.id, GenerationMode.ForReals, graph.concretePrecision)};{nl}");
            }

            #endregion

            // Function end
            sharedCodeIndices.Add(codeSnippets.Count);
            codeSnippets.Add($"{indent}return OUT;{nl}}}{nl}");

            #endregion

            result.codeSnippets      = codeSnippets.ToArray();
            result.sharedCodeIndices = sharedCodeIndices.ToArray();
            result.outputCodeIndices = new IntArray[ports.Count];
            for (var i = 0; i < ports.Count; i++)
            {
                result.outputCodeIndices[i] = portCodeIndices[i].ToArray();
            }

            var outputMetadatas = new OutputMetadata[ports.Count];
            for (int portIndex = 0; portIndex < outputMetadatas.Length; portIndex++)
            {
                outputMetadatas[portIndex] = new OutputMetadata(portIndex, ports[portIndex].shaderOutputName, originialPortIds[portIndex]);
            }

            asset.SetOutputs(outputMetadatas);

            asset.evaluationFunctionName = evaluationFunctionName;
            asset.inputStructName        = inputStructName;
            asset.outputStructName       = outputStructName;
            asset.portRequirements       = portRequirements;
            asset.concretePrecision      = graph.concretePrecision;
            asset.SetProperties(inputProperties);
            asset.outputPropertyIndices = new IntArray[ports.Count];
            for (var portIndex = 0; portIndex < ports.Count; portIndex++)
            {
                asset.outputPropertyIndices[portIndex] = portPropertyIndices[portIndex].ToArray();
            }

            return(asset);
        }
Example #5
0
        public int AddSlot(ConcreteSlotValueType concreteValueType)
        {
            var    index = this.GetInputSlots <ISlot>().Count() + 1;
            string name  = string.Format("Out_{0}", NodeUtils.GetDuplicateSafeNameForSlot(this, index, concreteValueType.ToString()));

            AddSlot(MaterialSlot.CreateMaterialSlot(concreteValueType.ToSlotValueType(), index, name, NodeUtils.GetHLSLSafeName(name), SlotType.Input, Vector4.zero));
            return(index);
        }
Example #6
0
        public void CanGetPermutationMapPerNode()
        {
            var previewNode = m_Graph.GetNodes <PreviewNode>().FirstOrDefault();

            Assert.IsNotNull(previewNode, "Preview Node not in graph.");

            var descendentNodes = new List <AbstractMaterialNode>();

            NodeUtils.DepthFirstCollectNodesFromNode(descendentNodes, previewNode, NodeUtils.IncludeSelf.Include);
            List <int>[] keywordPermutationsPerNode = new List <int> [descendentNodes.Count];
            Assert.IsNotEmpty(descendentNodes, "No Nodes in graph.");

            for (int i = 0; i < m_Collector.permutations.Count; i++)
            {
                var localNodes = ListPool <AbstractMaterialNode> .Get();

                NodeUtils.DepthFirstCollectNodesFromNode(localNodes, previewNode, NodeUtils.IncludeSelf.Include, keywordPermutation: m_Collector.permutations[i]);

                foreach (AbstractMaterialNode node in localNodes)
                {
                    int nodeIndex = descendentNodes.IndexOf(node);

                    if (keywordPermutationsPerNode[nodeIndex] == null)
                    {
                        keywordPermutationsPerNode[nodeIndex] = new List <int>();
                    }
                    keywordPermutationsPerNode[nodeIndex].Add(i);
                }
            }

            ShaderKeyword booleanAKeyword = m_Collector.keywords.Where(x => x.displayName == "Boolean A").FirstOrDefault();
            ShaderKeyword booleanBKeyword = m_Collector.keywords.Where(x => x.displayName == "Boolean B").FirstOrDefault();
            ShaderKeyword enumAKeyword    = m_Collector.keywords.Where(x => x.displayName == "Enum A").FirstOrDefault();
            ShaderKeyword enumBKeyword    = m_Collector.keywords.Where(x => x.displayName == "Enum B").FirstOrDefault();

            if (booleanAKeyword == null || booleanBKeyword == null || enumAKeyword == null || enumBKeyword == null)
            {
                Assert.Fail("One or more Keywords not in graph.");
            }

            var         keywordNodes = m_Graph.GetNodes <KeywordNode>().ToList();
            KeywordNode booleanANode = keywordNodes.Where(x => x.keywordGuid == booleanAKeyword.guid).FirstOrDefault();
            KeywordNode booleanBNode = keywordNodes.Where(x => x.keywordGuid == booleanBKeyword.guid).FirstOrDefault();
            KeywordNode enumANode    = keywordNodes.Where(x => x.keywordGuid == enumAKeyword.guid).FirstOrDefault();
            KeywordNode enumBNode    = keywordNodes.Where(x => x.keywordGuid == enumBKeyword.guid).FirstOrDefault();

            if (booleanANode == null || booleanBNode == null || enumANode == null || enumBNode == null)
            {
                Assert.Fail("One or more Keywords Nodes not in graph.");
            }

            int        booleanAIndex        = descendentNodes.IndexOf(booleanANode);
            List <int> booleanAPermutations = keywordPermutationsPerNode[booleanAIndex];

            Assert.AreEqual(24, booleanAPermutations.Count, "Boolean A had incorrect permutations.");

            int        booleanBIndex        = descendentNodes.IndexOf(booleanBNode);
            List <int> booleanBPermutations = keywordPermutationsPerNode[booleanBIndex];

            Assert.AreEqual(48, booleanBPermutations.Count, "Boolean B had incorrect permutations.");

            int        enumAIndex        = descendentNodes.IndexOf(enumANode);
            List <int> enumAPermutations = keywordPermutationsPerNode[enumAIndex];

            Assert.AreEqual(12, enumAPermutations.Count, "Enum A had incorrect permutations.");

            int        enumBIndex        = descendentNodes.IndexOf(enumBNode);
            List <int> enumBPermutations = keywordPermutationsPerNode[enumBIndex];

            Assert.AreEqual(24, enumBPermutations.Count, "Enum B had incorrect permutations.");
        }
 private string GetParamTypeName(MaterialSlot slot)
 {
     return(NodeUtils.ConvertConcreteSlotValueTypeToString(precision, slot.concreteValueType));
 }
        static void ProcessSubGraph(SubGraphAsset asset, GraphData graph)
        {
            var registry = new FunctionRegistry(new ShaderStringBuilder(), true);

            registry.names.Clear();
            asset.functions.Clear();
            asset.isValid = true;

            graph.OnEnable();
            graph.messageManager.ClearAll();
            graph.ValidateGraph();

            var assetPath = AssetDatabase.GUIDToAssetPath(asset.assetGuid);

            asset.hlslName        = NodeUtils.GetHLSLSafeName(Path.GetFileNameWithoutExtension(assetPath));
            asset.inputStructName = $"Bindings_{asset.hlslName}_{asset.assetGuid}";
            asset.functionName    = $"SG_{asset.hlslName}_{asset.assetGuid}";
            asset.path            = graph.path;

            var outputNode = graph.outputNode;

            var outputSlots = PooledList <MaterialSlot> .Get();

            outputNode.GetInputSlots(outputSlots);

            List <AbstractMaterialNode> nodes = new List <AbstractMaterialNode>();

            NodeUtils.DepthFirstCollectNodesFromNode(nodes, outputNode);

            asset.effectiveShaderStage = ShaderStageCapability.All;
            foreach (var slot in outputSlots)
            {
                var stage = NodeUtils.GetEffectiveShaderStageCapability(slot, true);
                if (stage != ShaderStageCapability.All)
                {
                    asset.effectiveShaderStage = stage;
                    break;
                }
            }

            asset.vtFeedbackVariables = VirtualTexturingFeedbackUtils.GetFeedbackVariables(outputNode as SubGraphOutputNode);
            asset.requirements        = ShaderGraphRequirements.FromNodes(nodes, asset.effectiveShaderStage, false);
            asset.graphPrecision      = graph.concretePrecision;
            asset.outputPrecision     = outputNode.concretePrecision;
            asset.previewMode         = graph.previewMode;

            GatherDescendentsFromGraph(new GUID(asset.assetGuid), out var containsCircularDependency, out var descendents);
            asset.descendents.AddRange(descendents.Select(g => g.ToString()));
            asset.descendents.Sort();   // ensure deterministic order

            var childrenSet = new HashSet <string>();
            var anyErrors   = false;

            foreach (var node in nodes)
            {
                if (node is SubGraphNode subGraphNode)
                {
                    var subGraphGuid = subGraphNode.subGraphGuid;
                    childrenSet.Add(subGraphGuid);
                }

                if (node.hasError)
                {
                    anyErrors = true;
                }
                asset.children = childrenSet.ToList();
                asset.children.Sort(); // ensure deterministic order
            }

            if (!anyErrors && containsCircularDependency)
            {
                Debug.LogError($"Error in Graph at {assetPath}: Sub Graph contains a circular dependency.", asset);
                anyErrors = true;
            }

            if (anyErrors)
            {
                asset.isValid = false;
                registry.ProvideFunction(asset.functionName, sb => {});
                return;
            }

            foreach (var node in nodes)
            {
                if (node is IGeneratesFunction generatesFunction)
                {
                    registry.builder.currentNode = node;
                    generatesFunction.GenerateNodeFunction(registry, GenerationMode.ForReals);
                    registry.builder.ReplaceInCurrentMapping(PrecisionUtil.Token, node.concretePrecision.ToShaderString());
                }
            }

            // provide top level subgraph function
            registry.ProvideFunction(asset.functionName, sb =>
            {
                GenerationUtils.GenerateSurfaceInputStruct(sb, asset.requirements, asset.inputStructName);
                sb.AppendNewLine();

                // Generate arguments... first INPUTS
                var arguments = new List <string>();
                foreach (var prop in graph.properties)
                {
                    prop.ValidateConcretePrecision(asset.graphPrecision);
                    arguments.Add(prop.GetPropertyAsArgumentString());
                }

                // now pass surface inputs
                arguments.Add(string.Format("{0} IN", asset.inputStructName));

                // Now generate outputs
                foreach (MaterialSlot output in outputSlots)
                {
                    arguments.Add($"out {output.concreteValueType.ToShaderString(asset.outputPrecision)} {output.shaderOutputName}_{output.id}");
                }

                // Vt Feedback arguments
                foreach (var output in asset.vtFeedbackVariables)
                {
                    arguments.Add($"out {ConcreteSlotValueType.Vector4.ToShaderString(ConcretePrecision.Single)} {output}_out");
                }

                // Create the function prototype from the arguments
                sb.AppendLine("void {0}({1})"
                              , asset.functionName
                              , arguments.Aggregate((current, next) => $"{current}, {next}"));

                // now generate the function
                using (sb.BlockScope())
                {
                    // Just grab the body from the active nodes
                    foreach (var node in nodes)
                    {
                        if (node is IGeneratesBodyCode generatesBodyCode)
                        {
                            sb.currentNode = node;
                            generatesBodyCode.GenerateNodeCode(sb, GenerationMode.ForReals);
                            sb.ReplaceInCurrentMapping(PrecisionUtil.Token, node.concretePrecision.ToShaderString());
                        }
                    }

                    foreach (var slot in outputSlots)
                    {
                        sb.AppendLine($"{slot.shaderOutputName}_{slot.id} = {outputNode.GetSlotValue(slot.id, GenerationMode.ForReals, asset.outputPrecision)};");
                    }

                    foreach (var slot in asset.vtFeedbackVariables)
                    {
                        sb.AppendLine($"{slot}_out = {slot};");
                    }
                }
            });

            asset.functions.AddRange(registry.names.Select(x => new FunctionPair(x, registry.sources[x].code)));

            var collector = new PropertyCollector();

            foreach (var node in nodes)
            {
                int previousPropertyCount = Math.Max(0, collector.propertyCount - 1);

                node.CollectShaderProperties(collector, GenerationMode.ForReals);

                // This is a stop-gap to prevent the autogenerated values from JsonObject and ShaderInput from
                // resulting in non-deterministic import data. While we should move to local ids in the future,
                // this will prevent cascading shader recompilations.
                for (int i = previousPropertyCount; i < collector.propertyCount; ++i)
                {
                    var prop        = collector.GetProperty(i);
                    var namespaceId = node.objectId;
                    var nameId      = prop.referenceName;

                    prop.OverrideObjectId(namespaceId, nameId + "_ObjectId_" + i);
                    prop.OverrideGuid(namespaceId, nameId + "_Guid_" + i);
                }
            }
            asset.WriteData(graph.properties, graph.keywords, collector.properties, outputSlots, graph.unsupportedTargets);
            outputSlots.Dispose();
        }
        static string GetExtraPassesFromTemplate(string template, UnlitMasterNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions)
        {
            // ----------------------------------------------------- //
            //                         SETUP                         //
            // ----------------------------------------------------- //

            // -------------------------------------
            // String builders

            var dummyBuilder     = new ShaderStringBuilder(0);
            var shaderProperties = new PropertyCollector();
            var functionBuilder  = new ShaderStringBuilder(1);
            var functionRegistry = new FunctionRegistry(functionBuilder);

            var defines = new ShaderStringBuilder(2);
            var graph   = new ShaderStringBuilder(0);

            var vertexDescriptionInputStruct = new ShaderStringBuilder(1);
            var vertexDescriptionStruct      = new ShaderStringBuilder(1);
            var vertexDescriptionFunction    = new ShaderStringBuilder(1);

            var vertexInputStruct = new ShaderStringBuilder(1);

            var vertexShader            = new ShaderStringBuilder(2);
            var vertexDescriptionInputs = new ShaderStringBuilder(2);

            // -------------------------------------
            // Get Slot and Node lists per stage

            var vertexSlots = pass.VertexShaderSlots.Select(masterNode.FindSlot <MaterialSlot>).ToList();
            var vertexNodes = ListPool <INode> .Get();

            NodeUtils.DepthFirstCollectNodesFromNode(vertexNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.VertexShaderSlots);

            // -------------------------------------
            // Get requirements

            var vertexRequirements = ShaderGraphRequirements.FromNodes(vertexNodes, ShaderStageCapability.Vertex, false);

            var modelRequiements = ShaderGraphRequirements.none;

            modelRequiements.requiresNormal   |= m_VertexCoordinateSpace;
            modelRequiements.requiresPosition |= m_VertexCoordinateSpace;
            modelRequiements.requiresMeshUVs.Add(UVChannel.UV1);

            // ----------------------------------------------------- //
            //                START SHADER GENERATION                //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Calculate material options

            var cullingBuilder = new ShaderStringBuilder(1);

            materialOptions.GetCull(cullingBuilder);

            // -------------------------------------
            // Generate defines

            if (masterNode.IsSlotConnected(PBRMasterNode.AlphaThresholdSlotId))
            {
                defines.AppendLine("#define _AlphaClip 1");
            }

            // ----------------------------------------------------- //
            //                START VERTEX DESCRIPTION               //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Generate Input structure for Vertex Description function
            // TODO - Vertex Description Input requirements are needed to exclude intermediate translation spaces

            vertexDescriptionInputStruct.AppendLine("struct VertexDescriptionInputs");
            using (vertexDescriptionInputStruct.BlockSemicolonScope())
            {
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresNormal, InterpolatorType.Normal, vertexDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresTangent, InterpolatorType.Tangent, vertexDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresBitangent, InterpolatorType.BiTangent, vertexDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresViewDir, InterpolatorType.ViewDirection, vertexDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresPosition, InterpolatorType.Position, vertexDescriptionInputStruct);

                if (vertexRequirements.requiresVertexColor)
                {
                    vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor);
                }

                if (vertexRequirements.requiresScreenPosition)
                {
                    vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition);
                }

                foreach (var channel in vertexRequirements.requiresMeshUVs.Distinct())
                {
                    vertexDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName());
                }
            }

            // -------------------------------------
            // Generate Output structure for Vertex Description function

            GraphUtil.GenerateVertexDescriptionStruct(vertexDescriptionStruct, vertexSlots);

            // -------------------------------------
            // Generate Vertex Description function

            GraphUtil.GenerateVertexDescriptionFunction(
                masterNode.owner as AbstractMaterialGraph,
                vertexDescriptionFunction,
                functionRegistry,
                shaderProperties,
                mode,
                vertexNodes,
                vertexSlots);

            // ----------------------------------------------------- //
            //           GENERATE VERTEX > PIXEL PIPELINE            //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Generate Input structure for Vertex shader

            GraphUtil.GenerateApplicationVertexInputs(vertexRequirements.Union(modelRequiements), vertexInputStruct);

            // -------------------------------------
            // Generate standard transformations
            // This method ensures all required transform data is available in vertex and pixel stages

            ShaderGenerator.GenerateStandardTransforms(
                3,
                10,
                dummyBuilder,
                vertexShader,
                vertexDescriptionInputs,
                dummyBuilder,
                dummyBuilder,
                dummyBuilder,
                ShaderGraphRequirements.none,
                ShaderGraphRequirements.none,
                modelRequiements,
                vertexRequirements,
                CoordinateSpace.World);

            // ----------------------------------------------------- //
            //                      FINALIZE                         //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Combine Graph sections

            graph.AppendLine(shaderProperties.GetPropertiesDeclaration(1));

            graph.AppendLine(vertexDescriptionInputStruct.ToString());

            graph.AppendLine(functionBuilder.ToString());

            graph.AppendLine(vertexDescriptionStruct.ToString());
            graph.AppendLine(vertexDescriptionFunction.ToString());

            graph.AppendLine(vertexInputStruct.ToString());

            // -------------------------------------
            // Generate final subshader

            var resultPass = template.Replace("${Culling}", cullingBuilder.ToString());

            resultPass = resultPass.Replace("${Defines}", defines.ToString());
            resultPass = resultPass.Replace("${Graph}", graph.ToString());
            resultPass = resultPass.Replace("${VertexShader}", vertexShader.ToString());
            resultPass = resultPass.Replace("${VertexShaderDescriptionInputs}", vertexDescriptionInputs.ToString());

            return(resultPass);
        }
 protected override string ConcreteSlotValueAsVariable()
 {
     return(NodeUtils.FloatToShaderValue(value));
 }
Example #11
0
        private static string GetShaderPassFromTemplate(string template, PBRMasterNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions)
        {
            var builder = new ShaderStringBuilder();

            builder.IncreaseIndent();
            builder.IncreaseIndent();
            var vertexInputs               = new ShaderGenerator();
            var surfaceVertexShader        = new ShaderGenerator();
            var surfaceDescriptionFunction = new ShaderGenerator();
            var surfaceDescriptionStruct   = new ShaderGenerator();
            var functionRegistry           = new FunctionRegistry(builder);
            var surfaceInputs              = new ShaderGenerator();

            var shaderProperties = new PropertyCollector();

            surfaceInputs.AddShaderChunk("struct SurfaceInputs{", false);
            surfaceInputs.Indent();

            var activeNodeList = ListPool <INode> .Get();

            NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, masterNode, NodeUtils.IncludeSelf.Include, pass.PixelShaderSlots);

            var requirements = ShaderGraphRequirements.FromNodes(activeNodeList);

            var modelRequiements = ShaderGraphRequirements.none;

            modelRequiements.requiresNormal    |= NeededCoordinateSpace.World;
            modelRequiements.requiresTangent   |= NeededCoordinateSpace.World;
            modelRequiements.requiresBitangent |= NeededCoordinateSpace.World;
            modelRequiements.requiresPosition  |= NeededCoordinateSpace.World;
            modelRequiements.requiresViewDir   |= NeededCoordinateSpace.World;
            modelRequiements.requiresMeshUVs.Add(UVChannel.UV1);

            GraphUtil.GenerateApplicationVertexInputs(requirements.Union(modelRequiements), vertexInputs);
            ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresNormal, InterpolatorType.Normal, surfaceInputs);
            ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresTangent, InterpolatorType.Tangent, surfaceInputs);
            ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresBitangent, InterpolatorType.BiTangent, surfaceInputs);
            ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresViewDir, InterpolatorType.ViewDirection, surfaceInputs);
            ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresPosition, InterpolatorType.Position, surfaceInputs);

            if (requirements.requiresVertexColor)
            {
                surfaceInputs.AddShaderChunk(string.Format("float4 {0};", ShaderGeneratorNames.VertexColor), false);
            }

            if (requirements.requiresScreenPosition)
            {
                surfaceInputs.AddShaderChunk(string.Format("float4 {0};", ShaderGeneratorNames.ScreenPosition), false);
            }

            foreach (var channel in requirements.requiresMeshUVs.Distinct())
            {
                surfaceInputs.AddShaderChunk(string.Format("half4 {0};", channel.GetUVName()), false);
            }

            surfaceInputs.Deindent();
            surfaceInputs.AddShaderChunk("};", false);

            surfaceVertexShader.AddShaderChunk("GraphVertexInput PopulateVertexData(GraphVertexInput v){", false);
            surfaceVertexShader.Indent();
            surfaceVertexShader.AddShaderChunk("return v;", false);
            surfaceVertexShader.Deindent();
            surfaceVertexShader.AddShaderChunk("}", false);

            var slots = new List <MaterialSlot>();

            foreach (var id in pass.PixelShaderSlots)
            {
                slots.Add(masterNode.FindSlot <MaterialSlot>(id));
            }
            GraphUtil.GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, slots, true);

            var usedSlots = new List <MaterialSlot>();

            foreach (var id in pass.PixelShaderSlots)
            {
                usedSlots.Add(masterNode.FindSlot <MaterialSlot>(id));
            }

            GraphUtil.GenerateSurfaceDescription(
                activeNodeList,
                masterNode,
                masterNode.owner as AbstractMaterialGraph,
                surfaceDescriptionFunction,
                functionRegistry,
                shaderProperties,
                requirements,
                mode,
                "PopulateSurfaceData",
                "SurfaceDescription",
                null,
                usedSlots);

            var graph = new ShaderGenerator();

            graph.AddShaderChunk(shaderProperties.GetPropertiesDeclaration(2), false);
            graph.AddShaderChunk(surfaceInputs.GetShaderString(2), false);
            graph.AddShaderChunk(builder.ToString(), false);
            graph.AddShaderChunk(vertexInputs.GetShaderString(2), false);
            graph.AddShaderChunk(surfaceDescriptionStruct.GetShaderString(2), false);
            graph.AddShaderChunk(surfaceVertexShader.GetShaderString(2), false);
            graph.AddShaderChunk(surfaceDescriptionFunction.GetShaderString(2), false);

            var blendingVisitor = new ShaderGenerator();
            var cullingVisitor  = new ShaderGenerator();
            var zTestVisitor    = new ShaderGenerator();
            var zWriteVisitor   = new ShaderGenerator();

            materialOptions.GetBlend(blendingVisitor);
            materialOptions.GetCull(cullingVisitor);
            materialOptions.GetDepthTest(zTestVisitor);
            materialOptions.GetDepthWrite(zWriteVisitor);

            var interpolators      = new ShaderGenerator();
            var localVertexShader  = new ShaderGenerator();
            var localPixelShader   = new ShaderGenerator();
            var localSurfaceInputs = new ShaderGenerator();
            var surfaceOutputRemap = new ShaderGenerator();

            ShaderGenerator.GenerateStandardTransforms(
                3,
                10,
                interpolators,
                localVertexShader,
                localPixelShader,
                localSurfaceInputs,
                requirements,
                modelRequiements,
                CoordinateSpace.World);

            ShaderGenerator defines = new ShaderGenerator();

            if (masterNode.IsSlotConnected(PBRMasterNode.NormalSlotId))
            {
                defines.AddShaderChunk("#define _NORMALMAP 1", true);
            }

            if (masterNode.model == PBRMasterNode.Model.Specular)
            {
                defines.AddShaderChunk("#define _SPECULAR_SETUP 1", true);
            }

            if (masterNode.IsSlotConnected(PBRMasterNode.AlphaThresholdSlotId))
            {
                defines.AddShaderChunk("#define _AlphaClip 1", true);
            }

            var templateLocation = ShaderGenerator.GetTemplatePath(template);

            foreach (var slot in usedSlots)
            {
                surfaceOutputRemap.AddShaderChunk(string.Format("{0} = surf.{0};", slot.shaderOutputName), true);
            }

            if (!File.Exists(templateLocation))
            {
                return(string.Empty);
            }

            var subShaderTemplate = File.ReadAllText(templateLocation);
            var resultPass        = subShaderTemplate.Replace("${Defines}", defines.GetShaderString(3));

            resultPass = resultPass.Replace("${Graph}", graph.GetShaderString(3));
            resultPass = resultPass.Replace("${Interpolators}", interpolators.GetShaderString(3));
            resultPass = resultPass.Replace("${VertexShader}", localVertexShader.GetShaderString(3));
            resultPass = resultPass.Replace("${LocalPixelShader}", localPixelShader.GetShaderString(3));
            resultPass = resultPass.Replace("${SurfaceInputs}", localSurfaceInputs.GetShaderString(3));
            resultPass = resultPass.Replace("${SurfaceOutputRemap}", surfaceOutputRemap.GetShaderString(3));

            resultPass = resultPass.Replace("${Tags}", string.Empty);
            resultPass = resultPass.Replace("${Blending}", blendingVisitor.GetShaderString(2));
            resultPass = resultPass.Replace("${Culling}", cullingVisitor.GetShaderString(2));
            resultPass = resultPass.Replace("${ZTest}", zTestVisitor.GetShaderString(2));
            resultPass = resultPass.Replace("${ZWrite}", zWriteVisitor.GetShaderString(2));
            return(resultPass);
        }
 internal override string GetPropertyBlockString()
 {
     return($"{hideTagString}{referenceName}(\"{displayName}\", Vector) = ({NodeUtils.FloatToShaderValue(value.x)}, {NodeUtils.FloatToShaderValue(value.y)}, {NodeUtils.FloatToShaderValue(value.z)}, {NodeUtils.FloatToShaderValue(value.w)})");
 }
        /// <summary>
        /// Build dao contexts
        /// </summary>
        /// <param name="configurationScope">The scope of the configuration</param>
        private void GetContexts(ConfigurationScope configurationScope)
        {
            DaoManager   daoManager = null;
            XmlAttribute attribute  = null;

            // Init
            DaoManager.Reset();

            // Build one daoManager for each context
            foreach (XmlNode contextNode in configurationScope.DaoConfigDocument.SelectNodes(ApplyNamespacePrefix(XML_DAO_CONTEXT), configurationScope.XmlNamespaceManager))
            {
                configurationScope.ErrorContext.Activity = "build daoManager";
                configurationScope.NodeContext           = contextNode;

                #region Configure a new DaoManager

                attribute  = contextNode.Attributes["id"];
                daoManager = DaoManager.NewInstance(attribute.Value);

                configurationScope.ErrorContext.Activity += daoManager.Id;

                // default
                attribute = contextNode.Attributes["default"];
                if (attribute != null)
                {
                    if (attribute.Value == "true")
                    {
                        daoManager.IsDefault = true;
                    }
                    else
                    {
                        daoManager.IsDefault = false;
                    }
                }
                else
                {
                    daoManager.IsDefault = false;
                }
                #endregion

                #region Properties
                ParseGlobalProperties(configurationScope);
                #endregion

                #region provider
                daoManager.DbProvider = ParseProvider(configurationScope);

                configurationScope.ErrorContext.Resource = string.Empty;
                configurationScope.ErrorContext.MoreInfo = string.Empty;
                configurationScope.ErrorContext.ObjectId = string.Empty;
                #endregion

                #region DataSource
                daoManager.DataSource            = ParseDataSource(configurationScope);
                daoManager.DataSource.DbProvider = daoManager.DbProvider;
                #endregion

                #region DaoSessionHandler

                XmlNode nodeSessionHandler = contextNode.SelectSingleNode(ApplyNamespacePrefix(XML_DAO_SESSION_HANDLER), configurationScope.XmlNamespaceManager);

                configurationScope.ErrorContext.Activity = "configure DaoSessionHandler";

                // The resources use to initialize the SessionHandler
                IDictionary resources = new Hashtable();
                // By default, add the DataSource
                resources.Add("DataSource", daoManager.DataSource);
                // By default, add the useConfigFileWatcher
                resources.Add("UseConfigFileWatcher", configurationScope.UseConfigFileWatcher);

                IDaoSessionHandler sessionHandler = null;
                Type typeSessionHandler           = null;

                if (nodeSessionHandler != null)
                {
                    configurationScope.ErrorContext.Resource = nodeSessionHandler.InnerXml.ToString();

                    typeSessionHandler = configurationScope.DaoSectionHandlers[nodeSessionHandler.Attributes[ID_ATTRIBUTE].Value] as Type;

                    // Parse property node
                    foreach (XmlNode nodeProperty in nodeSessionHandler.SelectNodes(ApplyNamespacePrefix(XML_PROPERTY), configurationScope.XmlNamespaceManager))
                    {
                        resources.Add(nodeProperty.Attributes["name"].Value,
                                      NodeUtils.ParsePropertyTokens(nodeProperty.Attributes["value"].Value, configurationScope.Properties));
                    }
                }
                else
                {
                    typeSessionHandler = configurationScope.DaoSectionHandlers[DEFAULT_DAOSESSIONHANDLER_NAME] as Type;
                }

                // Configure the sessionHandler
                configurationScope.ErrorContext.ObjectId = typeSessionHandler.FullName;

                try
                {
                    sessionHandler = (IDaoSessionHandler)Activator.CreateInstance(typeSessionHandler, EmptyObjects);
                }
                catch (Exception e)
                {
                    throw new ConfigurationException(
                              string.Format("DaoManager could not configure DaoSessionHandler. DaoSessionHandler of type \"{0}\", failed. Cause: {1}", typeSessionHandler.Name, e.Message), e
                              );
                }

                sessionHandler.Configure(configurationScope.Properties, resources);

                daoManager.DaoSessionHandler = sessionHandler;

                configurationScope.ErrorContext.Resource = string.Empty;
                configurationScope.ErrorContext.MoreInfo = string.Empty;
                configurationScope.ErrorContext.ObjectId = string.Empty;
                #endregion

                #region Build Daos
                ParseDaoFactory(configurationScope, daoManager);
                #endregion

                #region Register DaoManager

                configurationScope.ErrorContext.MoreInfo = "register DaoManager";
                configurationScope.ErrorContext.ObjectId = daoManager.Id;

                DaoManager.RegisterDaoManager(daoManager.Id, daoManager);

                configurationScope.ErrorContext.Resource = string.Empty;
                configurationScope.ErrorContext.MoreInfo = string.Empty;
                configurationScope.ErrorContext.ObjectId = string.Empty;
                #endregion
            }
        }
Example #14
0
 string GetFunctionHeader()
 {
     return("Unity_Multiply" + "_" + concretePrecision.ToShaderString()
            + (this.GetSlots <DynamicVectorMaterialSlot>().Select(s => NodeUtils.GetSlotDimension(s.concreteValueType)).FirstOrDefault() ?? "")
            + (this.GetSlots <DynamicMatrixMaterialSlot>().Select(s => NodeUtils.GetSlotDimension(s.concreteValueType)).FirstOrDefault() ?? ""));
 }
        void KickOffShaderCompilations()
        {
            // Start compilation for nodes that need to recompile
            using (KickOffShaderCompilationsMarker.Auto())
                using (var nodesToCompile = PooledHashSet <AbstractMaterialNode> .Get())
                {
                    // master node compile is first in the priority list, as it takes longer than the other previews
                    if ((m_NodesCompiling.Count + nodesToCompile.Count < m_MaxNodesCompiling) &&
                        m_NodesNeedsRecompile.Contains(m_MasterRenderData.shaderData.node) &&
                        !m_NodesCompiling.Contains(m_MasterRenderData.shaderData.node) &&
                        ((Shader.globalRenderPipeline != null) && (Shader.globalRenderPipeline.Length > 0))) // master node requires an SRP
                    {
                        var renderData = GetPreviewRenderData(m_MasterRenderData.shaderData.node);
                        Assert.IsTrue(renderData != null);
                        nodesToCompile.Add(m_MasterRenderData.shaderData.node);
                    }

                    // add each node to compile list if it needs a preview, is not already compiling, and we have room
                    // (we don't want to double kick compiles, so wait for the first one to get back before kicking another)
                    foreach (var node in m_NodesNeedsRecompile)
                    {
                        if (m_NodesCompiling.Count + nodesToCompile.Count >= m_MaxNodesCompiling)
                        {
                            break;
                        }

                        if (node.hasPreview && node.previewExpanded && !m_NodesCompiling.Contains(node))
                        {
                            var renderData = GetPreviewRenderData(node);
                            if (renderData == null) // non-active output nodes can have NULL render data (no preview)
                            {
                                continue;
                            }

                            nodesToCompile.Add(node);
                        }
                    }

                    // remove the selected nodes from the recompile list
                    m_NodesNeedsRecompile.ExceptWith(nodesToCompile);

                    // Reset error states for the UI, the shader, and all render data for nodes we're recompiling
                    m_Messenger.ClearNodesFromProvider(this, nodesToCompile);

                    // Force async compile on
                    var wasAsyncAllowed = ShaderUtil.allowAsyncCompilation;
                    ShaderUtil.allowAsyncCompilation = true;

                    // kick async compiles for all nodes in m_NodeToCompile
                    foreach (var node in nodesToCompile)
                    {
                        if (node is IMasterNode && node == masterRenderData.shaderData.node && !(node is VfxMasterNode))
                        {
                            UpdateMasterNodeShader();
                            continue;
                        }

                        Assert.IsFalse(!node.hasPreview && !(node is SubGraphOutputNode || node is VfxMasterNode));

                        var renderData = GetPreviewRenderData(node);

                        // Get shader code and compile
                        var generator = new Generator(node.owner, node, GenerationMode.Preview, $"hidden/preview/{node.GetVariableNameForNode()}");
                        BeginCompile(renderData, generator.generatedShader);

                        // Calculate the PreviewMode from upstream nodes
                        // If any upstream node is 3D that trickles downstream
                        // TODO: not sure why this code exists here
                        // it would make more sense in HandleGraphChanges and/or RenderPreview
                        List <AbstractMaterialNode> upstreamNodes = new List <AbstractMaterialNode>();
                        NodeUtils.DepthFirstCollectNodesFromNode(upstreamNodes, node, NodeUtils.IncludeSelf.Include);
                        renderData.previewMode = PreviewMode.Preview2D;
                        foreach (var pNode in upstreamNodes)
                        {
                            if (pNode.previewMode == PreviewMode.Preview3D)
                            {
                                renderData.previewMode = PreviewMode.Preview3D;
                                break;
                            }
                        }
                    }

                    ShaderUtil.allowAsyncCompilation = wasAsyncAllowed;
                }
        }
Example #16
0
        // Update is called once per frame
        void Update()
        {
            try
            {
                Performance.Enter("CameraControl.Update");
                // Check mouse click

                if (Input.GetButtonDown("Fire1"))
                {
                    Map.MapPos mapPos;

                    if (Map.MapControl.SystemMap.GetScreenGroundPosition((int)Input.mousePosition.x, (int)(Screen.height - Input.mousePosition.y), (uint)Screen.width, (uint)Screen.height, out mapPos, Map.ClampFlags.DEFAULT))
                    {
                        List <GameObject> list;

                        if (NodeUtils.FindGameObjects(mapPos.node.GetNativeReference(), out list))
                        {
                            foreach (GameObject o in list)
                            {
                                GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);

                                sphere.transform.parent = o.transform;
                                sphere.transform.transform.localPosition = new Vector3((float)mapPos.position.x, (float)mapPos.position.y, (float)mapPos.position.z);
                                sphere.transform.localScale = new Vector3(10, 10, 10);
                            }
                        }

                        // Just test some update
                        mapPos.position += new Vec3(1, 1, 1);

                        Map.MapControl.SystemMap.UpdatePosition(mapPos, GroundClampType.GROUND);

                        GlobalPosition = mapPos.GlobalPosition(new Vec3(0, 0, 10));
                    }
                }

                if (Input.GetButtonDown("Fire2"))
                {
                    GizmoSDK.Coordinate.LatPos latpos = new GizmoSDK.Coordinate.LatPos
                    {
                        Altitude  = 245.52585220821,
                        Latitude  = 1.00778345058085,
                        Longitude = 0.251106492463706
                    };

                    Map.MapPos mappos;

                    if (Map.MapControl.SystemMap.GetPosition(latpos, out mappos, Map.GroundClampType.GROUND, Map.ClampFlags.WAIT_FOR_DATA))
                    {
                        Debug.Log("Hit Ground ok");
                    }

                    //Performance.DumpPerformanceInfo();
                }

                //transform.position;

                if (Input.GetKey("w"))
                {
                    MoveForward(speed);
                }
                if (Input.GetKey("s"))
                {
                    MoveForward(-speed);
                }

                if (Input.GetKey(KeyCode.Space))
                {
                    MoveUp(speed / 2);
                }
                if (Input.GetKey(KeyCode.C))
                {
                    MoveUp(-speed / 2);
                }

                if (Input.GetKey("d"))
                {
                    MoveRight(speed);
                }
                if (Input.GetKey("a"))
                {
                    MoveRight(-speed);
                }


                //transform.position = pos;

                Quaternion rot = transform.rotation;

                if (Input.GetKey(KeyCode.UpArrow))
                {
                    rot = rot * Tilt(rotspeed);
                }

                if (Input.GetKey(KeyCode.DownArrow))
                {
                    rot = rot * Tilt(-rotspeed);
                }

                if (Input.GetKey(KeyCode.LeftArrow))
                {
                    rot = Pan(-rotspeed) * rot;
                }

                if (Input.GetKey(KeyCode.RightArrow))
                {
                    rot = Pan(rotspeed) * rot;
                }

#if TEST_ROTATION
                rot = Pan(-rotspeed) * rot;
#endif

                transform.rotation = rot;
            }
            finally
            {
                Performance.Leave();
            }
        }
 protected override string ConcreteSlotValueAsVariable(AbstractMaterialNode.OutputPrecision precision)
 {
     return(precision + "2 (" + NodeUtils.FloatToShaderValue(value.x) + "," + NodeUtils.FloatToShaderValue(value.y) + ")");
 }
 /// <summary>Resolves this reference into a single <see cref="BlockExpression"/> containing all the sequential statements.</summary>
 public BlockExpression ResolveStatement(VisualProgram context) => Expression.Block(expressions: NodeUtils.FlattenExpressions(context, this));
Example #19
0
        void UpdateShader(Identifier nodeId)
        {
            var node = m_Graph.GetNodeFromTempId(nodeId) as AbstractMaterialNode;

            if (node == null)
            {
                return;
            }
            var renderData = Get(m_RenderDatas, nodeId);

            if (renderData == null || renderData.shaderData == null)
            {
                return;
            }
            var shaderData = renderData.shaderData;

            if (!(node is IMasterNode) && (!node.hasPreview || NodeUtils.FindEffectiveShaderStage(node, true) == ShaderStage.Vertex))
            {
                shaderData.shaderString = null;
            }
            else
            {
                var masterNode = node as IMasterNode;
                if (masterNode != null)
                {
                    List <PropertyCollector.TextureInfo> configuredTextures;
                    shaderData.shaderString = masterNode.GetShader(GenerationMode.Preview, node.name, out configuredTextures);
                }
                else
                {
                    shaderData.shaderString = m_Graph.GetPreviewShader(node).shader;
                }
            }

            File.WriteAllText(Application.dataPath + "/../GeneratedShader.shader", (shaderData.shaderString ?? "null").Replace("UnityEngine.MaterialGraph", "Generated"));

            if (string.IsNullOrEmpty(shaderData.shaderString))
            {
                if (shaderData.shader != null)
                {
                    ShaderUtil.ClearShaderErrors(shaderData.shader);
                    Object.DestroyImmediate(shaderData.shader, true);
                    shaderData.shader = null;
                }
                return;
            }

            if (shaderData.shader == null)
            {
                shaderData.shader           = ShaderUtil.CreateShaderAsset(shaderData.shaderString);
                shaderData.shader.hideFlags = HideFlags.HideAndDontSave;
            }
            else
            {
                ShaderUtil.ClearShaderErrors(shaderData.shader);
                ShaderUtil.UpdateShaderAsset(shaderData.shader, shaderData.shaderString);
            }

            // Debug output
            var message = "RecreateShader: " + node.GetVariableNameForNode() + Environment.NewLine + shaderData.shaderString;

            if (MaterialGraphAsset.ShaderHasError(shaderData.shader))
            {
                shaderData.hasError = true;
                Debug.LogWarning(message);
                ShaderUtil.ClearShaderErrors(shaderData.shader);
                Object.DestroyImmediate(shaderData.shader, true);
                shaderData.shader = null;
            }
            else
            {
                shaderData.hasError = false;
            }
        }
Example #20
0
 public override string GetPropertyBlockString()
 {
     return($"{hideTagString}{hdrTagString}{referenceName}(\"{displayName}\", Color) = ({NodeUtils.FloatToShaderValue(value.r)}, {NodeUtils.FloatToShaderValue(value.g)}, {NodeUtils.FloatToShaderValue(value.b)}, {NodeUtils.FloatToShaderValue(value.a)})");
 }
        private string GetFunctionName()
        {
            var function = GetFunctionToConvert();

            return(function.Name + "_" + (function.IsStatic ? string.Empty : GuidEncoder.Encode(guid) + "_") + precision + (this.GetSlots <DynamicVectorMaterialSlot>().Select(s => NodeUtils.GetSlotDimension(s.concreteValueType)).FirstOrDefault() ?? ""));
        }
        static string GetShaderPassFromTemplate(string template, SpriteUnlitMasterNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions)
        {
            // ----------------------------------------------------- //
            //                         SETUP                         //
            // ----------------------------------------------------- //

            // -------------------------------------
            // String builders

            var shaderProperties       = new PropertyCollector();
            var shaderPropertyUniforms = new ShaderStringBuilder(1);
            var functionBuilder        = new ShaderStringBuilder(1);
            var functionRegistry       = new FunctionRegistry(functionBuilder);

            var defines = new ShaderStringBuilder(1);
            var graph   = new ShaderStringBuilder(0);

            var vertexDescriptionInputStruct = new ShaderStringBuilder(1);
            var vertexDescriptionStruct      = new ShaderStringBuilder(1);
            var vertexDescriptionFunction    = new ShaderStringBuilder(1);

            var surfaceDescriptionInputStruct = new ShaderStringBuilder(1);
            var surfaceDescriptionStruct      = new ShaderStringBuilder(1);
            var surfaceDescriptionFunction    = new ShaderStringBuilder(1);

            var vertexInputStruct  = new ShaderStringBuilder(1);
            var vertexOutputStruct = new ShaderStringBuilder(2);

            var vertexShader = new ShaderStringBuilder(2);
            var vertexShaderDescriptionInputs = new ShaderStringBuilder(2);
            var vertexShaderOutputs           = new ShaderStringBuilder(2);

            var pixelShader = new ShaderStringBuilder(2);
            var pixelShaderSurfaceInputs = new ShaderStringBuilder(2);
            // var pixelShaderSurfaceRemap = new ShaderStringBuilder(2);

            // -------------------------------------
            // Get Slot and Node lists per stage

            var vertexSlots = pass.VertexShaderSlots.Select(masterNode.FindSlot <MaterialSlot>).ToList();
            var vertexNodes = ListPool <AbstractMaterialNode> .Get();

            NodeUtils.DepthFirstCollectNodesFromNode(vertexNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.VertexShaderSlots);

            var pixelSlots = pass.PixelShaderSlots.Select(masterNode.FindSlot <MaterialSlot>).ToList();
            var pixelNodes = ListPool <AbstractMaterialNode> .Get();

            NodeUtils.DepthFirstCollectNodesFromNode(pixelNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.PixelShaderSlots);

            // -------------------------------------
            // Get Requirements

            var vertexRequirements  = ShaderGraphRequirements.FromNodes(vertexNodes, ShaderStageCapability.Vertex, false);
            var pixelRequirements   = ShaderGraphRequirements.FromNodes(pixelNodes, ShaderStageCapability.Fragment);
            var graphRequirements   = pixelRequirements.Union(vertexRequirements);
            var surfaceRequirements = ShaderGraphRequirements.FromNodes(pixelNodes, ShaderStageCapability.Fragment, false);

            var modelRequiements = ShaderGraphRequirements.none;

            modelRequiements.requiresVertexColor = true;
            modelRequiements.requiresMeshUVs     = new List <UVChannel>()
            {
                UVChannel.UV0
            };


            // ----------------------------------------------------- //
            //                START SHADER GENERATION                //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Calculate material options

            var blendingBuilder = new ShaderStringBuilder(1);
            var cullingBuilder  = new ShaderStringBuilder(1);
            var zTestBuilder    = new ShaderStringBuilder(1);
            var zWriteBuilder   = new ShaderStringBuilder(1);

            materialOptions.GetBlend(blendingBuilder);
            materialOptions.GetCull(cullingBuilder);
            materialOptions.GetDepthTest(zTestBuilder);
            materialOptions.GetDepthWrite(zWriteBuilder);

            // ----------------------------------------------------- //
            //                START VERTEX DESCRIPTION               //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Generate Input structure for Vertex Description function
            // TODO - Vertex Description Input requirements are needed to exclude intermediate translation spaces

            vertexDescriptionInputStruct.AppendLine("struct VertexDescriptionInputs");
            using (vertexDescriptionInputStruct.BlockSemicolonScope())
            {
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresNormal, InterpolatorType.Normal, vertexDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresTangent, InterpolatorType.Tangent, vertexDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresBitangent, InterpolatorType.BiTangent, vertexDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresViewDir, InterpolatorType.ViewDirection, vertexDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresPosition, InterpolatorType.Position, vertexDescriptionInputStruct);

                if (vertexRequirements.requiresVertexColor)
                {
                    vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor);
                }

                if (vertexRequirements.requiresScreenPosition)
                {
                    vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition);
                }

                foreach (var channel in vertexRequirements.requiresMeshUVs.Distinct())
                {
                    vertexDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName());
                }

                if (vertexRequirements.requiresTime)
                {
                    vertexDescriptionInputStruct.AppendLine("float3 {0};", ShaderGeneratorNames.TimeParameters);
                }
            }

            // -------------------------------------
            // Generate Output structure for Vertex Description function

            GraphUtil.GenerateVertexDescriptionStruct(vertexDescriptionStruct, vertexSlots);

            // -------------------------------------
            // Generate Vertex Description function

            GraphUtil.GenerateVertexDescriptionFunction(
                masterNode.owner as GraphData,
                vertexDescriptionFunction,
                functionRegistry,
                shaderProperties,
                mode,
                vertexNodes,
                vertexSlots);

            // ----------------------------------------------------- //
            //               START SURFACE DESCRIPTION               //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Generate Input structure for Surface Description function
            // Surface Description Input requirements are needed to exclude intermediate translation spaces

            surfaceDescriptionInputStruct.AppendLine("struct SurfaceDescriptionInputs");
            using (surfaceDescriptionInputStruct.BlockSemicolonScope())
            {
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresNormal, InterpolatorType.Normal, surfaceDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresTangent, InterpolatorType.Tangent, surfaceDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresBitangent, InterpolatorType.BiTangent, surfaceDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresViewDir, InterpolatorType.ViewDirection, surfaceDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresPosition, InterpolatorType.Position, surfaceDescriptionInputStruct);

                if (surfaceRequirements.requiresVertexColor)
                {
                    surfaceDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor);
                }

                if (surfaceRequirements.requiresScreenPosition)
                {
                    surfaceDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition);
                }

                if (surfaceRequirements.requiresFaceSign)
                {
                    surfaceDescriptionInputStruct.AppendLine("float {0};", ShaderGeneratorNames.FaceSign);
                }

                foreach (var channel in surfaceRequirements.requiresMeshUVs.Distinct())
                {
                    surfaceDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName());
                }

                if (surfaceRequirements.requiresTime)
                {
                    surfaceDescriptionInputStruct.AppendLine("float3 {0};", ShaderGeneratorNames.TimeParameters);
                }
            }

            // -------------------------------------
            // Generate Output structure for Surface Description function

            GraphUtil.GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, pixelSlots);

            // -------------------------------------
            // Generate Surface Description function

            GraphUtil.GenerateSurfaceDescriptionFunction(
                pixelNodes,
                masterNode,
                masterNode.owner as GraphData,
                surfaceDescriptionFunction,
                functionRegistry,
                shaderProperties,
                pixelRequirements,
                mode,
                "PopulateSurfaceData",
                "SurfaceDescription",
                null,
                pixelSlots);

            // ----------------------------------------------------- //
            //           GENERATE VERTEX > PIXEL PIPELINE            //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Property uniforms

            shaderProperties.GetPropertiesDeclaration(shaderPropertyUniforms, mode, masterNode.owner.concretePrecision);

            // -------------------------------------
            // Generate Input structure for Vertex shader

            GraphUtil.GenerateApplicationVertexInputs(vertexRequirements.Union(pixelRequirements.Union(modelRequiements)), vertexInputStruct);

            // -------------------------------------
            // Generate standard transformations
            // This method ensures all required transform data is available in vertex and pixel stages

            ShaderGenerator.GenerateStandardTransforms(
                3,
                10,
                vertexOutputStruct,
                vertexShader,
                vertexShaderDescriptionInputs,
                vertexShaderOutputs,
                pixelShader,
                pixelShaderSurfaceInputs,
                pixelRequirements,
                surfaceRequirements,
                modelRequiements,
                vertexRequirements,
                CoordinateSpace.World);

            // ----------------------------------------------------- //
            //                      FINALIZE                         //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Combine Graph sections

            graph.AppendLines(shaderPropertyUniforms.ToString());

            graph.AppendLine(vertexDescriptionInputStruct.ToString());
            graph.AppendLine(surfaceDescriptionInputStruct.ToString());

            graph.AppendLine(functionBuilder.ToString());

            graph.AppendLine(vertexDescriptionStruct.ToString());
            graph.AppendLine(vertexDescriptionFunction.ToString());

            graph.AppendLine(surfaceDescriptionStruct.ToString());
            graph.AppendLine(surfaceDescriptionFunction.ToString());

            graph.AppendLine(vertexInputStruct.ToString());

            // -------------------------------------
            // Generate final subshader

            var resultPass = template.Replace("${Tags}", string.Empty);

            resultPass = resultPass.Replace("${Blending}", blendingBuilder.ToString());
            resultPass = resultPass.Replace("${Culling}", cullingBuilder.ToString());
            resultPass = resultPass.Replace("${ZTest}", zTestBuilder.ToString());
            resultPass = resultPass.Replace("${ZWrite}", zWriteBuilder.ToString());
            resultPass = resultPass.Replace("${Defines}", defines.ToString());

            resultPass = resultPass.Replace("${Graph}", graph.ToString());
            resultPass = resultPass.Replace("${VertexOutputStruct}", vertexOutputStruct.ToString());

            resultPass = resultPass.Replace("${VertexShader}", vertexShader.ToString());
            resultPass = resultPass.Replace("${VertexShaderDescriptionInputs}", vertexShaderDescriptionInputs.ToString());
            resultPass = resultPass.Replace("${VertexShaderOutputs}", vertexShaderOutputs.ToString());

            resultPass = resultPass.Replace("${PixelShader}", pixelShader.ToString());
            resultPass = resultPass.Replace("${PixelShaderSurfaceInputs}", pixelShaderSurfaceInputs.ToString());

            return(resultPass);
        }
Example #23
0
        public void GenerateNodeCode(ShaderStringBuilder sb, 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(conversionType == ConversionType.Direction ? "TransformWorldToObjectDir({0})" : "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(conversionType == ConversionType.Direction ? "TransformWorldToViewDir({0})" : "TransformWorldToView({0})", inputValue);
                }
                else if (conversion.to == CoordinateSpace.AbsoluteWorld)
                {
                    transformString = string.Format("GetAbsolutePositionWS({0})", inputValue);
                }
            }
            else if (conversion.from == CoordinateSpace.Object)
            {
                if (conversion.to == CoordinateSpace.World)
                {
                    transformString = string.Format(conversionType == ConversionType.Direction ? "TransformObjectToWorldDir({0})" : "TransformObjectToWorld({0})", inputValue);
                }
                else if (conversion.to == CoordinateSpace.Object)
                {
                    transformString = inputValue;
                }
                else if (conversion.to == CoordinateSpace.Tangent)
                {
                    requiresTangentTransform = true;
                    transformString = string.Format(conversionType == ConversionType.Direction ? "TransformWorldToTangent(TransformObjectToWorldDir({0}), {1})" : "TransformWorldToTangent(TransformObjectToWorld({0}), {1})", inputValue, targetTransformString);
                }
                else if (conversion.to == CoordinateSpace.View)
                {
                    transformString = string.Format(conversionType == ConversionType.Direction ? "TransformWorldToViewDir(TransformObjectToWorldDir({0}))" : "TransformWorldToView(TransformObjectToWorld({0}))", inputValue);
                }
                if (conversion.to == CoordinateSpace.AbsoluteWorld)
                {
                    transformString = string.Format(conversionType == ConversionType.Direction ? "TransformObjectToWorldDir({0})" : "GetAbsolutePositionWS(TransformObjectToWorld({0}))", inputValue);
                }
            }
            else if (conversion.from == CoordinateSpace.Tangent)
            {
                if (conversion.to == CoordinateSpace.World)
                {
                    requiresTransposeTangentTransform = true;
                    transformString = string.Format("mul({0}, {1}).xyz", transposeTargetTransformString, inputValue);
                }
                else if (conversion.to == CoordinateSpace.Object)
                {
                    requiresTransposeTangentTransform = true;
                    transformString = string.Format(conversionType == ConversionType.Direction ? "TransformWorldToObjectDir(mul({0}, {1}).xyz)" : "TransformWorldToObject(mul({0}, {1}).xyz)", transposeTargetTransformString, inputValue);
                }
                else if (conversion.to == CoordinateSpace.Tangent)
                {
                    transformString = inputValue;
                }
                else if (conversion.to == CoordinateSpace.View)
                {
                    requiresTransposeTangentTransform = true;
                    transformString = string.Format(conversionType == ConversionType.Direction ? "TransformWorldToViewDir(mul({0}, {1}).xyz)" : "TransformWorldToView(mul({0}, {1}).xyz)", transposeTargetTransformString, inputValue);
                }
                if (conversion.to == CoordinateSpace.AbsoluteWorld)
                {
                    requiresTransposeTangentTransform = true;
                    transformString = string.Format("GetAbsolutePositionWS(mul({0}, {1})).xyz", transposeTargetTransformString, inputValue);
                }
            }
            else if (conversion.from == CoordinateSpace.View)
            {
                if (conversion.to == CoordinateSpace.World)
                {
                    transformString = string.Format("mul(UNITY_MATRIX_I_V, $precision4({0}, 1)).xyz", inputValue);
                }
                else if (conversion.to == CoordinateSpace.Object)
                {
                    transformString = string.Format(conversionType == ConversionType.Direction ? "TransformWorldToObjectDir(mul(UNITY_MATRIX_I_V, $precision4({0}, 1) ).xyz)" : "TransformWorldToObject(mul(UNITY_MATRIX_I_V, $precision4({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, $precision4({0}, 1) ).xyz, {1})", inputValue, targetTransformString);
                }
                else if (conversion.to == CoordinateSpace.View)
                {
                    transformString = inputValue;
                }
                else if (conversion.to == CoordinateSpace.AbsoluteWorld)
                {
                    transformString = string.Format("GetAbsolutePositionWS(mul(UNITY_MATRIX_I_V, $precision4({0}, 1))).xyz", inputValue);
                }
            }
            else if (conversion.from == CoordinateSpace.AbsoluteWorld)
            {
                if (conversion.to == CoordinateSpace.World)
                {
                    transformString = string.Format("GetCameraRelativePositionWS({0})", inputValue);
                }
                else if (conversion.to == CoordinateSpace.Object)
                {
                    transformString = string.Format(conversionType == ConversionType.Direction ? "TransformWorldToObjectDir({0})" : "TransformWorldToObject({0})", inputValue);
                }
                else if (conversion.to == CoordinateSpace.Tangent)
                {
                    requiresTangentTransform = true;
                    tangentTransformSpace = CoordinateSpace.World.ToString();
                    transformString = string.Format("TransformWorldToTangent(GetCameraRelativePositionWS({0}), {1})", inputValue, targetTransformString);
                }
                else if (conversion.to == CoordinateSpace.View)
                {
                    transformString = string.Format(conversionType == ConversionType.Direction ? "TransformWorldToViewDir(GetCameraRelativePositionWS({0}))" : "TransformWorldToView(GetCameraRelativePositionWS({0}))", inputValue);
                }
                else if (conversion.to == CoordinateSpace.AbsoluteWorld)
                {
                    transformString = inputValue;
                }
            }
            if (requiresTransposeTangentTransform)
                sb.AppendLine(string.Format("$precision3x3 {0} = transpose($precision3x3(IN.{1}SpaceTangent, IN.{1}SpaceBiTangent, IN.{1}SpaceNormal));", transposeTargetTransformString, CoordinateSpace.World.ToString()));
            else if (requiresTangentTransform)
                sb.AppendLine(string.Format("$precision3x3 {0} = $precision3x3(IN.{1}SpaceTangent, IN.{1}SpaceBiTangent, IN.{1}SpaceNormal);", targetTransformString, tangentTransformSpace));
            sb.AppendLine("{0} {1} = {2};", FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType.ToShaderString(),
                    GetVariableNameForSlot(OutputSlotId),
                    transformString);
        }
Example #24
0
 public static string ToString(this ConcreteSlotValueType type, AbstractMaterialNode.OutputPrecision precision)
 {
     return(NodeUtils.ConvertConcreteSlotValueTypeToString(precision, type));
 }
        public static string GetPreviewSubShader(AbstractMaterialNode node, ShaderGraphRequirements shaderGraphRequirements)
        {
            // Should never be called without a node
            Debug.Assert(node != null);

            var vertexOutputStruct = new ShaderStringBuilder(2);

            var vertexShader = new ShaderStringBuilder(2);
            var vertexShaderDescriptionInputs = new ShaderStringBuilder(2);
            var vertexShaderOutputs           = new ShaderStringBuilder(1);

            var pixelShader = new ShaderStringBuilder(2);
            var pixelShaderSurfaceInputs = new ShaderStringBuilder(2);
            var pixelShaderSurfaceRemap  = new ShaderStringBuilder(2);

            ShaderGenerator.GenerateStandardTransforms(
                0,
                16,
                vertexOutputStruct,
                vertexShader,
                vertexShaderDescriptionInputs,
                vertexShaderOutputs,
                pixelShader,
                pixelShaderSurfaceInputs,
                shaderGraphRequirements,
                shaderGraphRequirements,
                ShaderGraphRequirements.none,
                ShaderGraphRequirements.none,
                CoordinateSpace.World);

            vertexShader.AppendLines(vertexShaderDescriptionInputs.ToString());
            vertexShader.AppendLines(vertexShaderOutputs.ToString());

            var outputSlot = node.GetOutputSlots <MaterialSlot>().FirstOrDefault();

            // Sub Graph Output uses first input slot
            if (node is SubGraphOutputNode)
            {
                outputSlot = node.GetInputSlots <MaterialSlot>().FirstOrDefault();
            }

            if (outputSlot != null)
            {
                var result = string.Format("surf.{0}", NodeUtils.GetHLSLSafeName(outputSlot.shaderOutputName));
                pixelShaderSurfaceRemap.AppendLine("return all(isfinite({0})) ? {1} : {2};",
                                                   result, AdaptNodeOutputForPreview(node, outputSlot.id, result), nanOutput);
            }
            else
            {
                // No valid slots to display, so just show black.
                // It's up to each node to error or warn as appropriate.
                pixelShaderSurfaceRemap.AppendLine("return 0;");
            }

            // -------------------------------------
            // Extra pixel shader work

            var faceSign = new ShaderStringBuilder();

            if (shaderGraphRequirements.requiresFaceSign)
            {
                faceSign.AppendLine(", half FaceSign : VFACE");
            }

            var res = subShaderTemplate.Replace("${Interpolators}", vertexOutputStruct.ToString());

            res = res.Replace("${VertexShader}", vertexShader.ToString());
            res = res.Replace("${FaceSign}", faceSign.ToString());
            res = res.Replace("${LocalPixelShader}", pixelShader.ToString());
            res = res.Replace("${SurfaceInputs}", pixelShaderSurfaceInputs.ToString());
            res = res.Replace("${SurfaceOutputRemap}", pixelShaderSurfaceRemap.ToString());
            return(res);
        }
Example #26
0
        static string GetShaderPassFromTemplate(string template, UnlitMasterNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions)
        {
            // ----------------------------------------------------- //
            //                         SETUP                         //
            // ----------------------------------------------------- //

            // -------------------------------------
            // String builders

            var shaderProperties = new PropertyCollector();
            var functionBuilder  = new ShaderStringBuilder(1);
            var functionRegistry = new FunctionRegistry(functionBuilder);

            var defines = new ShaderStringBuilder(1);
            var graph   = new ShaderStringBuilder(0);

            var vertexDescriptionInputStruct = new ShaderStringBuilder(1);
            var vertexDescriptionStruct      = new ShaderStringBuilder(1);
            var vertexDescriptionFunction    = new ShaderStringBuilder(1);

            var surfaceDescriptionInputStruct = new ShaderStringBuilder(1);
            var surfaceDescriptionStruct      = new ShaderStringBuilder(1);
            var surfaceDescriptionFunction    = new ShaderStringBuilder(1);

            var vertexInputStruct  = new ShaderStringBuilder(1);
            var vertexOutputStruct = new ShaderStringBuilder(2);

            var vertexShader = new ShaderStringBuilder(2);
            var vertexShaderDescriptionInputs = new ShaderStringBuilder(2);
            var vertexShaderOutputs           = new ShaderStringBuilder(2);

            var pixelShader = new ShaderStringBuilder(2);
            var pixelShaderSurfaceInputs = new ShaderStringBuilder(2);
            var pixelShaderSurfaceRemap  = new ShaderStringBuilder(2);

            // -------------------------------------
            // Get Slot and Node lists per stage

            var vertexSlots = pass.VertexShaderSlots.Select(masterNode.FindSlot <MaterialSlot>).ToList();
            var vertexNodes = ListPool <INode> .Get();

            NodeUtils.DepthFirstCollectNodesFromNode(vertexNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.VertexShaderSlots);

            var pixelSlots = pass.PixelShaderSlots.Select(masterNode.FindSlot <MaterialSlot>).ToList();
            var pixelNodes = ListPool <INode> .Get();

            NodeUtils.DepthFirstCollectNodesFromNode(pixelNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.PixelShaderSlots);

            // -------------------------------------
            // Get Requirements

            var vertexRequirements  = ShaderGraphRequirements.FromNodes(vertexNodes, ShaderStageCapability.Vertex, false);
            var pixelRequirements   = ShaderGraphRequirements.FromNodes(pixelNodes, ShaderStageCapability.Fragment);
            var graphRequirements   = pixelRequirements.Union(vertexRequirements);
            var surfaceRequirements = ShaderGraphRequirements.FromNodes(pixelNodes, ShaderStageCapability.Fragment, false);

            var modelRequiements = ShaderGraphRequirements.none;

            modelRequiements.requiresNormal    |= m_PixelCoordinateSpace;
            modelRequiements.requiresTangent   |= m_PixelCoordinateSpace;
            modelRequiements.requiresBitangent |= m_PixelCoordinateSpace;
            modelRequiements.requiresPosition  |= m_PixelCoordinateSpace;
            modelRequiements.requiresViewDir   |= m_PixelCoordinateSpace;
            modelRequiements.requiresMeshUVs.Add(UVChannel.UV1);

            // ----------------------------------------------------- //
            //                START SHADER GENERATION                //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Calculate material options

            var blendingBuilder = new ShaderStringBuilder(1);
            var cullingBuilder  = new ShaderStringBuilder(1);
            var zTestBuilder    = new ShaderStringBuilder(1);
            var zWriteBuilder   = new ShaderStringBuilder(1);

            materialOptions.GetBlend(blendingBuilder);
            materialOptions.GetCull(cullingBuilder);
            materialOptions.GetDepthTest(zTestBuilder);
            materialOptions.GetDepthWrite(zWriteBuilder);

            // -------------------------------------
            // Generate defines

            if (masterNode.IsSlotConnected(UnlitMasterNode.AlphaThresholdSlotId))
            {
                defines.AppendLine("#define _AlphaClip 1");
            }

            if (masterNode.surfaceType == SurfaceType.Transparent && masterNode.alphaMode == AlphaMode.Premultiply)
            {
                defines.AppendLine("#define _ALPHAPREMULTIPLY_ON 1");
            }

            if (graphRequirements.requiresDepthTexture)
            {
                defines.AppendLine("#define REQUIRE_DEPTH_TEXTURE");
            }

            if (graphRequirements.requiresCameraOpaqueTexture)
            {
                defines.AppendLine("#define REQUIRE_OPAQUE_TEXTURE");
            }

            // ----------------------------------------------------- //
            //                START VERTEX DESCRIPTION               //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Generate Input structure for Vertex Description function
            // TODO - Vertex Description Input requirements are needed to exclude intermediate translation spaces

            vertexDescriptionInputStruct.AppendLine("struct VertexDescriptionInputs");
            using (vertexDescriptionInputStruct.BlockSemicolonScope())
            {
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresNormal, InterpolatorType.Normal, vertexDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresTangent, InterpolatorType.Tangent, vertexDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresBitangent, InterpolatorType.BiTangent, vertexDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresViewDir, InterpolatorType.ViewDirection, vertexDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresPosition, InterpolatorType.Position, vertexDescriptionInputStruct);

                if (vertexRequirements.requiresVertexColor)
                {
                    vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor);
                }

                if (vertexRequirements.requiresScreenPosition)
                {
                    vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition);
                }

                foreach (var channel in vertexRequirements.requiresMeshUVs.Distinct())
                {
                    vertexDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName());
                }
            }

            // -------------------------------------
            // Generate Output structure for Vertex Description function

            GraphUtil.GenerateVertexDescriptionStruct(vertexDescriptionStruct, vertexSlots);

            // -------------------------------------
            // Generate Vertex Description function

            GraphUtil.GenerateVertexDescriptionFunction(
                masterNode.owner as AbstractMaterialGraph,
                vertexDescriptionFunction,
                functionRegistry,
                shaderProperties,
                mode,
                vertexNodes,
                vertexSlots);

            // ----------------------------------------------------- //
            //               START SURFACE DESCRIPTION               //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Generate Input structure for Surface Description function
            // Surface Description Input requirements are needed to exclude intermediate translation spaces

            surfaceDescriptionInputStruct.AppendLine("struct SurfaceDescriptionInputs");
            using (surfaceDescriptionInputStruct.BlockSemicolonScope())
            {
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresNormal, InterpolatorType.Normal, surfaceDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresTangent, InterpolatorType.Tangent, surfaceDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresBitangent, InterpolatorType.BiTangent, surfaceDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresViewDir, InterpolatorType.ViewDirection, surfaceDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresPosition, InterpolatorType.Position, surfaceDescriptionInputStruct);

                if (surfaceRequirements.requiresVertexColor)
                {
                    surfaceDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor);
                }

                if (surfaceRequirements.requiresScreenPosition)
                {
                    surfaceDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition);
                }

                if (surfaceRequirements.requiresFaceSign)
                {
                    surfaceDescriptionInputStruct.AppendLine("float {0};", ShaderGeneratorNames.FaceSign);
                }

                foreach (var channel in surfaceRequirements.requiresMeshUVs.Distinct())
                {
                    surfaceDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName());
                }
            }

            // -------------------------------------
            // Generate Output structure for Surface Description function

            GraphUtil.GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, pixelSlots, true);

            // -------------------------------------
            // Generate Surface Description function

            GraphUtil.GenerateSurfaceDescriptionFunction(
                pixelNodes,
                masterNode,
                masterNode.owner as AbstractMaterialGraph,
                surfaceDescriptionFunction,
                functionRegistry,
                shaderProperties,
                pixelRequirements,
                mode,
                "PopulateSurfaceData",
                "SurfaceDescription",
                null,
                pixelSlots);

            // ----------------------------------------------------- //
            //           GENERATE VERTEX > PIXEL PIPELINE            //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Generate Input structure for Vertex shader

            GraphUtil.GenerateApplicationVertexInputs(vertexRequirements.Union(pixelRequirements.Union(modelRequiements)), vertexInputStruct);

            // -------------------------------------
            // Generate standard transformations
            // This method ensures all required transform data is available in vertex and pixel stages

            ShaderGenerator.GenerateStandardTransforms(
                3,
                10,
                vertexOutputStruct,
                vertexShader,
                vertexShaderDescriptionInputs,
                vertexShaderOutputs,
                pixelShader,
                pixelShaderSurfaceInputs,
                pixelRequirements,
                surfaceRequirements,
                modelRequiements,
                vertexRequirements,
                CoordinateSpace.World);

            // -------------------------------------
            // Generate pixel shader surface remap

            foreach (var slot in pixelSlots)
            {
                pixelShaderSurfaceRemap.AppendLine("{0} = surf.{0};", slot.shaderOutputName);
            }

            // -------------------------------------
            // Extra pixel shader work

            var faceSign = new ShaderStringBuilder();

            if (pixelRequirements.requiresFaceSign)
            {
                faceSign.AppendLine(", half FaceSign : VFACE");
            }

            // ----------------------------------------------------- //
            //                      FINALIZE                         //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Combine Graph sections

            graph.AppendLine(shaderProperties.GetPropertiesDeclaration(1));

            graph.AppendLine(vertexDescriptionInputStruct.ToString());
            graph.AppendLine(surfaceDescriptionInputStruct.ToString());

            graph.AppendLine(functionBuilder.ToString());

            graph.AppendLine(vertexDescriptionStruct.ToString());
            graph.AppendLine(vertexDescriptionFunction.ToString());

            graph.AppendLine(surfaceDescriptionStruct.ToString());
            graph.AppendLine(surfaceDescriptionFunction.ToString());

            graph.AppendLine(vertexInputStruct.ToString());

            // -------------------------------------
            // Generate final subshader

            var resultPass = template.Replace("${Tags}", string.Empty);

            resultPass = resultPass.Replace("${Blending}", blendingBuilder.ToString());
            resultPass = resultPass.Replace("${Culling}", cullingBuilder.ToString());
            resultPass = resultPass.Replace("${ZTest}", zTestBuilder.ToString());
            resultPass = resultPass.Replace("${ZWrite}", zWriteBuilder.ToString());
            resultPass = resultPass.Replace("${Defines}", defines.ToString());

            resultPass = resultPass.Replace("${Graph}", graph.ToString());
            resultPass = resultPass.Replace("${VertexOutputStruct}", vertexOutputStruct.ToString());

            resultPass = resultPass.Replace("${VertexShader}", vertexShader.ToString());
            resultPass = resultPass.Replace("${VertexShaderDescriptionInputs}", vertexShaderDescriptionInputs.ToString());
            resultPass = resultPass.Replace("${VertexShaderOutputs}", vertexShaderOutputs.ToString());

            resultPass = resultPass.Replace("${FaceSign}", faceSign.ToString());
            resultPass = resultPass.Replace("${PixelShader}", pixelShader.ToString());
            resultPass = resultPass.Replace("${PixelShaderSurfaceInputs}", pixelShaderSurfaceInputs.ToString());
            resultPass = resultPass.Replace("${PixelShaderSurfaceRemap}", pixelShaderSurfaceRemap.ToString());

            return(resultPass);
        }
Example #27
0
        private void MouseClickHandler(Mouse3DPosition mousePosition)
        {
            if (!Enabled)
            {
                return;
            }
            var matchingSketches = new List <int>();

            if (mousePosition.MouseDown == false)
            {
                var linesEdges = (from line in lines where line != null && line.Shape != null select GeomUtils.ExtractEdge(line.Shape)).ToList();
                _document.Revert();

                // continue only if we have a drag action
                if (Math.Abs(mousePosition.Initial2Dx - startX) < 3 && Math.Abs(mousePosition.Initial2Dy - startY) < 3)
                {
                    return;
                }
                bool leftToRight = startX < mousePosition.Initial2Dx ? true : false;

                if (selectionFace == null)
                {
                    return;
                }
                var sketchNodes = NodeUtils.GetDocumentNodesOfType(_document, FunctionNames.Sketch);

                // find all sketches that are on the same plane as the selection
                matchingSketches.AddRange(from sketchNodeIndex in sketchNodes
                                          let nb = new NodeBuilder(_document.Root[sketchNodeIndex])
                                                   let normal = nb.Dependency[0].TransformedAxis3D
                                                                where normal.IsParallel(viewPlane.Axis, Precision.Confusion)
                                                                select sketchNodeIndex);

                var pointsToShapeMapping = new Dictionary <int, List <int> >();
                var shapeToPointMapping  = new Dictionary <int, List <int> >();
                var functionNames        = new List <string> {
                    FunctionNames.Circle, FunctionNames.Ellipse, FunctionNames.LineTwoPoints, FunctionNames.Arc, FunctionNames.Arc3P
                };
                var selectedShapes = new List <int>();
                foreach (var index in matchingSketches)
                {
                    var sketchPoints = NodeUtils.GetSketchPoints(_document.Root[index], _document);
                    // find all shapes and points on the matching sketches
                    foreach (var node in _document.Root.Children)
                    {
                        var builder = new NodeBuilder(node.Value);
                        if (functionNames.Contains(builder.FunctionName))
                        {
                            var currentSketchNode = AutoGroupLogic.FindSketchNode(node.Value);
                            if (currentSketchNode.Index == index)
                            {
                                if (builder.FunctionName == FunctionNames.Circle)
                                {
                                    if (!pointsToShapeMapping.ContainsKey(builder.Dependency[0].Node.Index))
                                    {
                                        pointsToShapeMapping.Add(builder.Dependency[0].ReferenceBuilder.Node.Index,
                                                                 new List <int> {
                                            builder.Node.Index
                                        });
                                    }
                                    else
                                    {
                                        pointsToShapeMapping[builder.Dependency[0].ReferenceBuilder.Node.Index].Add(builder.Node.Index);
                                    }

                                    shapeToPointMapping.Add(builder.Node.Index, new List <int> {
                                        builder.Dependency[0].ReferenceBuilder.Node.Index
                                    });
                                }
                                else
                                {
                                    var pointsList = new List <int>();
                                    for (int k = 0; k < builder.Dependency.Count; k++)
                                    {
                                        if (!pointsToShapeMapping.ContainsKey(builder.Dependency[k].ReferenceBuilder.Node.Index))
                                        {
                                            pointsToShapeMapping.Add(builder.Dependency[k].ReferenceBuilder.Node.Index, new List <int> {
                                                builder.Node.Index
                                            });
                                        }
                                        else
                                        {
                                            pointsToShapeMapping[builder.Dependency[k].ReferenceBuilder.Node.Index].Add(builder.Node.Index);
                                        }
                                        pointsList.Add(builder.Dependency[k].ReferenceBuilder.Node.Index);
                                    }
                                    shapeToPointMapping.Add(builder.Node.Index, pointsList);
                                }
                            }

                            var edge = GeomUtils.ExtractEdge(builder.Shape);
                            if (edge != null && !edgeMappings.ContainsKey(builder.Node.Index))
                            {
                                edgeMappings.Add(builder.Node.Index, edge);
                            }
                        }
                    }
                    var selectedPoints = new List <int>();

                    // check which points are inside the selection
                    foreach (var point in sketchPoints)
                    {
                        var shapeFace = new NodeBuilder(point).Shape;
                        if (shapeFace == null)
                        {
                            continue;
                        }
                        var common = new BRepAlgoAPICommon(selectionFace, shapeFace);
                        if (common.IsDone)
                        {
                            var commonArea = GeomUtils.GetFaceArea(common.Shape);
                            if (commonArea > 0)
                            {
                                selectedPoints.Add(point.Index);
                            }
                        }
                        _document.Transact();
                    }

                    // Left->Right - only shapes that are fully inside the selection box are selected
                    if (leftToRight)
                    {
                        foreach (var point in selectedPoints)
                        {
                            if (!pointsToShapeMapping.ContainsKey(point))
                            {
                                selectedShapes.Add(point);
                                continue;
                            }
                            var shapes = pointsToShapeMapping[point];
                            foreach (var shape in shapes)
                            {
                                var points = shapeToPointMapping[shape];
                                var allPointsAreSelected = true;
                                foreach (var pointIndex in points)
                                {
                                    if (!selectedPoints.Contains(pointIndex))
                                    {
                                        allPointsAreSelected = false;
                                        break;
                                    }
                                }
                                if (allPointsAreSelected)
                                {
                                    selectedShapes.Add(shape);
                                }
                            }
                        }
                        selectedShapes = selectedShapes.Distinct().ToList();
                    }
                    else
                    {
                        // Right->Left - shapes that are corssed by the selection box are also included in the selection
                        foreach (var point in selectedPoints)
                        {
                            if (pointsToShapeMapping.ContainsKey(point))
                            {
                                selectedShapes.AddRange(pointsToShapeMapping[point]);
                            }
                            else
                            {
                                selectedShapes.Add(point);
                            }
                        }
                        foreach (var edgeMapping in edgeMappings)
                        {
                            if (!selectedShapes.Contains(edgeMapping.Key))
                            {
                                foreach (var line in linesEdges)
                                {
                                    var intersection = GeomUtils.IntersectionPoints(line, edgeMapping.Value);
                                    if (intersection.Count > 0)
                                    {
                                        selectedShapes.Add(edgeMapping.Key);
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
                selectedShapes = selectedShapes.Distinct().ToList();
                _selectionContainer.BuildSelections(selectedShapes);

                Inputs[InputNames.UiElementsItem].Send(NotificationNames.RefreshPropertyTabMultipleSelections, _selectionContainer.Entities);
                _document.Transact();
                return;
            }

            selectedNodesIndexes.Clear();
            startX     = mousePosition.Initial2Dx;
            startY     = mousePosition.Initial2Dy;
            startPoint = mousePosition.Point;

            var correctedMousePosition = CalculateCorrectCoordinate(mousePosition);

            _context.MoveTo(correctedMousePosition.Initial2Dx, correctedMousePosition.Initial2Dy, ViewItems.View);

            if (mousePosition.MouseDown)
            {
                if (mousePosition.ShiftDown)
                {
                    _context.ShiftSelect(true);
                }
                else
                {
                    _context.Select(true);
                }
            }

            // Perform click selection using the corrected coordinate
            _selectionContainer.BuildSelections(correctedMousePosition);
            if (_selectionContainer.Entities.Count == 2)
            {
                Inputs[InputNames.UiElementsItem].Send(NotificationNames.RefreshPropertyTabTwoSelections, _selectionContainer.Entities);
            }
            if (_selectionContainer.Entities.Count == 1)
            {
                Inputs[InputNames.UiElementsItem].Send(NotificationNames.SelectNode, _selectionContainer.Entities[0].Node);
            }
        }
        public static GenerationResults GetShader(this GraphData graph, AbstractMaterialNode node, GenerationMode mode, string name)
        {
            // ----------------------------------------------------- //
            //                         SETUP                         //
            // ----------------------------------------------------- //

            // -------------------------------------
            // String builders

            var finalShader = new ShaderStringBuilder();
            var results     = new GenerationResults();

            var shaderProperties          = new PropertyCollector();
            var shaderKeywords            = new KeywordCollector();
            var shaderPropertyUniforms    = new ShaderStringBuilder();
            var shaderKeywordDeclarations = new ShaderStringBuilder();
            var shaderKeywordPermutations = new ShaderStringBuilder(1);

            var functionBuilder  = new ShaderStringBuilder();
            var functionRegistry = new FunctionRegistry(functionBuilder);

            var vertexDescriptionFunction = new ShaderStringBuilder(0);

            var surfaceDescriptionInputStruct = new ShaderStringBuilder(0);
            var surfaceDescriptionStruct      = new ShaderStringBuilder(0);
            var surfaceDescriptionFunction    = new ShaderStringBuilder(0);

            var vertexInputs = new ShaderStringBuilder(0);

            graph.CollectShaderKeywords(shaderKeywords, mode);

            if (graph.GetKeywordPermutationCount() > ShaderGraphPreferences.variantLimit)
            {
                graph.AddValidationError(node.tempId, ShaderKeyword.kVariantLimitWarning, Rendering.ShaderCompilerMessageSeverity.Error);

                results.configuredTextures = shaderProperties.GetConfiguredTexutres();
                results.shader             = string.Empty;
                return(results);
            }

            // -------------------------------------
            // Get Slot and Node lists

            var activeNodeList = ListPool <AbstractMaterialNode> .Get();

            NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, node);

            var slots = new List <MaterialSlot>();

            if (node is IMasterNode || node is SubGraphOutputNode)
            {
                slots.AddRange(node.GetInputSlots <MaterialSlot>());
            }
            else
            {
                var outputSlots = node.GetOutputSlots <MaterialSlot>().ToList();
                if (outputSlots.Count > 0)
                {
                    slots.Add(outputSlots[0]);
                }
            }

            // -------------------------------------
            // Get Requirements

            var requirements = ShaderGraphRequirements.FromNodes(activeNodeList, ShaderStageCapability.Fragment);

            // ----------------------------------------------------- //
            //                         KEYWORDS                      //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Get keyword permutations

            graph.CollectShaderKeywords(shaderKeywords, mode);

            // Track permutation indicies for all nodes and requirements
            List <int>[] keywordPermutationsPerNode = new List <int> [activeNodeList.Count];

            // -------------------------------------
            // Evaluate all permutations

            for (int i = 0; i < shaderKeywords.permutations.Count; i++)
            {
                // Get active nodes for this permutation
                var localNodes = ListPool <AbstractMaterialNode> .Get();

                NodeUtils.DepthFirstCollectNodesFromNode(localNodes, node, keywordPermutation: shaderKeywords.permutations[i]);

                // Track each pixel node in this permutation
                foreach (AbstractMaterialNode pixelNode in localNodes)
                {
                    int nodeIndex = activeNodeList.IndexOf(pixelNode);

                    if (keywordPermutationsPerNode[nodeIndex] == null)
                    {
                        keywordPermutationsPerNode[nodeIndex] = new List <int>();
                    }
                    keywordPermutationsPerNode[nodeIndex].Add(i);
                }

                // Get active requirements for this permutation
                var localSurfaceRequirements = ShaderGraphRequirements.FromNodes(localNodes, ShaderStageCapability.Fragment, false);
                var localPixelRequirements   = ShaderGraphRequirements.FromNodes(localNodes, ShaderStageCapability.Fragment);
            }


            // ----------------------------------------------------- //
            //                START VERTEX DESCRIPTION               //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Generate Vertex Description function

            vertexDescriptionFunction.AppendLine("GraphVertexInput PopulateVertexData(GraphVertexInput v)");
            using (vertexDescriptionFunction.BlockScope())
            {
                vertexDescriptionFunction.AppendLine("return v;");
            }

            // ----------------------------------------------------- //
            //               START SURFACE DESCRIPTION               //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Generate Input structure for Surface Description function
            // Surface Description Input requirements are needed to exclude intermediate translation spaces

            GenerateSurfaceInputStruct(surfaceDescriptionInputStruct, requirements, "SurfaceDescriptionInputs");

            results.previewMode = PreviewMode.Preview2D;
            foreach (var pNode in activeNodeList)
            {
                if (pNode.previewMode == PreviewMode.Preview3D)
                {
                    results.previewMode = PreviewMode.Preview3D;
                    break;
                }
            }

            // -------------------------------------
            // Generate Output structure for Surface Description function

            GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, slots, useIdsInNames: !(node is IMasterNode));

            // -------------------------------------
            // Generate Surface Description function

            GenerateSurfaceDescriptionFunction(
                activeNodeList,
                keywordPermutationsPerNode,
                node,
                graph,
                surfaceDescriptionFunction,
                functionRegistry,
                shaderProperties,
                shaderKeywords,
                mode,
                outputIdProperty: results.outputIdProperty);

            // ----------------------------------------------------- //
            //           GENERATE VERTEX > PIXEL PIPELINE            //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Keyword declarations

            shaderKeywords.GetKeywordsDeclaration(shaderKeywordDeclarations, mode);

            // -------------------------------------
            // Property uniforms

            shaderProperties.GetPropertiesDeclaration(shaderPropertyUniforms, mode, graph.concretePrecision);

            // -------------------------------------
            // Generate Input structure for Vertex shader

            GenerateApplicationVertexInputs(requirements, vertexInputs);

            // ----------------------------------------------------- //
            //                      FINALIZE                         //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Build final shader

            finalShader.AppendLine(@"Shader ""{0}""", name);
            using (finalShader.BlockScope())
            {
                SubShaderGenerator.GeneratePropertiesBlock(finalShader, shaderProperties, shaderKeywords, mode);
                finalShader.AppendNewLine();

                finalShader.AppendLine(@"HLSLINCLUDE");
                finalShader.AppendLine(@"#include ""Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl""");
                finalShader.AppendLine(@"#include ""Packages/com.unity.render-pipelines.core/ShaderLibrary/Packing.hlsl""");
                finalShader.AppendLine(@"#include ""Packages/com.unity.render-pipelines.core/ShaderLibrary/NormalSurfaceGradient.hlsl""");
                finalShader.AppendLine(@"#include ""Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl""");
                finalShader.AppendLine(@"#include ""Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityInstancing.hlsl""");
                finalShader.AppendLine(@"#include ""Packages/com.unity.render-pipelines.core/ShaderLibrary/EntityLighting.hlsl""");
                finalShader.AppendLine(@"#include ""Packages/com.unity.shadergraph/ShaderGraphLibrary/ShaderVariables.hlsl""");
                finalShader.AppendLine(@"#include ""Packages/com.unity.shadergraph/ShaderGraphLibrary/ShaderVariablesFunctions.hlsl""");
                finalShader.AppendLine(@"#include ""Packages/com.unity.shadergraph/ShaderGraphLibrary/Functions.hlsl""");

                finalShader.AppendLines(shaderKeywordDeclarations.ToString());
                finalShader.AppendLine(@"#define SHADERGRAPH_PREVIEW 1");
                finalShader.AppendNewLine();

                finalShader.AppendLines(shaderKeywordPermutations.ToString());

                finalShader.AppendLines(shaderPropertyUniforms.ToString());
                finalShader.AppendNewLine();

                finalShader.AppendLines(surfaceDescriptionInputStruct.ToString());
                finalShader.AppendNewLine();

                finalShader.Concat(functionBuilder);
                finalShader.AppendNewLine();

                finalShader.AppendLines(surfaceDescriptionStruct.ToString());
                finalShader.AppendNewLine();
                finalShader.AppendLines(surfaceDescriptionFunction.ToString());
                finalShader.AppendNewLine();

                finalShader.AppendLines(vertexInputs.ToString());
                finalShader.AppendNewLine();
                finalShader.AppendLines(vertexDescriptionFunction.ToString());
                finalShader.AppendNewLine();

                finalShader.AppendLine(@"ENDHLSL");

                finalShader.AppendLines(ShaderGenerator.GetPreviewSubShader(node, requirements));
                ListPool <AbstractMaterialNode> .Release(activeNodeList);
            }

            // -------------------------------------
            // Finalize

            results.configuredTextures = shaderProperties.GetConfiguredTexutres();
            ShaderSourceMap sourceMap;

            results.shader    = finalShader.ToString(out sourceMap);
            results.sourceMap = sourceMap;
            return(results);
        }
Example #29
0
        internal static void GenerateSurfaceDescription(
            List <INode> activeNodeList,
            AbstractMaterialNode masterNode,
            AbstractMaterialGraph graph,
            ShaderGenerator surfaceDescriptionFunction,
            FunctionRegistry functionRegistry,
            PropertyCollector shaderProperties,
            ShaderGraphRequirements requirements,
            GenerationMode mode,
            string functionName                  = "PopulateSurfaceData",
            string surfaceDescriptionName        = "SurfaceDescription",
            FloatShaderProperty outputIdProperty = null,
            IEnumerable <MaterialSlot> slots     = null)
        {
            if (graph == null)
            {
                return;
            }

            surfaceDescriptionFunction.AddShaderChunk(String.Format("{0} {1}(SurfaceInputs IN) {{", surfaceDescriptionName, functionName), false);
            surfaceDescriptionFunction.Indent();
            surfaceDescriptionFunction.AddShaderChunk(String.Format("{0} surface = ({0})0;", surfaceDescriptionName), false);

            graph.CollectShaderProperties(shaderProperties, mode);

            foreach (var activeNode in activeNodeList.OfType <AbstractMaterialNode>())
            {
                if (activeNode is IGeneratesFunction)
                {
                    functionRegistry.builder.currentNode = activeNode;
                    (activeNode as IGeneratesFunction).GenerateNodeFunction(functionRegistry, mode);
                }
                if (activeNode is IGeneratesBodyCode)
                {
                    (activeNode as IGeneratesBodyCode).GenerateNodeCode(surfaceDescriptionFunction, mode);
                }
                if (masterNode == null && activeNode.hasPreview)
                {
                    var outputSlot = activeNode.GetOutputSlots <MaterialSlot>().FirstOrDefault();
                    if (outputSlot != null)
                    {
                        surfaceDescriptionFunction.AddShaderChunk(String.Format("if ({0} == {1}) {{ surface.PreviewOutput = {2}; return surface; }}", outputIdProperty.referenceName, activeNode.tempId.index, ShaderGenerator.AdaptNodeOutputForPreview(activeNode, outputSlot.id, activeNode.GetVariableNameForSlot(outputSlot.id))), false);
                    }
                }

                activeNode.CollectShaderProperties(shaderProperties, mode);
            }
            functionRegistry.builder.currentNode = null;

            if (masterNode != null)
            {
                if (masterNode is IMasterNode)
                {
                    var usedSlots = slots ?? masterNode.GetInputSlots <MaterialSlot>();
                    foreach (var input in usedSlots)
                    {
                        var foundEdges = graph.GetEdges(input.slotReference).ToArray();
                        if (foundEdges.Any())
                        {
                            var outputRef = foundEdges[0].outputSlot;
                            var fromNode  = graph.GetNodeFromGuid <AbstractMaterialNode>(outputRef.nodeGuid);
                            surfaceDescriptionFunction.AddShaderChunk(string.Format("surface.{0} = {1};", NodeUtils.GetHLSLSafeName(input.shaderOutputName), fromNode.GetVariableNameForSlot(outputRef.slotId)), true);
                        }
                        else
                        {
                            surfaceDescriptionFunction.AddShaderChunk(string.Format("surface.{0} = {1};", NodeUtils.GetHLSLSafeName(input.shaderOutputName), input.GetDefaultValue(mode)), true);
                        }
                    }
                }
                else if (masterNode.hasPreview)
                {
                    foreach (var slot in masterNode.GetOutputSlots <MaterialSlot>())
                    {
                        surfaceDescriptionFunction.AddShaderChunk(string.Format("surface.{0} = {1};", NodeUtils.GetHLSLSafeName(slot.shaderOutputName), masterNode.GetVariableNameForSlot(slot.id)), true);
                    }
                }
            }

            surfaceDescriptionFunction.AddShaderChunk("return surface;", false);
            surfaceDescriptionFunction.Deindent();
            surfaceDescriptionFunction.AddShaderChunk("}", false);
        }
Example #30
0
        static void GetActiveFieldsAndPermutationsForNodes(AbstractMaterialNode masterNode, ShaderPass pass,
                                                           KeywordCollector keywordCollector, List <AbstractMaterialNode> vertexNodes, List <AbstractMaterialNode> pixelNodes,
                                                           List <int>[] vertexNodePermutations, List <int>[] pixelNodePermutations,
                                                           ActiveFields activeFields, out ShaderGraphRequirementsPerKeyword graphRequirements)
        {
            // Initialize requirements
            ShaderGraphRequirementsPerKeyword pixelRequirements  = new ShaderGraphRequirementsPerKeyword();
            ShaderGraphRequirementsPerKeyword vertexRequirements = new ShaderGraphRequirementsPerKeyword();

            graphRequirements = new ShaderGraphRequirementsPerKeyword();

            // Evaluate all Keyword permutations
            if (keywordCollector.permutations.Count > 0)
            {
                for (int i = 0; i < keywordCollector.permutations.Count; i++)
                {
                    // Get active nodes for this permutation
                    var localVertexNodes = Graphing.ListPool <AbstractMaterialNode> .Get();

                    var localPixelNodes = Graphing.ListPool <AbstractMaterialNode> .Get();

                    NodeUtils.DepthFirstCollectNodesFromNode(localVertexNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.vertexPorts, keywordCollector.permutations[i]);
                    NodeUtils.DepthFirstCollectNodesFromNode(localPixelNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.pixelPorts, keywordCollector.permutations[i]);

                    // Track each vertex node in this permutation
                    foreach (AbstractMaterialNode vertexNode in localVertexNodes)
                    {
                        int nodeIndex = vertexNodes.IndexOf(vertexNode);

                        if (vertexNodePermutations[nodeIndex] == null)
                        {
                            vertexNodePermutations[nodeIndex] = new List <int>();
                        }
                        vertexNodePermutations[nodeIndex].Add(i);
                    }

                    // Track each pixel node in this permutation
                    foreach (AbstractMaterialNode pixelNode in localPixelNodes)
                    {
                        int nodeIndex = pixelNodes.IndexOf(pixelNode);

                        if (pixelNodePermutations[nodeIndex] == null)
                        {
                            pixelNodePermutations[nodeIndex] = new List <int>();
                        }
                        pixelNodePermutations[nodeIndex].Add(i);
                    }

                    // Get requirements for this permutation
                    vertexRequirements[i].SetRequirements(ShaderGraphRequirements.FromNodes(localVertexNodes, ShaderStageCapability.Vertex, false));
                    pixelRequirements[i].SetRequirements(ShaderGraphRequirements.FromNodes(localPixelNodes, ShaderStageCapability.Fragment, false));

                    // Add active fields
                    AddActiveFieldsFromGraphRequirements(activeFields[i], vertexRequirements[i].requirements, "VertexDescriptionInputs");
                    AddActiveFieldsFromGraphRequirements(activeFields[i], pixelRequirements[i].requirements, "SurfaceDescriptionInputs");
                }
            }
            // No Keywords
            else
            {
                // Get requirements
                vertexRequirements.baseInstance.SetRequirements(ShaderGraphRequirements.FromNodes(vertexNodes, ShaderStageCapability.Vertex, false));
                pixelRequirements.baseInstance.SetRequirements(ShaderGraphRequirements.FromNodes(pixelNodes, ShaderStageCapability.Fragment, false));

                // Add active fields
                AddActiveFieldsFromGraphRequirements(activeFields.baseInstance, vertexRequirements.baseInstance.requirements, "VertexDescriptionInputs");
                AddActiveFieldsFromGraphRequirements(activeFields.baseInstance, pixelRequirements.baseInstance.requirements, "SurfaceDescriptionInputs");
            }

            // Build graph requirements
            graphRequirements.UnionWith(pixelRequirements);
            graphRequirements.UnionWith(vertexRequirements);
        }