public string GetShader(GenerationMode mode, string outputName, out List<PropertyCollector.TextureInfo> configuredTextures, List<string> sourceAssetDependencyPaths = null)
        {
            var activeNodeList = ListPool<AbstractMaterialNode>.Get();
            NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, this);

            var shaderProperties = new PropertyCollector();

            var abstractMaterialGraph = owner as GraphData;
            if (abstractMaterialGraph != null)
                abstractMaterialGraph.CollectShaderProperties(shaderProperties, mode);

            foreach (var activeNode in activeNodeList.OfType<AbstractMaterialNode>())
                activeNode.CollectShaderProperties(shaderProperties, mode);

            var finalShader = new ShaderStringBuilder();
            finalShader.AppendLine(@"Shader ""{0}""", outputName);
            using (finalShader.BlockScope())
            {
                finalShader.AppendLine("Properties");
                using (finalShader.BlockScope())
                {
                    finalShader.AppendLine(shaderProperties.GetPropertiesBlock(0));
                }

                foreach (var subShader in m_SubShaders)
                {
                    if (mode != GenerationMode.Preview || subShader.IsPipelineCompatible(GraphicsSettings.renderPipelineAsset))
                        finalShader.AppendLines(subShader.GetSubshader(this, mode, sourceAssetDependencyPaths));
                }

                finalShader.AppendLine(@"FallBack ""Hidden/InternalErrorShader""");
            }
            configuredTextures = shaderProperties.GetConfiguredTexutres();
            return finalShader.ToString();
        }
Beispiel #2
0
        void BuildShader()
        {
            var activeNodeList = Graphing.ListPool <AbstractMaterialNode> .Get();

            NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, m_OutputNode);

            var shaderProperties = new PropertyCollector();
            var shaderKeywords   = new KeywordCollector();

            m_GraphData.CollectShaderProperties(shaderProperties, m_Mode);
            m_GraphData.CollectShaderKeywords(shaderKeywords, m_Mode);

            if (m_GraphData.GetKeywordPermutationCount() > ShaderGraphPreferences.variantLimit)
            {
                m_GraphData.AddValidationError(m_OutputNode.guid, ShaderKeyword.kVariantLimitWarning, Rendering.ShaderCompilerMessageSeverity.Error);

                m_ConfiguredTextures = shaderProperties.GetConfiguredTexutres();
                m_Builder.AppendLines(ShaderGraphImporter.k_ErrorShader);
            }

            GetTargetImplementations();

            foreach (var activeNode in activeNodeList.OfType <AbstractMaterialNode>())
            {
                activeNode.CollectShaderProperties(shaderProperties, m_Mode);
            }

            m_Builder.AppendLine(@"Shader ""{0}""", m_Name);
            using (m_Builder.BlockScope())
            {
                GenerationUtils.GeneratePropertiesBlock(m_Builder, shaderProperties, shaderKeywords, m_Mode);

                for (int i = 0; i < m_TargetImplementations.Length; i++)
                {
                    TargetSetupContext context = new TargetSetupContext();
                    context.SetMasterNode(m_OutputNode as IMasterNode);

                    // Instead of setup target, we can also just do get context
                    m_TargetImplementations[i].SetupTarget(ref context);
                    GetAssetDependencyPaths(context);
                    GenerateSubShader(i, context.descriptor);
                }

                // Either grab the pipeline default for the active node or the user override
                if (m_OutputNode is ICanChangeShaderGUI canChangeShaderGui)
                {
                    string customEditor = GenerationUtils.FinalCustomEditorString(canChangeShaderGui);

                    if (customEditor != null)
                    {
                        m_Builder.AppendLine("CustomEditor \"" + customEditor + "\"");
                    }
                }

                m_Builder.AppendLine(@"FallBack ""Hidden/Shader Graph/FallbackError""");
            }

            m_ConfiguredTextures = shaderProperties.GetConfiguredTexutres();
        }
        public string GetSubshader(IMasterNode inMasterNode, GenerationMode mode)
        {
            var templatePath = GetTemplatePath("HDUnlitPassForward.template");
            if (!File.Exists(templatePath))
                return string.Empty;

            string passTemplate = File.ReadAllText(templatePath);

            var masterNode = inMasterNode as UnlitMasterNode;
            var subShader = new ShaderStringBuilder();
            subShader.AppendLine("SubShader");
            using(subShader.BlockScope())
            {
                subShader.AppendLine("Tags{ \"RenderPipeline\" = \"HDRenderPipeline\"}");
                subShader.AppendLine("Tags{ \"RenderType\" = \"Opaque\" }");

                subShader.AppendLines(
                    GetShaderPassFromTemplate(
                        passTemplate,
                        masterNode,
                        m_UnlitPassForwardDepthOnly,
                        mode));

                subShader.AppendLines(
                    GetShaderPassFromTemplate(
                        passTemplate,
                        masterNode,
                        m_UnlitPassForwardOnly,
                        mode));
            }
            
            return subShader.ToString();
        }
Beispiel #4
0
        public static void WorldToTangent(SpaceTransform xform, string inputValue, string outputVariable, ShaderStringBuilder sb)
        {
            if (xform.version <= 1)
            {
                // prior to version 2, all transform were normalized, and all transforms were Normal transforms
                xform.normalize = true;
                xform.type      = ConversionType.Normal;
            }

            using (sb.BlockScope())
            {
                string tangentTransform = GenerateTangentTransform(sb, xform.from);

                switch (xform.type)
                {
                case ConversionType.Position:
                    sb.AddLine(outputVariable, " = TransformWorldToTangentDir(", inputValue, " - IN.WorldSpacePosition, ", tangentTransform, ", false);");
                    break;

                case ConversionType.Direction:
                    sb.AddLine(outputVariable, " = TransformWorldToTangentDir(", inputValue, ", ", tangentTransform, ", ", xform.NormalizeString(), ");");
                    break;

                case ConversionType.Normal:
                    sb.AddLine(outputVariable, " = TransformWorldToTangent(", inputValue, ", ", tangentTransform, ", ", xform.NormalizeString(), ");");
                    break;
                }
            }
        }
