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); }
/// <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"); } }
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); }
// 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); }
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); }
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)); }
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 } }
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; } }
// 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));
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; } }
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); }
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); }
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); }
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); }
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); }
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); }
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); }