using System.Collections.Generic; using System.Linq; using UnityEditor.Graphing; namespace UnityEditor.ShaderGraph { public struct ShaderGraphRequirements { public NeededCoordinateSpace requiresNormal; public NeededCoordinateSpace requiresBitangent; public NeededCoordinateSpace requiresTangent; public NeededCoordinateSpace requiresViewDir; public NeededCoordinateSpace requiresPosition; public bool requiresScreenPosition; public bool requiresVertexColor; public bool requiresFaceSign; public List requiresMeshUVs; public static ShaderGraphRequirements none { get { return new ShaderGraphRequirements { requiresMeshUVs = new List() }; } } public bool NeedsTangentSpace() { var compoundSpaces = requiresBitangent | requiresNormal | requiresPosition | requiresTangent | requiresViewDir | requiresPosition | requiresNormal; return (compoundSpaces & NeededCoordinateSpace.Tangent) > 0; } public ShaderGraphRequirements Union(ShaderGraphRequirements other) { var newReqs = new ShaderGraphRequirements(); newReqs.requiresNormal = other.requiresNormal | requiresNormal; newReqs.requiresTangent = other.requiresTangent | requiresTangent; newReqs.requiresBitangent = other.requiresBitangent | requiresBitangent; newReqs.requiresViewDir = other.requiresViewDir | requiresViewDir; newReqs.requiresPosition = other.requiresPosition | requiresPosition; newReqs.requiresScreenPosition = other.requiresScreenPosition | requiresScreenPosition; newReqs.requiresVertexColor = other.requiresVertexColor | requiresVertexColor; newReqs.requiresFaceSign = other.requiresFaceSign | requiresFaceSign; newReqs.requiresMeshUVs = new List(); if (requiresMeshUVs != null) newReqs.requiresMeshUVs.AddRange(requiresMeshUVs); if (other.requiresMeshUVs != null) newReqs.requiresMeshUVs.AddRange(other.requiresMeshUVs); return newReqs; } public static ShaderGraphRequirements FromNodes(List nodes, ShaderStageCapability stageCapability = ShaderStageCapability.All, bool includeIntermediateSpaces = true) where T : class, INode { NeededCoordinateSpace requiresNormal = nodes.OfType().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresNormal(stageCapability)); NeededCoordinateSpace requiresBitangent = nodes.OfType().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresBitangent(stageCapability)); NeededCoordinateSpace requiresTangent = nodes.OfType().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresTangent(stageCapability)); NeededCoordinateSpace requiresViewDir = nodes.OfType().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresViewDirection(stageCapability)); NeededCoordinateSpace requiresPosition = nodes.OfType().Aggregate(NeededCoordinateSpace.None, (mask, node) => mask | node.RequiresPosition(stageCapability)); bool requiresScreenPosition = nodes.OfType().Any(x => x.RequiresScreenPosition()); bool requiresVertexColor = nodes.OfType().Any(x => x.RequiresVertexColor()); bool requiresFaceSign = nodes.OfType().Any(x => x.RequiresFaceSign()); var meshUV = new List(); for (int uvIndex = 0; uvIndex < ShaderGeneratorNames.UVCount; ++uvIndex) { var channel = (UVChannel)uvIndex; if (nodes.OfType().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() { requiresNormal = requiresNormal, requiresBitangent = requiresBitangent, requiresTangent = requiresTangent, requiresViewDir = requiresViewDir, requiresPosition = requiresPosition, requiresScreenPosition = requiresScreenPosition, requiresVertexColor = requiresVertexColor, requiresFaceSign = requiresFaceSign, requiresMeshUVs = meshUV }; return reqs; } } }