Beispiel #5
0
        public static void TangentToWorld(SpaceTransform xform, string inputValue, string outputVariable, ShaderStringBuilder sb)
        {
            // prior to version 2 all transforms were Normal, and directional transforms were normalized
            if (xform.version <= 1)
            {
                if (xform.type != ConversionType.Position)
                {
                    xform.normalize = true;
                }
                xform.type = ConversionType.Normal;
            }

            using (sb.BlockScope())
            {
                string tangentTransform = GenerateTangentTransform(sb, CoordinateSpace.World);
                switch (xform.type)
                {
                case ConversionType.Position:
                    sb.AddLine(outputVariable, " = TransformTangentToWorldDir(", inputValue, ", ", tangentTransform, ", false).xyz + IN.WorldSpacePosition;");
                    break;

                case ConversionType.Direction:
                    sb.AddLine(outputVariable, " = TransformTangentToWorldDir(", inputValue, ", ", tangentTransform, ", ", xform.NormalizeString(), ").xyz;");
                    break;

                case ConversionType.Normal:
                    sb.AddLine(outputVariable, " = TransformTangentToWorld(", inputValue, ", ", tangentTransform, ", ", xform.NormalizeString(), ");");
                    break;
                }
            }
        }
Beispiel #6
0
        internal override string GetPropertyDeclarationString(string delimiter = ";")
        {
            ShaderStringBuilder s = new ShaderStringBuilder();

            s.AppendLine("Gradient {0}_Definition()", referenceName);
            using (s.BlockScope())
            {
                string[] colors = new string[8];
                for (int i = 0; i < colors.Length; i++)
                {
                    colors[i] = string.Format("g.colors[{0}] = {1}4(0, 0, 0, 0);", i, concretePrecision.ToShaderString());
                }
                for (int i = 0; i < value.colorKeys.Length; i++)
                {
                    colors[i] = string.Format("g.colors[{0}] = {1}4({2}, {3}, {4}, {5});"
                                              , i
                                              , concretePrecision.ToShaderString()
                                              , NodeUtils.FloatToShaderValue(value.colorKeys[i].color.r)
                                              , NodeUtils.FloatToShaderValue(value.colorKeys[i].color.g)
                                              , NodeUtils.FloatToShaderValue(value.colorKeys[i].color.b)
                                              , NodeUtils.FloatToShaderValue(value.colorKeys[i].time));
                }

                string[] alphas = new string[8];
                for (int i = 0; i < alphas.Length; i++)
                {
                    alphas[i] = string.Format("g.alphas[{0}] = {1}2(0, 0);", i, concretePrecision.ToShaderString());
                }
                for (int i = 0; i < value.alphaKeys.Length; i++)
                {
                    alphas[i] = string.Format("g.alphas[{0}] = {1}2({2}, {3});"
                                              , i
                                              , concretePrecision.ToShaderString()
                                              , NodeUtils.FloatToShaderValue(value.alphaKeys[i].alpha)
                                              , NodeUtils.FloatToShaderValue(value.alphaKeys[i].time));
                }

                s.AppendLine("Gradient g;");
                s.AppendLine("g.type = {0};",
                             (int)value.mode);
                s.AppendLine("g.colorsLength = {0};",
                             value.colorKeys.Length);
                s.AppendLine("g.alphasLength = {0};",
                             value.alphaKeys.Length);

                for (int i = 0; i < colors.Length; i++)
                {
                    s.AppendLine(colors[i]);
                }

                for (int i = 0; i < alphas.Length; i++)
                {
                    s.AppendLine(alphas[i]);
                }
                s.AppendLine("return g;", true);
            }
            s.AppendIndentation();
            s.Append("#define {0} {0}_Definition()", referenceName);
            return(s.ToString());
        }
        public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
        {
            var sb = new ShaderStringBuilder();

            sb.AppendLine("void {0}({1} Texture, {2} Sampler, {3} UV, {4} Offset, {5} Strength, out {6} Out)", GetFunctionName(),
                          FindInputSlot <MaterialSlot>(TextureInputId).concreteValueType.ToString(precision),
                          FindInputSlot <MaterialSlot>(SamplerInputId).concreteValueType.ToString(precision),
                          FindInputSlot <MaterialSlot>(UVInputId).concreteValueType.ToString(precision),
                          FindInputSlot <MaterialSlot>(OffsetInputId).concreteValueType.ToString(precision),
                          FindInputSlot <MaterialSlot>(StrengthInputId).concreteValueType.ToString(precision),
                          FindOutputSlot <MaterialSlot>(OutputSlotId).concreteValueType.ToString(precision));
            using (sb.BlockScope())
            {
                sb.AppendLine("Offset = pow(Offset, 3) * 0.1;");
                sb.AppendLine("{0}2 offsetU = float2(UV.x + Offset, UV.y);", precision);
                sb.AppendLine("{0}2 offsetV = float2(UV.x, UV.y + Offset);", precision);

                sb.AppendLine("{0} normalSample = Texture.Sample(Sampler, UV).x;", precision);
                sb.AppendLine("{0} uSample = Texture.Sample(Sampler, offsetU).x;", precision);
                sb.AppendLine("{0} vSample = Texture.Sample(Sampler, offsetV).x;", precision);

                sb.AppendLine("{0}3 va = float3(1, 0, (uSample - normalSample) * Strength);", precision);
                sb.AppendLine("{0}3 vb = float3(0, 1, (vSample - normalSample) * Strength);", precision);
                sb.AppendLine("Out = normalize(cross(va, vb));");
            }

            visitor.AddShaderChunk(sb.ToString(), true);
        }
 public void GetTags(ShaderStringBuilder builder)
 {
     builder.AppendLine("Tags");
     using (builder.BlockScope())
     {
         builder.AppendLine("\"RenderType\"=\"{0}\"", renderType);
         builder.AppendLine("\"Queue\"=\"{0}\"", renderQueue);
     }
 }
