static void ProcessSubGraph(SubGraphAsset asset, GraphData graph, ShaderGraphImporter.AssetImportErrorLog importLog) { var graphIncludes = new IncludeCollection(); var registry = new FunctionRegistry(new ShaderStringBuilder(), graphIncludes, true); 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}_$precision"; asset.functionName = $"SG_{asset.hlslName}_{asset.assetGuid}_$precision"; 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); // flag the used nodes so we can filter out errors from unused nodes foreach (var node in nodes) { node.SetUsedByGenerator(); } // Start with a clean slate for the input/output capabilities and dependencies asset.inputCapabilities.Clear(); asset.outputCapabilities.Clear(); asset.slotDependencies.Clear(); ShaderStageCapability effectiveShaderStage = ShaderStageCapability.All; foreach (var slot in outputSlots) { var stage = NodeUtils.GetEffectiveShaderStageCapability(slot, true); if (effectiveShaderStage == ShaderStageCapability.All && stage != ShaderStageCapability.All) { effectiveShaderStage = stage; } asset.outputCapabilities.Add(new SlotCapability { slotName = slot.RawDisplayName(), capabilities = stage }); // Find all unique property nodes used by this slot and record a dependency for this input/output pair var inputPropertyNames = new HashSet <string>(); var nodeSet = new HashSet <AbstractMaterialNode>(); NodeUtils.CollectNodeSet(nodeSet, slot); foreach (var node in nodeSet) { if (node is PropertyNode propNode && !inputPropertyNames.Contains(propNode.property.displayName)) { inputPropertyNames.Add(propNode.property.displayName); var slotDependency = new SlotDependencyPair(); slotDependency.inputSlotName = propNode.property.displayName; slotDependency.outputSlotName = slot.RawDisplayName(); asset.slotDependencies.Add(slotDependency); } } } CollectInputCapabilities(asset, graph); asset.vtFeedbackVariables = VirtualTexturingFeedbackUtils.GetFeedbackVariables(outputNode as SubGraphOutputNode); asset.requirements = ShaderGraphRequirements.FromNodes(nodes, effectiveShaderStage, false); // output precision is whatever the output node has as a graph precision, falling back to the graph default asset.outputGraphPrecision = outputNode.graphPrecision.GraphFallback(graph.graphDefaultPrecision); // this saves the graph precision, which indicates whether this subgraph is switchable or not asset.subGraphGraphPrecision = graph.graphDefaultPrecision; asset.previewMode = graph.previewMode; asset.includes = graphIncludes; 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) { importLog.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); } } // Need to order the properties so that they are in the same order on a subgraph node in a shadergraph // as they are in the blackboard for the subgraph itself. The (blackboard) categories keep that ordering, // so traverse those and add those items to the ordered properties list. Needs to be used to set up the // function _and_ to write out the final asset data so that the function call parameter order matches as well. var orderedProperties = new List <AbstractShaderProperty>(); var propertiesList = graph.properties.ToList(); foreach (var category in graph.categories) { foreach (var child in category.Children) { var prop = propertiesList.Find(p => p.guid == child.guid); // Not all properties in the category are actually on the graph. // In particular, it seems as if keywords are not properties on sub-graphs. if (prop != null) { orderedProperties.Add(prop); } } } // If we are importing an older file that has not had categories generated for it yet, include those now. orderedProperties.AddRange(graph.properties.Except(orderedProperties)); // provide top level subgraph function // NOTE: actual concrete precision here shouldn't matter, it's irrelevant when building the subgraph asset registry.ProvideFunction(asset.functionName, asset.subGraphGraphPrecision, ConcretePrecision.Single, sb => { GenerationUtils.GenerateSurfaceInputStruct(sb, asset.requirements, asset.inputStructName); sb.AppendNewLine(); // Generate the arguments... first INPUTS var arguments = new List <string>(); foreach (var prop in orderedProperties) { // apply fallback to the graph default precision (but don't convert to concrete) // this means "graph switchable" properties will use the precision token GraphPrecision propGraphPrecision = prop.precision.ToGraphPrecision(graph.graphDefaultPrecision); string precisionString = propGraphPrecision.ToGenericString(); arguments.Add(prop.GetPropertyAsArgumentString(precisionString)); if (prop.isConnectionTestable) { arguments.Add($"bool {prop.GetConnectionStateHLSLVariableName()}"); } } { var dropdowns = graph.dropdowns; foreach (var dropdown in dropdowns) { arguments.Add($"int {dropdown.referenceName}"); } } // now pass surface inputs arguments.Add(string.Format("{0} IN", asset.inputStructName)); // Now generate output arguments foreach (MaterialSlot output in outputSlots) { arguments.Add($"out {output.concreteValueType.ToShaderString(asset.outputGraphPrecision.ToGenericString())} {output.shaderOutputName}_{output.id}"); } // Vt Feedback output arguments (always full float4) 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); if (node.graphPrecision == GraphPrecision.Graph) { // code generated by nodes that use graph precision stays in generic form with embedded tokens // those tokens are replaced when this subgraph function is pulled into a graph that defines the precision } else { sb.ReplaceInCurrentMapping(PrecisionUtil.Token, node.concretePrecision.ToShaderString()); } } } foreach (var slot in outputSlots) { sb.AppendLine($"{slot.shaderOutputName}_{slot.id} = {outputNode.GetSlotValue(slot.id, GenerationMode.ForReals)};"); } foreach (var slot in asset.vtFeedbackVariables) { sb.AppendLine($"{slot}_out = {slot};"); } } }); // save all of the node-declared functions to the subgraph asset foreach (var name in registry.names) { var source = registry.sources[name]; var func = new FunctionPair(name, source.code, source.graphPrecisionFlags); asset.functions.Add(func); } 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(orderedProperties, graph.keywords, graph.dropdowns, collector.properties, outputSlots, graph.unsupportedTargets); outputSlots.Dispose(); }
public bool RequiresMeshUV(UVChannel channel, ShaderStageCapability stageCapability) { return(true); }
public NeededCoordinateSpace RequiresNormal(ShaderStageCapability stageCapability) { return(CoordinateSpace.World.ToNeededCoordinateSpace()); }
protected MaterialSlot(int slotId, string displayName, string shaderOutputName, SlotType slotType, int priority, ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false) { m_Id = slotId; m_DisplayName = displayName; m_SlotType = slotType; m_Priority = priority; m_Hidden = hidden; m_ShaderOutputName = shaderOutputName; this.stageCapability = stageCapability; }
protected SpaceMaterialSlot(int slotId, string displayName, string shaderOutputName, CoordinateSpace space, ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false) : base(slotId, displayName, shaderOutputName, SlotType.Input, Vector3.zero, stageCapability, hidden: hidden) { this.space = space; }
public NeededCoordinateSpace RequiresPosition(ShaderStageCapability stageCapability = ShaderStageCapability.Vertex) { return(NeededCoordinateSpace.World); }
public bool RequiresScreenPosition(ShaderStageCapability stageCapability) { return(true); }
// TODO: Fix this - VFX Graph can now use ShaderGraph as a code generation path. However, currently, the new // generation path still slightly depends on this container (The implementation of it was tightly coupled in VFXShaderGraphParticleOutput, // and we keep it now as there is no migration path for users yet). This will need to be decoupled so that we can eventually // remove this container. static ShaderGraphVfxAsset GenerateVfxShaderGraphAsset(GraphData graph) { var target = graph.activeTargets.FirstOrDefault(x => x.SupportsVFX()); 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; if (target is VFXTarget vfxTarget) { asset.lit = vfxTarget.lit; asset.alphaClipping = vfxTarget.alphaTest; asset.generatesWithShaderGraph = false; } else { asset.lit = true; asset.alphaClipping = false; asset.generatesWithShaderGraph = true; } 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 legacy generation if (!asset.generatesWithShaderGraph) { var tmpCtx = new TargetActiveBlockContext(new List <BlockFieldDescriptor>(), null); // NOTE: For whatever reason, this call fails for custom interpolator ports (ie, active ones are not detected as active). // For the sake of compatibility with custom interpolator with shadergraph generation, skip the removal of inactive blocks. target.GetActiveBlocks(ref tmpCtx); ports.RemoveAll(materialSlot => { return(!tmpCtx.activeBlocks.Any(o => materialSlot.RawDisplayName() == o.displayName)); }); } var bodySb = new ShaderStringBuilder(1); var graphIncludes = new IncludeCollection(); var registry = new FunctionRegistry(new ShaderStringBuilder(), graphIncludes, true); foreach (var properties in graph.properties) { properties.SetupConcretePrecision(graph.graphDefaultConcretePrecision); } 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.GetConfiguredTextures()); 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}"); foreach (var include in graphIncludes) { sharedCodeIndices.Add(codeSnippets.Count); codeSnippets.Add(include.value + 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.isExposed) { continue; } for (var portIndex = 0; portIndex < ports.Count; portIndex++) { var portPropertySet = portPropertySets[portIndex]; if (portPropertySet.Contains(property.objectId)) { portCodeIndices[portIndex].Add(codeSnippets.Count); } } ShaderStringBuilder builder = new ShaderStringBuilder(); property.ForeachHLSLProperty(h => h.AppendTo(builder)); codeSnippets.Add($"// Property: {property.displayName}{nl}{builder.ToCodeBlock()}{nl}{nl}"); } foreach (var prop in shaderProperties.properties) { if (!graph.properties.Contains(prop) && (prop is SamplerStateShaderProperty)) { sharedCodeIndices.Add(codeSnippets.Count); ShaderStringBuilder builder = new ShaderStringBuilder(); prop.ForeachHLSLProperty(h => h.AppendTo(builder)); codeSnippets.Add($"// Property: {prop.displayName}{nl}{builder.ToCodeBlock()}{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.graphDefaultConcretePrecision)} {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]; var propertiesStages = new List <ShaderStageCapability>(); for (var portIndex = 0; portIndex < ports.Count; portIndex++) { portPropertyIndices[portIndex] = new List <int>(); } foreach (var property in graph.properties) { if (!property.isExposed) { continue; } var propertyIndex = inputProperties.Count; var codeIndex = codeSnippets.Count; ShaderStageCapability stageCapability = 0; 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); stageCapability |= ports[portIndex].stageCapability; } } propertiesStages.Add(stageCapability); inputProperties.Add(property); codeSnippets.Add($",{nl}{indent}/* Property: {property.displayName} */ {property.GetPropertyAsArgumentStringForVFX(property.concretePrecision.ToShaderString())}"); } 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.graphDefaultConcretePrecision)};{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.m_PropertiesStages = propertiesStages.ToArray(); asset.concretePrecision = graph.graphDefaultConcretePrecision; 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 bool RequiresVertexColor(ShaderStageCapability stageCapability) { return(true); }
public DiffusionProfileInputMaterialSlot(int slotId, string displayName, string shaderOutputName, ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false) : base(slotId, displayName, shaderOutputName, SlotType.Input, 0.0f, stageCapability, hidden: hidden) { }
public bool RequiresFaceSign(ShaderStageCapability stageCapability = ShaderStageCapability.Fragment) { return(true); }
public static bool RequiresScreenPosition(this MaterialSlot slot, ShaderStageCapability stageCapability = ShaderStageCapability.All) { var mayRequireScreenPosition = slot as IMayRequireScreenPosition; return(mayRequireScreenPosition != null && mayRequireScreenPosition.RequiresScreenPosition(stageCapability)); }
internal static ShaderGraphRequirements FromNodes <T>(List <T> nodes, ShaderStageCapability stageCapability = ShaderStageCapability.All, bool includeIntermediateSpaces = true) where T : AbstractMaterialNode { NeededCoordinateSpace requiresNormal = nodes.OfType <IMayRequireNormal>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresNormal(stageCapability)); NeededCoordinateSpace requiresBitangent = nodes.OfType <IMayRequireBitangent>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresBitangent(stageCapability)); NeededCoordinateSpace requiresTangent = nodes.OfType <IMayRequireTangent>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresTangent(stageCapability)); NeededCoordinateSpace requiresViewDir = nodes.OfType <IMayRequireViewDirection>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresViewDirection(stageCapability)); NeededCoordinateSpace requiresPosition = nodes.OfType <IMayRequirePosition>().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresPosition(stageCapability)); bool requiresScreenPosition = nodes.OfType <IMayRequireScreenPosition>().Any(x => x.RequiresScreenPosition()); bool requiresVertexColor = nodes.OfType <IMayRequireVertexColor>().Any(x => x.RequiresVertexColor()); bool requiresFaceSign = nodes.OfType <IMayRequireFaceSign>().Any(x => x.RequiresFaceSign()); bool requiresDepthTexture = nodes.OfType <IMayRequireDepthTexture>().Any(x => x.RequiresDepthTexture()); bool requiresCameraOpaqueTexture = nodes.OfType <IMayRequireCameraOpaqueTexture>().Any(x => x.RequiresCameraOpaqueTexture()); bool requiresTime = nodes.Any(x => x.RequiresTime()); bool requiresVertexSkinning = nodes.OfType <IMayRequireVertexSkinning>().Any(x => x.RequiresVertexSkinning(stageCapability)); var meshUV = new List <UVChannel>(); for (int uvIndex = 0; uvIndex < ShaderGeneratorNames.UVCount; ++uvIndex) { var channel = (UVChannel)uvIndex; if (nodes.OfType <IMayRequireMeshUV>().Any(x => x.RequiresMeshUV(channel))) { meshUV.Add(channel); } } // if anything needs tangentspace we have make // sure to have our othonormal basis! if (includeIntermediateSpaces) { var compoundSpaces = requiresBitangent | requiresNormal | requiresPosition | requiresTangent | requiresViewDir | requiresPosition | requiresNormal; var needsTangentSpace = (compoundSpaces & NeededCoordinateSpace.Tangent) > 0; if (needsTangentSpace) { requiresBitangent |= NeededCoordinateSpace.World; requiresNormal |= NeededCoordinateSpace.World; requiresTangent |= NeededCoordinateSpace.World; } } var reqs = new ShaderGraphRequirements() { m_RequiresNormal = requiresNormal, m_RequiresBitangent = requiresBitangent, m_RequiresTangent = requiresTangent, m_RequiresViewDir = requiresViewDir, m_RequiresPosition = requiresPosition, m_RequiresScreenPosition = requiresScreenPosition, m_RequiresVertexColor = requiresVertexColor, m_RequiresFaceSign = requiresFaceSign, m_RequiresMeshUVs = meshUV, m_RequiresDepthTexture = requiresDepthTexture, m_RequiresCameraOpaqueTexture = requiresCameraOpaqueTexture, m_RequiresTime = requiresTime, m_RequiresVertexSkinning = requiresVertexSkinning }; return(reqs); }
public NeededTransform[] RequiresTransform(ShaderStageCapability stageCapability = ShaderStageCapability.All) => new[] { NeededTransform.ObjectToWorld };
private static MaterialSlot CreateBoundSlot(Binding attributeBinding, int slotId, string displayName, string shaderOutputName, ShaderStageCapability shaderStageCapability, bool hidden) { switch (attributeBinding) { case Binding.ObjectSpaceNormal: return(new NormalMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Object, shaderStageCapability)); case Binding.ObjectSpaceTangent: return(new TangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Object, shaderStageCapability)); case Binding.ObjectSpaceBitangent: return(new BitangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Object, shaderStageCapability)); case Binding.ObjectSpacePosition: return(new PositionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Object, shaderStageCapability)); case Binding.ViewSpaceNormal: return(new NormalMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.View, shaderStageCapability)); case Binding.ViewSpaceTangent: return(new TangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.View, shaderStageCapability)); case Binding.ViewSpaceBitangent: return(new BitangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.View, shaderStageCapability)); case Binding.ViewSpacePosition: return(new PositionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.View, shaderStageCapability)); case Binding.WorldSpaceNormal: return(new NormalMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.World, shaderStageCapability)); case Binding.WorldSpaceTangent: return(new TangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.World, shaderStageCapability)); case Binding.WorldSpaceBitangent: return(new BitangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.World, shaderStageCapability)); case Binding.WorldSpacePosition: return(new PositionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.World, shaderStageCapability)); case Binding.TangentSpaceNormal: return(new NormalMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Tangent, shaderStageCapability)); case Binding.TangentSpaceTangent: return(new TangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Tangent, shaderStageCapability)); case Binding.TangentSpaceBitangent: return(new BitangentMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Tangent, shaderStageCapability)); case Binding.TangentSpacePosition: return(new PositionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Tangent, shaderStageCapability)); case Binding.MeshUV0: return(new UVMaterialSlot(slotId, displayName, shaderOutputName, UVChannel.UV0, shaderStageCapability)); case Binding.MeshUV1: return(new UVMaterialSlot(slotId, displayName, shaderOutputName, UVChannel.UV1, shaderStageCapability)); case Binding.MeshUV2: return(new UVMaterialSlot(slotId, displayName, shaderOutputName, UVChannel.UV2, shaderStageCapability)); case Binding.MeshUV3: return(new UVMaterialSlot(slotId, displayName, shaderOutputName, UVChannel.UV3, shaderStageCapability)); case Binding.ScreenPosition: return(new ScreenPositionMaterialSlot(slotId, displayName, shaderOutputName, ScreenSpaceType.Default, shaderStageCapability)); case Binding.ObjectSpaceViewDirection: return(new ViewDirectionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Object, shaderStageCapability)); case Binding.ViewSpaceViewDirection: return(new ViewDirectionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.View, shaderStageCapability)); case Binding.WorldSpaceViewDirection: return(new ViewDirectionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.World, shaderStageCapability)); case Binding.TangentSpaceViewDirection: return(new ViewDirectionMaterialSlot(slotId, displayName, shaderOutputName, CoordinateSpace.Tangent, shaderStageCapability)); case Binding.VertexColor: return(new VertexColorMaterialSlot(slotId, displayName, shaderOutputName, shaderStageCapability)); default: throw new ArgumentOutOfRangeException("attributeBinding", attributeBinding, null); } }
public NeededCoordinateSpace RequiresBitangent(ShaderStageCapability stageCapability) { return(NeededCoordinateSpace.World); }
public NeededCoordinateSpace RequiresBitangent(ShaderStageCapability stageCapability) { return(space.ToNeededCoordinateSpace()); }
public bool RequiresPixelPosition(ShaderStageCapability stageCapability = ShaderStageCapability.All) => FindSlot <MaterialSlot>(kUvInputSlotId)?.RequiresPixelPosition(stageCapability) ?? false;
public bool RequiresScreenPosition(ShaderStageCapability stageCapability = ShaderStageCapability.All) { // Feedback dithering requires screen position (and only works in Pixel Shader currently) return(stageCapability.HasFlag(ShaderStageCapability.Fragment) && !noFeedback); }
public TestSlot(int slotId, string displayName, SlotType slotType, int priority, ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false) : base(slotId, displayName, displayName, slotType, priority, stageCapability, hidden) { }
public static MaterialSlot CreateMaterialSlot(SlotValueType type, int slotId, string displayName, string shaderOutputName, SlotType slotType, Vector4 defaultValue, ShaderStageCapability shaderStageCapability = ShaderStageCapability.All, bool hidden = false) { switch (type) { case SlotValueType.SamplerState: return(new SamplerStateMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden)); case SlotValueType.DynamicMatrix: return(new DynamicMatrixMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden)); case SlotValueType.Matrix4: return(new Matrix4MaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden)); case SlotValueType.Matrix3: return(new Matrix3MaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden)); case SlotValueType.Matrix2: return(new Matrix2MaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden)); case SlotValueType.Texture2D: return(slotType == SlotType.Input ? new Texture2DInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStageCapability, hidden) : new Texture2DMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden)); case SlotValueType.Texture2DArray: return(slotType == SlotType.Input ? new Texture2DArrayInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStageCapability, hidden) : new Texture2DArrayMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden)); case SlotValueType.Texture3D: return(slotType == SlotType.Input ? new Texture3DInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStageCapability, hidden) : new Texture3DMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden)); case SlotValueType.Cubemap: return(slotType == SlotType.Input ? new CubemapInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStageCapability, hidden) : new CubemapMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden)); case SlotValueType.Gradient: return(slotType == SlotType.Input ? new GradientInputMaterialSlot(slotId, displayName, shaderOutputName, shaderStageCapability, hidden) : new GradientMaterialSlot(slotId, displayName, shaderOutputName, slotType, shaderStageCapability, hidden)); case SlotValueType.DynamicVector: return(new DynamicVectorMaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStageCapability, hidden)); case SlotValueType.Vector4: return(new Vector4MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStageCapability, hidden: hidden)); case SlotValueType.Vector3: return(new Vector3MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStageCapability, hidden: hidden)); case SlotValueType.Vector2: return(new Vector2MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue, shaderStageCapability, hidden: hidden)); case SlotValueType.Vector1: return(new Vector1MaterialSlot(slotId, displayName, shaderOutputName, slotType, defaultValue.x, shaderStageCapability, hidden: hidden)); case SlotValueType.Dynamic: return(new DynamicValueMaterialSlot(slotId, displayName, shaderOutputName, slotType, new Matrix4x4(defaultValue, Vector4.zero, Vector4.zero, Vector4.zero), shaderStageCapability, hidden)); case SlotValueType.Boolean: return(new BooleanMaterialSlot(slotId, displayName, shaderOutputName, slotType, false, shaderStageCapability, hidden)); } throw new ArgumentOutOfRangeException("type", type, null); }
public bool RequiresVertexSkinning(ShaderStageCapability stageCapability = ShaderStageCapability.All) { return(true); }
public UVMaterialSlot(int slotId, string displayName, string shaderOutputName, UVChannel channel, ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false) : base(slotId, displayName, shaderOutputName, SlotType.Input, Vector2.zero, stageCapability, hidden: hidden) { this.channel = channel; }
public bool RequiresCameraOpaqueTexture(ShaderStageCapability stageCapability) { return(true); }
public PositionMaterialSlot(int slotId, string displayName, string shaderOutputName, CoordinateSpace space, ShaderStageCapability stageCapability = ShaderStageCapability.All, bool hidden = false) : base(slotId, displayName, shaderOutputName, space, stageCapability, hidden) { }
public SlotAttribute(int mSlotId, Binding mImplicitBinding, bool mHidden, ShaderStageCapability mStageCapability = ShaderStageCapability.All) { slotId = mSlotId; binding = mImplicitBinding; hidden = mHidden; defaultValue = null; stageCapability = mStageCapability; }
public NeededCoordinateSpace RequiresPosition(ShaderStageCapability stageCapability) { return(CoordinateSpace.AbsoluteWorld.ToNeededCoordinateSpace() | CoordinateSpace.World.ToNeededCoordinateSpace()); }
public SlotAttribute(int mSlotId, Binding mImplicitBinding, float defaultX, float defaultY, float defaultZ, float defaultW, ShaderStageCapability mStageCapability = ShaderStageCapability.All) { slotId = mSlotId; binding = mImplicitBinding; defaultValue = new Vector4(defaultX, defaultY, defaultZ, defaultW); stageCapability = mStageCapability; }
public NeededCoordinateSpace RequiresViewDirection(ShaderStageCapability stageCapability = ShaderStageCapability.All) { return(NeededCoordinateSpace.Tangent); }
public bool RequiresVertexColor(ShaderStageCapability stageCapability) { return(!isConnected); }