Beispiel #9
0
        public override string GetPropertyDeclarationString(string delimiter = ";")
        {
            ShaderStringBuilder s = new ShaderStringBuilder();

            s.AppendLine("Gradient {0}_Definition()", referenceName);
            using (s.BlockScope())
            {
                string[] colors = new string[8];
                for (int i = 0; i < colors.Length; i++)
                {
                    colors[i] = string.Format("g.colors[{0}] = float4(0, 0, 0, 0);", i);
                }
                for (int i = 0; i < value.colorKeys.Length; i++)
                {
                    colors[i] = string.Format("g.colors[{0}] = float4({1}, {2}, {3}, {4});"
                                              , i
                                              , value.colorKeys[i].color.r
                                              , value.colorKeys[i].color.g
                                              , value.colorKeys[i].color.b
                                              , value.colorKeys[i].time);
                }

                string[] alphas = new string[8];
                for (int i = 0; i < alphas.Length; i++)
                {
                    alphas[i] = string.Format("g.alphas[{0}] = float2(0, 0);", i);
                }
                for (int i = 0; i < value.alphaKeys.Length; i++)
                {
                    alphas[i] = string.Format("g.alphas[{0}] = float2({1}, {2});"
                                              , i
                                              , value.alphaKeys[i].alpha
                                              , value.alphaKeys[i].time);
                }

                s.AppendLine("Gradient g;");
                s.AppendLine("g.type = {0};",
                             (int)value.mode);
                s.AppendLine("g.colorsLength = {0};",
                             value.colorKeys.Length);
                s.AppendLine("g.alphasLength = {0};",
                             value.alphaKeys.Length);

                for (int i = 0; i < colors.Length; i++)
                {
                    s.AppendLine(colors[i]);
                }

                for (int i = 0; i < alphas.Length; i++)
                {
                    s.AppendLine(alphas[i]);
                }
                s.AppendLine("return g;", true);
            }
            s.AppendLine("#define {0} {0}_Definition()", referenceName);
            return(s.ToString());
        }
        public static string ToShaderString(this StencilDescriptor descriptor)
        {
            ShaderStringBuilder builder = new ShaderStringBuilder();

            builder.AppendLine("Stencil");
            using (builder.BlockScope())
            {
                string compBack  = descriptor.CompBack != null && descriptor.CompBack.Length > 0 ? descriptor.CompBack : descriptor.Comp;
                string zFailBack = descriptor.ZFailBack != null && descriptor.ZFailBack.Length > 0 ? descriptor.ZFailBack : descriptor.ZFail;
                string failBack  = descriptor.FailBack != null && descriptor.FailBack.Length > 0 ? descriptor.FailBack : descriptor.Fail;
                string passBack  = descriptor.PassBack != null && descriptor.PassBack.Length > 0 ? descriptor.PassBack : descriptor.Pass;

                if (descriptor.WriteMask != null && descriptor.WriteMask.Length > 0)
                {
                    builder.AppendLine($"WriteMask {descriptor.WriteMask}");
                }
                if (descriptor.Ref != null && descriptor.Ref.Length > 0)
                {
                    builder.AppendLine($"Ref {descriptor.Ref}");
                }
                if (descriptor.Comp != null && descriptor.Comp.Length > 0)
                {
                    builder.AppendLine($"CompFront {descriptor.Comp}");
                }
                if (descriptor.ZFail != null && descriptor.ZFail.Length > 0)
                {
                    builder.AppendLine($"ZFailFront {descriptor.ZFail}");
                }
                if (descriptor.Fail != null && descriptor.Fail.Length > 0)
                {
                    builder.AppendLine($"FailFront {descriptor.Fail}");
                }
                if (descriptor.Pass != null && descriptor.Pass.Length > 0)
                {
                    builder.AppendLine($"PassFront {descriptor.Pass}");
                }
                if (compBack != null && compBack.Length > 0)
                {
                    builder.AppendLine($"CompBack {compBack}");
                }
                if (zFailBack != null && zFailBack.Length > 0)
                {
                    builder.AppendLine($"ZFailBack {zFailBack}");
                }
                if (failBack != null && failBack.Length > 0)
                {
                    builder.AppendLine($"FailBack {failBack}");
                }
                if (passBack != null && passBack.Length > 0)
                {
                    builder.AppendLine($"PassBack {passBack}");
                }
            }
            return(builder.ToCodeBlock());
        }
        public string GetShader(GenerationMode mode, string outputName, out List <PropertyCollector.TextureInfo> configuredTextures)
        {
            var activeNodeList = ListPool <INode> .Get();

            NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, this);

            var shaderProperties = new PropertyCollector();

            var abstractMaterialGraph = owner as AbstractMaterialGraph;

            if (abstractMaterialGraph != null)
            {
                abstractMaterialGraph.CollectShaderProperties(shaderProperties, mode);
            }

            foreach (var activeNode in activeNodeList.OfType <AbstractMaterialNode>())
            {
                activeNode.CollectShaderProperties(shaderProperties, mode);
            }

            var finalShader = new ShaderStringBuilder();

            finalShader.AppendLine(@"Shader ""{0}""", outputName);
            using (finalShader.BlockScope())
            {
                finalShader.AppendLine("Properties");
                using (finalShader.BlockScope())
                {
                    finalShader.AppendLine(shaderProperties.GetPropertiesBlock(0));
                }

                foreach (var subShader in m_SubShaders)
                {
                    finalShader.AppendLines(subShader.GetSubshader(this, mode));
                }

                finalShader.AppendLine(@"FallBack ""Hidden/InternalErrorShader""");
            }
            configuredTextures = shaderProperties.GetConfiguredTexutres();
            return(finalShader.ToString());
        }
        public void GetTags(ShaderStringBuilder builder, string pipeline)
        {
            builder.AppendLine("Tags");
            using (builder.BlockScope())
            {
                builder.AppendLine("\"RenderPipeline\"=\"{0}\"", pipeline);
                builder.AppendLine("\"RenderType\"=\"{0}\"", renderType);

                string seperator = renderQueueOffset >= 0 ? "+" : "";
                builder.AppendLine("\"Queue\"=\"{0}{1}{2}\"", renderQueue, seperator, renderQueueOffset);
            }
        }
Beispiel #13
0
 private void GenCopyFunc(string funcName, string dstType, string srcType, ShaderStringBuilder builder, string makeDefine = "")
 {
     builder.AppendLine($"{dstType} {funcName}(inout {dstType} output, {srcType} input)");
     using (builder.BlockScope())
     {
         GenCopyBlock("output", "input", builder);
         builder.AppendLine("return output;");
     }
     if (makeDefine != null && makeDefine != "")
     {
         builder.AppendLine($"#define {makeDefine}");
     }
 }
Beispiel #14
0
        public static void GenerateVertexDescriptionFunction(
            GraphData graph,
            ShaderStringBuilder builder,
            FunctionRegistry functionRegistry,
            PropertyCollector shaderProperties,
            KeywordCollector shaderKeywords,
            GenerationMode mode,
            AbstractMaterialNode rootNode,
            List <AbstractMaterialNode> nodes,
            List <int>[] keywordPermutationsPerNode,
            List <MaterialSlot> slots,
            string graphInputStructName  = "VertexDescriptionInputs",
            string functionName          = "PopulateVertexData",
            string graphOutputStructName = k_VertexDescriptionStructName)
        {
            if (graph == null)
            {
                return;
            }

            graph.CollectShaderProperties(shaderProperties, mode);

            builder.AppendLine("{0} {1}({2} IN)", graphOutputStructName, functionName, graphInputStructName);
            using (builder.BlockScope())
            {
                builder.AppendLine("{0} description = ({0})0;", graphOutputStructName);
                for (int i = 0; i < nodes.Count; i++)
                {
                    GenerateDescriptionForNode(nodes[i], keywordPermutationsPerNode[i], functionRegistry, builder,
                                               shaderProperties, shaderKeywords,
                                               graph, mode);
                }

                functionRegistry.builder.currentNode = null;
                builder.currentNode = null;

                if (slots.Count != 0)
                {
                    foreach (var slot in slots)
                    {
                        var isSlotConnected = slot.owner.owner.GetEdges(slot.slotReference).Any();
                        var slotName        = NodeUtils.GetHLSLSafeName(slot.shaderOutputName);
                        var slotValue       = isSlotConnected ?
                                              ((AbstractMaterialNode)slot.owner).GetSlotValue(slot.id, mode, slot.owner.concretePrecision) : slot.GetDefaultValue(mode, slot.owner.concretePrecision);
                        builder.AppendLine("description.{0} = {1};", slotName, slotValue);
                    }
                }

                builder.AppendLine("return description;");
            }
        }
        public static void GenerateVertexDescriptionFunction(
            AbstractMaterialGraph graph,
            ShaderStringBuilder builder,
            FunctionRegistry functionRegistry,
            PropertyCollector shaderProperties,
            GenerationMode mode,
            List <AbstractMaterialNode> nodes,
            List <MaterialSlot> slots,
            string graphInputStructName = "VertexDescriptionInputs")
        {
            if (graph == null)
            {
                return;
            }

            GraphContext graphContext = new GraphContext(graphInputStructName);

            graph.CollectShaderProperties(shaderProperties, mode);

            builder.AppendLine("{0} PopulateVertexData(VertexDescriptionInputs IN)", k_VertexDescriptionStructName);
            using (builder.BlockScope())
            {
                ShaderGenerator sg = new ShaderGenerator();
                builder.AppendLine("{0} description = ({0})0;", k_VertexDescriptionStructName);
                foreach (var node in nodes)
                {
                    var generatesFunction = node as IGeneratesFunction;
                    if (generatesFunction != null)
                    {
                        functionRegistry.builder.currentNode = node;
                        generatesFunction.GenerateNodeFunction(functionRegistry, graphContext, mode);
                    }
                    var generatesBodyCode = node as IGeneratesBodyCode;
                    if (generatesBodyCode != null)
                    {
                        generatesBodyCode.GenerateNodeCode(sg, mode);
                    }
                    node.CollectShaderProperties(shaderProperties, mode);
                }
                builder.AppendLines(sg.GetShaderString(0));
                foreach (var slot in slots)
                {
                    var isSlotConnected = slot.owner.owner.GetEdges(slot.slotReference).Any();
                    var slotName        = NodeUtils.GetHLSLSafeName(slot.shaderOutputName);
                    var slotValue       = isSlotConnected ? ((AbstractMaterialNode)slot.owner).GetSlotValue(slot.id, mode) : slot.GetDefaultValue(mode);
                    builder.AppendLine("description.{0} = {1};", slotName, slotValue);
                }
                builder.AppendLine("return description;");
            }
        }
Beispiel #16
0
        public static string ToShaderString(this StencilDescriptor descriptor)
        {
            ShaderStringBuilder builder = new ShaderStringBuilder();

            builder.AppendLine("Stencil");
            using (builder.BlockScope())
            {
                builder.AppendLine($"WriteMask {descriptor.WriteMask}");
                builder.AppendLine($"Ref {descriptor.Ref}");
                builder.AppendLine($"Comp {descriptor.Comp}");
                builder.AppendLine($"Pass {descriptor.Pass}");
            }
            return(builder.ToCodeBlock());
        }
Beispiel #17
0
        public void GenerateNodeFunction(ShaderGenerator visitor, GraphContext graphContext, GenerationMode generationMode)
        {
            var sb = new ShaderStringBuilder();

            sb.AppendLine("void {0}({1} In, {2} Flip, out {3} Out)",
                          GetFunctionName(),
                          FindInputSlot <MaterialSlot>(InputSlotId).concreteValueType.ToString(precision),
                          FindInputSlot <MaterialSlot>(InputSlotId).concreteValueType.ToString(precision),
                          FindOutputSlot <MaterialSlot>(OutputSlotId).concreteValueType.ToString(precision));
            using (sb.BlockScope())
            {
                sb.AppendLine("Out = (Flip * -2 + 1) * In;");
            }
            visitor.AddShaderChunk(sb.ToString(), true);
        }
Beispiel #18
0
        public string GetShader(GenerationMode mode, string outputName, out List <PropertyCollector.TextureInfo> configuredTextures, List <string> sourceAssetDependencyPaths = null)
        {
            var activeNodeList = ListPool <AbstractMaterialNode> .Get();

            NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, this);

            var shaderProperties = new PropertyCollector();
            var shaderKeywords   = new KeywordCollector();

            if (owner != null)
            {
                owner.CollectShaderProperties(shaderProperties, mode);
                owner.CollectShaderKeywords(shaderKeywords, mode);
            }

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

                configuredTextures = shaderProperties.GetConfiguredTexutres();
                return(ShaderGraphImporter.k_ErrorShader);
            }

            foreach (var activeNode in activeNodeList.OfType <AbstractMaterialNode>())
            {
                activeNode.CollectShaderProperties(shaderProperties, mode);
            }

            var finalShader = new ShaderStringBuilder();

            finalShader.AppendLine(@"Shader ""{0}""", outputName);
            using (finalShader.BlockScope())
            {
                GraphUtil.GeneratePropertiesBlock(finalShader, shaderProperties, shaderKeywords, mode);

                foreach (var subShader in m_SubShaders)
                {
                    if (mode != GenerationMode.Preview || subShader.IsPipelineCompatible(GraphicsSettings.renderPipelineAsset))
                    {
                        finalShader.AppendLines(subShader.GetSubshader(this, mode, sourceAssetDependencyPaths));
                    }
                }

                finalShader.AppendLine(@"FallBack ""Hidden/InternalErrorShader""");
            }
            configuredTextures = shaderProperties.GetConfiguredTexutres();
            return(finalShader.ToString());
        }
Beispiel #19
0
        public static void GenerateSurfaceDescriptionFunction(
            List <AbstractMaterialNode> nodes,
            List <int>[] keywordPermutationsPerNode,
            AbstractMaterialNode rootNode,
            GraphData graph,
            ShaderStringBuilder surfaceDescriptionFunction,
            FunctionRegistry functionRegistry,
            PropertyCollector shaderProperties,
            KeywordCollector shaderKeywords,
            GenerationMode mode,
            string functionName                    = "PopulateSurfaceData",
            string surfaceDescriptionName          = "SurfaceDescription",
            Vector1ShaderProperty outputIdProperty = null,
            IEnumerable <MaterialSlot> slots       = null,
            string graphInputStructName            = "SurfaceDescriptionInputs")
        {
            if (graph == null)
            {
                return;
            }

            graph.CollectShaderProperties(shaderProperties, mode);

            surfaceDescriptionFunction.AppendLine(String.Format("{0} {1}(SurfaceDescriptionInputs IN)", surfaceDescriptionName, functionName), false);
            using (surfaceDescriptionFunction.BlockScope())
            {
                surfaceDescriptionFunction.AppendLine("{0} surface = ({0})0;", surfaceDescriptionName);
                for (int i = 0; i < nodes.Count; i++)
                {
                    GenerateDescriptionForNode(nodes[i], keywordPermutationsPerNode[i], functionRegistry, surfaceDescriptionFunction,
                                               shaderProperties, shaderKeywords,
                                               graph, mode);
                }

                functionRegistry.builder.currentNode   = null;
                surfaceDescriptionFunction.currentNode = null;

                GenerateSurfaceDescriptionRemap(graph, rootNode, slots,
                                                surfaceDescriptionFunction, mode);

                surfaceDescriptionFunction.AppendLine("return surface;");
            }
        }
Beispiel #20
0
        void AppendVtParameters(ShaderStringBuilder sb, string uvExpr, string lodExpr, string dxExpr, string dyExpr, AddressMode address, FilterMode filter, LodCalculation lod, UvSpace space, QualityMode quality)
        {
            sb.AppendLine("VtInputParameters vtParams;");
            sb.AppendLine("vtParams.uv = " + uvExpr + ";");
            sb.AppendLine("vtParams.lodOrOffset = " + lodExpr + ";");
            sb.AppendLine("vtParams.dx = " + dxExpr + ";");
            sb.AppendLine("vtParams.dy = " + dyExpr + ";");
            sb.AppendLine("vtParams.addressMode = " + address + ";");
            sb.AppendLine("vtParams.filterMode = " + filter + ";");
            sb.AppendLine("vtParams.levelMode = " + lod + ";");
            sb.AppendLine("vtParams.uvMode = " + space + ";");
            sb.AppendLine("vtParams.sampleQuality = " + quality + ";");

            sb.AppendLine("#if defined(SHADER_STAGE_RAY_TRACING)");
            sb.AppendLine("if (vtParams.levelMode == VtLevel_Automatic || vtParams.levelMode == VtLevel_Bias)");
            using (sb.BlockScope())
            {
                sb.AppendLine("vtParams.levelMode = VtLevel_Lod;");
                sb.AppendLine("vtParams.lodOrOffset = 0.0f;");
            }
            sb.AppendLine("#endif");
        }
Beispiel #21
0
        public static void GeneratePropertiesBlock(ShaderStringBuilder sb, PropertyCollector propertyCollector, KeywordCollector keywordCollector, GenerationMode mode)
        {
            sb.AppendLine("Properties");
            using (sb.BlockScope())
            {
                foreach (var prop in propertyCollector.properties.Where(x => x.generatePropertyBlock))
                {
                    sb.AppendLine(prop.GetPropertyBlockString());
                }

                // Keywords use hardcoded state in preview
                // Do not add them to the Property Block
                if (mode == GenerationMode.Preview)
                {
                    return;
                }

                foreach (var key in keywordCollector.keywords.Where(x => x.generatePropertyBlock))
                {
                    sb.AppendLine(key.GetPropertyBlockString());
                }
            }
        }
 public override string GetPropertyDeclarationString(string delimiter = ";")
 {
     if (m_OverrideMembers)
     {
         ShaderStringBuilder s = new ShaderStringBuilder();
         s.AppendLine("Gradient Unity{0} ()",
                      referenceName);
         using (s.BlockScope())
         {
             s.AppendLine("Gradient g;");
             s.AppendLine("g.type = {0}_Type;", m_OverrideSlotName);
             s.AppendLine("g.colorsLength = {0}_ColorsLength;", m_OverrideSlotName);
             s.AppendLine("g.alphasLength = {0}_AlphasLength;", m_OverrideSlotName);
             for (int i = 0; i < 8; i++)
             {
                 s.AppendLine("g.colors[{0}] = {1}_ColorKey{0};", i, m_OverrideSlotName);
             }
             for (int i = 0; i < 8; i++)
             {
                 s.AppendLine("g.alphas[{0}] = {1}_AlphaKey{0};", i, m_OverrideSlotName);
             }
             s.AppendLine("return g;", true);
         }
         return(s.ToString());
     }
     else
     {
         ShaderStringBuilder s = new ShaderStringBuilder();
         s.AppendLine("Gradient Unity{0} ()", referenceName);
         using (s.BlockScope())
         {
             GradientUtils.GetGradientDeclaration(value, ref s);
             s.AppendLine("return g;", true);
         }
         return(s.ToString());
     }
 }
Beispiel #23
0
        // TODO: could get rid of this if we could run a codegen prepass (with proper keyword #ifdef)
        public static void GenerateVirtualTextureFeedback(
            List <AbstractMaterialNode> downstreamNodesIncludingRoot,
            List <int>[] keywordPermutationsPerNode,
            ShaderStringBuilder surfaceDescriptionFunction,
            KeywordCollector shaderKeywords)
        {
            // A note on how we handle vt feedback in combination with keywords:
            // We essentially generate a fully separate feedback path for each permutation of keywords
            // so per permutation we gather variables contribution to feedback and we generate
            // feedback gathering for each permutation individually.

            var feedbackVariablesPerPermutation = PooledList <PooledList <string> > .Get();

            try
            {
                if (shaderKeywords.permutations.Count >= 1)
                {
                    for (int i = 0; i < shaderKeywords.permutations.Count; i++)
                    {
                        feedbackVariablesPerPermutation.Add(PooledList <string> .Get());
                    }
                }
                else
                {
                    // Create a dummy single permutation
                    feedbackVariablesPerPermutation.Add(PooledList <string> .Get());
                }

                int index = 0; //for keywordPermutationsPerNode
                foreach (var node in downstreamNodesIncludingRoot)
                {
                    if (node is SampleVirtualTextureNode vtNode)
                    {
                        if (vtNode.noFeedback)
                        {
                            continue;
                        }
                        if (keywordPermutationsPerNode[index] == null)
                        {
                            Debug.Assert(shaderKeywords.permutations.Count == 0, $"Shader has {shaderKeywords.permutations.Count} permutations but keywordPermutationsPerNode of some nodes are null.");
                            feedbackVariablesPerPermutation[0].Add(vtNode.GetFeedbackVariableName());
                        }
                        else
                        {
                            foreach (int perm in keywordPermutationsPerNode[index])
                            {
                                feedbackVariablesPerPermutation[perm].Add(vtNode.GetFeedbackVariableName());
                            }
                        }
                    }

                    if (node is SubGraphNode sgNode)
                    {
                        if (sgNode.asset == null)
                        {
                            continue;
                        }
                        if (keywordPermutationsPerNode[index] == null)
                        {
                            Debug.Assert(shaderKeywords.permutations.Count == 0, $"Shader has {shaderKeywords.permutations.Count} permutations but keywordPermutationsPerNode of some nodes are null.");
                            foreach (var feedbackSlot in sgNode.asset.vtFeedbackVariables)
                            {
                                feedbackVariablesPerPermutation[0].Add(node.GetVariableNameForNode() + "_" + feedbackSlot);
                            }
                        }
                        else
                        {
                            foreach (var feedbackSlot in sgNode.asset.vtFeedbackVariables)
                            {
                                foreach (int perm in keywordPermutationsPerNode[index])
                                {
                                    feedbackVariablesPerPermutation[perm].Add(node.GetVariableNameForNode() + "_" + feedbackSlot);
                                }
                            }
                        }
                    }

                    index++;
                }

                index = 0;
                foreach (var feedbackVariables in feedbackVariablesPerPermutation)
                {
                    // If it's a dummy single always-on permutation don't put an ifdef around the code
                    if (shaderKeywords.permutations.Count >= 1)
                    {
                        surfaceDescriptionFunction.AppendLine(KeywordUtil.GetKeywordPermutationConditional(index));
                    }

                    using (surfaceDescriptionFunction.BlockScope())
                    {
                        if (feedbackVariables.Count == 0)
                        {
                            string feedBackCode = "surface.VTPackedFeedback = float4(1.0f,1.0f,1.0f,1.0f);";
                            surfaceDescriptionFunction.AppendLine(feedBackCode);
                        }
                        else if (feedbackVariables.Count == 1)
                        {
                            string feedBackCode = "surface.VTPackedFeedback = GetPackedVTFeedback(" + feedbackVariables[0] + ");";
                            surfaceDescriptionFunction.AppendLine(feedBackCode);
                        }
                        else if (feedbackVariables.Count > 1)
                        {
                            surfaceDescriptionFunction.AppendLine("float4 VTFeedback_array[" + feedbackVariables.Count + "];");

                            int arrayIndex = 0;
                            foreach (var variable in feedbackVariables)
                            {
                                surfaceDescriptionFunction.AppendLine("VTFeedback_array[" + arrayIndex + "] = " + variable + ";");
                                arrayIndex++;
                            }

                            // TODO: should read from NDCPosition instead...
                            surfaceDescriptionFunction.AppendLine("uint pixelColumn = (IN.ScreenPosition.x / IN.ScreenPosition.w) * _ScreenParams.x;");
                            surfaceDescriptionFunction.AppendLine(
                                "surface.VTPackedFeedback = GetPackedVTFeedback(VTFeedback_array[(pixelColumn + _FrameCount) % (uint)" + feedbackVariables.Count + "]);");
                        }
                    }

                    if (shaderKeywords.permutations.Count >= 1)
                    {
                        surfaceDescriptionFunction.AppendLine("#endif");
                    }

                    index++;
                }
            }
            finally
            {
                foreach (var list in feedbackVariablesPerPermutation)
                {
                    list.Dispose();
                }
                feedbackVariablesPerPermutation.Dispose();
            }
        }
Beispiel #24
0
        private static void ViaWorld(SpaceTransform xform, string inputValue, string outputVariable, ShaderStringBuilder sb)
        {
            // should never be calling this if one of the spaces is already world space (silly, and could lead to infinite recursions)
            if ((xform.from == CoordinateSpace.World) || (xform.to == CoordinateSpace.World))
            {
                return;
            }

            // this breaks the transform into two parts: (from->world) and (world->to)
            var toWorld = new SpaceTransform()
            {
                from      = xform.from,
                to        = CoordinateSpace.World,
                type      = xform.type,
                normalize = false,
                version   = xform.version
            };

            var fromWorld = new SpaceTransform()
            {
                from      = CoordinateSpace.World,
                to        = xform.to,
                type      = xform.type,
                normalize = xform.normalize,
                version   = xform.version
            };

            // Apply Versioning Hacks to match old (incorrect) versions
            if (xform.version <= 1)
            {
                if (xform.type == ConversionType.Direction)
                {
                    switch (xform.from)
                    {
                    case CoordinateSpace.AbsoluteWorld:
                        if ((xform.to == CoordinateSpace.Object) || (xform.to == CoordinateSpace.View))
                        {
                            // these transforms were wrong in v0, but correct in v1, so here we
                            // pretend it is a later version to disable the v1 versioning in the AbsWorldToWorld transform
                            if (xform.version == 1)
                            {
                                toWorld.version = 2;
                            }
                        }
                        break;

                    case CoordinateSpace.View:
                        if ((xform.to == CoordinateSpace.Tangent) || (xform.to == CoordinateSpace.AbsoluteWorld))
                        {
                            // these transforms erroneously used the position view-to-world transform
                            toWorld.type = ConversionType.Position;
                        }
                        break;

                    case CoordinateSpace.Tangent:
                        if ((xform.to == CoordinateSpace.Object) || (xform.to == CoordinateSpace.View) || (xform.to == CoordinateSpace.AbsoluteWorld))
                        {
                            // manually version to 2, to remove normalization (while keeping Normal type)
                            toWorld.type    = ConversionType.Normal;
                            toWorld.version = 2;
                        }
                        break;
                    }
                }
            }

            using (sb.BlockScope())
            {
                sb.AddLine("// Converting ", xform.type.ToString(), " from ", xform.from.ToString(), " to ", xform.to.ToString(), " via world space");
                sb.AddLine("float3 world;");
                GenerateTransformCodeStatement(toWorld, inputValue, "world", sb);
                GenerateTransformCodeStatement(fromWorld, "world", outputVariable, sb);
            }
        }
        public static void GenerateSurfaceDescriptionFunction(
            List <INode> activeNodeList,
            AbstractMaterialNode masterNode,
            AbstractMaterialGraph graph,
            ShaderStringBuilder surfaceDescriptionFunction,
            FunctionRegistry functionRegistry,
            PropertyCollector shaderProperties,
            ShaderGraphRequirements requirements,
            GenerationMode mode,
            string functionName                    = "PopulateSurfaceData",
            string surfaceDescriptionName          = "SurfaceDescription",
            Vector1ShaderProperty outputIdProperty = null,
            IEnumerable <MaterialSlot> slots       = null,
            string graphInputStructName            = "SurfaceDescriptionInputs")
        {
            if (graph == null)
            {
                return;
            }

            GraphContext graphContext = new GraphContext(graphInputStructName);

            graph.CollectShaderProperties(shaderProperties, mode);

            surfaceDescriptionFunction.AppendLine(String.Format("{0} {1}(SurfaceDescriptionInputs IN)", surfaceDescriptionName, functionName), false);
            using (surfaceDescriptionFunction.BlockScope())
            {
                ShaderGenerator sg = new ShaderGenerator();
                surfaceDescriptionFunction.AppendLine("{0} surface = ({0})0;", surfaceDescriptionName);
                foreach (var activeNode in activeNodeList.OfType <AbstractMaterialNode>())
                {
                    if (activeNode is IGeneratesFunction)
                    {
                        functionRegistry.builder.currentNode = activeNode;
                        (activeNode as IGeneratesFunction).GenerateNodeFunction(functionRegistry, graphContext, mode);
                    }
                    if (activeNode is IGeneratesBodyCode)
                    {
                        (activeNode as IGeneratesBodyCode).GenerateNodeCode(sg, mode);
                    }
                    if (masterNode == null && activeNode.hasPreview)
                    {
                        var outputSlot = activeNode.GetOutputSlots <MaterialSlot>().FirstOrDefault();
                        if (outputSlot != null)
                        {
                            sg.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);
                        }
                    }

                    // In case of the subgraph output node, the preview is generated
                    // from the first input to the node.
                    if (activeNode is SubGraphOutputNode)
                    {
                        var inputSlot = activeNode.GetInputSlots <MaterialSlot>().FirstOrDefault();
                        if (inputSlot != null)
                        {
                            var    foundEdges = graph.GetEdges(inputSlot.slotReference).ToArray();
                            string slotValue  = foundEdges.Any() ? activeNode.GetSlotValue(inputSlot.id, mode) : inputSlot.GetDefaultValue(mode);
                            sg.AddShaderChunk(String.Format("if ({0} == {1}) {{ surface.PreviewOutput = {2}; return surface; }}", outputIdProperty.referenceName, activeNode.tempId.index, slotValue), false);
                        }
                    }

                    activeNode.CollectShaderProperties(shaderProperties, mode);
                }
                surfaceDescriptionFunction.AppendLines(sg.GetShaderString(0));
                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())
                            {
                                surfaceDescriptionFunction.AppendLine("surface.{0} = {1};", NodeUtils.GetHLSLSafeName(input.shaderOutputName), masterNode.GetSlotValue(input.id, mode));
                            }
                            else
                            {
                                surfaceDescriptionFunction.AppendLine("surface.{0} = {1};", NodeUtils.GetHLSLSafeName(input.shaderOutputName), input.GetDefaultValue(mode));
                            }
                        }
                    }
                    else if (masterNode.hasPreview)
                    {
                        foreach (var slot in masterNode.GetOutputSlots <MaterialSlot>())
                        {
                            surfaceDescriptionFunction.AppendLine("surface.{0} = {1};", NodeUtils.GetHLSLSafeName(slot.shaderOutputName), masterNode.GetSlotValue(slot.id, mode));
                        }
                    }
                }

                surfaceDescriptionFunction.AppendLine("return surface;");
            }
        }
        public static GenerationResults GetShader(this AbstractMaterialGraph graph, AbstractMaterialNode node, GenerationMode mode, string name)
        {
            var  results = new GenerationResults();
            bool isUber  = node == null;

            var vertexInputs = new ShaderGenerator();
            var vertexShader = new ShaderGenerator();
            var surfaceDescriptionFunction = new ShaderGenerator();
            var surfaceDescriptionStruct   = new ShaderGenerator();
            var functionBuilder            = new ShaderStringBuilder();
            var functionRegistry           = new FunctionRegistry(functionBuilder);
            var surfaceInputs = new ShaderGenerator();

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

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

            if (isUber)
            {
                var unmarkedNodes = graph.GetNodes <INode>().Where(x => !(x is IMasterNode)).ToDictionary(x => x.guid);
                while (unmarkedNodes.Any())
                {
                    var unmarkedNode = unmarkedNodes.FirstOrDefault();
                    Visit(activeNodeList, unmarkedNodes, unmarkedNode.Value);
                }
            }
            else
            {
                NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, node);
            }

            var requirements = ShaderGraphRequirements.FromNodes(activeNodeList);

            GenerateApplicationVertexInputs(requirements, 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);
            }

            results.previewMode = PreviewMode.Preview3D;
            if (!isUber)
            {
                foreach (var pNode in activeNodeList.OfType <AbstractMaterialNode>())
                {
                    if (pNode.previewMode == PreviewMode.Preview3D)
                    {
                        results.previewMode = PreviewMode.Preview3D;
                        break;
                    }
                }
            }

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

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

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

            var slots = new List <MaterialSlot>();

            foreach (var activeNode in isUber ? activeNodeList.Where(n => ((AbstractMaterialNode)n).hasPreview) : ((INode)node).ToEnumerable())
            {
                if (activeNode is IMasterNode)
                {
                    slots.AddRange(activeNode.GetInputSlots <MaterialSlot>());
                }
                else
                {
                    slots.AddRange(activeNode.GetOutputSlots <MaterialSlot>());
                }
            }
            GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, slots, !isUber);

            var shaderProperties = new PropertyCollector();

            results.outputIdProperty = new Vector1ShaderProperty
            {
                displayName           = "OutputId",
                generatePropertyBlock = false,
                value = -1
            };
            if (isUber)
            {
                shaderProperties.AddShaderProperty(results.outputIdProperty);
            }

            GenerateSurfaceDescription(
                activeNodeList,
                node,
                graph,
                surfaceDescriptionFunction,
                functionRegistry,
                shaderProperties,
                requirements,
                mode,
                outputIdProperty: results.outputIdProperty);

            var finalBuilder = new ShaderStringBuilder();

            finalBuilder.AppendLine(@"Shader ""{0}""", name);
            using (finalBuilder.BlockScope())
            {
                finalBuilder.AppendLine("Properties");
                using (finalBuilder.BlockScope())
                {
                    finalBuilder.AppendLines(shaderProperties.GetPropertiesBlock(0));
                }

                finalBuilder.AppendLine(@"HLSLINCLUDE");
                finalBuilder.AppendLine("#define USE_LEGACY_UNITY_MATRIX_VARIABLES");
                finalBuilder.AppendLine(@"#include ""CoreRP/ShaderLibrary/Common.hlsl""");
                finalBuilder.AppendLine(@"#include ""CoreRP/ShaderLibrary/Packing.hlsl""");
                finalBuilder.AppendLine(@"#include ""CoreRP/ShaderLibrary/Color.hlsl""");
                finalBuilder.AppendLine(@"#include ""CoreRP/ShaderLibrary/UnityInstancing.hlsl""");
                finalBuilder.AppendLine(@"#include ""CoreRP/ShaderLibrary/EntityLighting.hlsl""");
                finalBuilder.AppendLine(@"#include ""ShaderGraphLibrary/ShaderVariables.hlsl""");
                finalBuilder.AppendLine(@"#include ""ShaderGraphLibrary/ShaderVariablesFunctions.hlsl""");
                finalBuilder.AppendLine(@"#include ""ShaderGraphLibrary/Functions.hlsl""");

                finalBuilder.AppendLines(shaderProperties.GetPropertiesDeclaration(0));
                finalBuilder.AppendLines(surfaceInputs.GetShaderString(0));
                finalBuilder.Concat(functionBuilder);
                finalBuilder.AppendLines(vertexInputs.GetShaderString(0));
                finalBuilder.AppendLines(surfaceDescriptionStruct.GetShaderString(0));
                finalBuilder.AppendLines(vertexShader.GetShaderString(0));
                finalBuilder.AppendLines(surfaceDescriptionFunction.GetShaderString(0));
                finalBuilder.AppendLine(@"ENDHLSL");

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

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

            results.shader    = finalBuilder.ToString(out sourceMap);
            results.sourceMap = sourceMap;
            return(results);
        }
Beispiel #27
0
        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 ""Assets/Scripts/URP/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl""");
                finalShader.AppendLine(@"#include ""Assets/Scripts/URP/com.unity.render-pipelines.core/ShaderLibrary/Packing.hlsl""");
                finalShader.AppendLine(@"#include ""Assets/Scripts/URP/com.unity.render-pipelines.core/ShaderLibrary/NormalSurfaceGradient.hlsl""");
                finalShader.AppendLine(@"#include ""Assets/Scripts/URP/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl""");
                finalShader.AppendLine(@"#include ""Assets/Scripts/URP/com.unity.render-pipelines.core/ShaderLibrary/UnityInstancing.hlsl""");
                finalShader.AppendLine(@"#include ""Assets/Scripts/URP/com.unity.render-pipelines.core/ShaderLibrary/EntityLighting.hlsl""");
                finalShader.AppendLine(@"#include ""Assets/Scripts/URP/com.unity.shadergraph/ShaderGraphLibrary/ShaderVariables.hlsl""");
                finalShader.AppendLine(@"#include ""Assets/Scripts/URP/com.unity.shadergraph/ShaderGraphLibrary/ShaderVariablesFunctions.hlsl""");
                finalShader.AppendLine(@"#include ""Assets/Scripts/URP/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);
        }