Пример #1
0
        internal override void AppendNonBatchablePropertyDeclarations(ShaderStringBuilder builder, string delimiter = ";")
        {
            int numLayers = value.layers.Count;

            if (numLayers > 0)
            {
                if (!value.procedural)
                {
                    // declare regular texture properties (for fallback case)
                    for (int i = 0; i < value.layers.Count; i++)
                    {
                        string layerRefName = value.layers[i].layerRefName;
                        builder.AppendLine(
                            $"TEXTURE2D({layerRefName}); SAMPLER(sampler{layerRefName}); {concretePrecision.ToShaderString()}4 {layerRefName}_TexelSize;");
                    }
                }

                // declare texture stack
                builder.AppendIndentation();
                builder.Append("DECLARE_STACK");
                builder.Append((numLayers <= 1) ? "" : numLayers.ToString());
                builder.Append("(");
                builder.Append(referenceName);
                builder.Append(",");
                for (int i = 0; i < value.layers.Count; i++)
                {
                    if (i != 0)
                    {
                        builder.Append(",");
                    }
                    builder.Append(value.layers[i].layerRefName);
                }
                builder.Append(")");
                builder.Append(delimiter);
                builder.AppendNewLine();

                // declare the actual virtual texture property "variable" as a macro define to the BuildVTProperties function
                builder.AppendIndentation();
                builder.Append("#define ");
                builder.Append(referenceName);
                builder.Append(" AddTextureType(BuildVTProperties_");
                builder.Append(referenceName);
                builder.Append("()");
                for (int i = 0; i < value.layers.Count; i++)
                {
                    builder.Append(",");
                    builder.Append("TEXTURETYPE_");
                    builder.Append(value.layers[i].layerTextureType.ToString().ToUpper());
                }
                builder.Append(")");
                builder.AppendNewLine();
            }
        }
Пример #2
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());
        }
Пример #3
0
        public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
        {
            var inputValue  = GetSlotValue(InputSlotId, generationMode);
            var outputValue = GetSlotValue(OutputSlotId, generationMode);

            sb.AppendLine("{0} {1};", FindOutputSlot <MaterialSlot>(OutputSlotId).concreteValueType.ToShaderString(), GetVariableNameForSlot(OutputSlotId));

            if (!generationMode.IsPreview())
            {
                sb.AppendIndentation();
                sb.Append("{0} _{1}_Flip = {0} ({2}",
                          FindInputSlot <MaterialSlot>(InputSlotId).concreteValueType.ToShaderString(),
                          GetVariableNameForNode(),
                          Convert.ToInt32(m_RedChannel));
                if (channelCount > 1)
                {
                    sb.Append(", {0}", Convert.ToInt32(m_GreenChannel));
                }
                if (channelCount > 2)
                {
                    sb.Append(", {0}", Convert.ToInt32(m_BlueChannel));
                }
                if (channelCount > 3)
                {
                    sb.Append(", {0}", Convert.ToInt32(m_AlphaChannel));
                }
                sb.Append(");");
                sb.AppendNewLine();
            }

            sb.AppendLine("{0}({1}, _{2}_Flip, {3});", GetFunctionName(), inputValue, GetVariableNameForNode(), outputValue);
        }
Пример #4
0
 void AppendVtSample(ShaderStringBuilder sb, string propertiesName, string vtInputVariable, string infoVariable, int layerIndex, string outputVariableName)
 {
     sb.AppendIndentation();
     sb.Append(outputVariableName); sb.Append(" = ");
     sb.Append("SampleVTLayerWithTextureType(");
     sb.Append(propertiesName);          sb.Append(", ");
     sb.Append(vtInputVariable);         sb.Append(", ");
     sb.Append(infoVariable);            sb.Append(", ");
     sb.Append(layerIndex.ToString());   sb.Append(");");
     sb.AppendNewLine();
 }
Пример #5
0
        public static void GetKeywordPermutationDeclarations(ShaderStringBuilder sb, List <List <KeyValuePair <ShaderKeyword, int> > > permutations)
        {
            if (permutations.Count == 0)
            {
                return;
            }

            for (int p = 0; p < permutations.Count; p++)
            {
                // ShaderStringBuilder.Append doesnt apply indentation
                sb.AppendIndentation();

                // Append correct if
                bool isLast = false;
                if (p == 0)
                {
                    sb.Append("#if ");
                }
                else if (p == permutations.Count - 1)
                {
                    sb.Append("#else");
                    isLast = true;
                }
                else
                {
                    sb.Append("#elif ");
                }

                // Last permutation is always #else
                if (!isLast)
                {
                    // Track whether && is required
                    bool appendAnd = false;

                    // Iterate all keywords that are part of the permutation
                    for (int i = 0; i < permutations[p].Count; i++)
                    {
                        // When previous keyword was inserted subsequent requires &&
                        string and = appendAnd ? " && " : string.Empty;

                        switch (permutations[p][i].Key.keywordType)
                        {
                        case KeywordType.Enum:
                        {
                            sb.Append($"{and}defined({permutations[p][i].Key.referenceName}_{permutations[p][i].Key.entries[permutations[p][i].Value].referenceName})");
                            appendAnd = true;
                            break;
                        }

                        case KeywordType.Boolean:
                        {
                            // HLSL does not support a !value predicate
                            if (permutations[p][i].Value != 0)
                            {
                                continue;
                            }

                            sb.Append($"{and}defined({permutations[p][i].Key.referenceName})");
                            appendAnd = true;
                            break;
                        }

                        default:
                            throw new ArgumentOutOfRangeException();
                        }
                    }
                }
                sb.AppendNewLine();

                // Define the matching permutation keyword
                sb.IncreaseIndent();
                sb.AppendLine($"#define KEYWORD_PERMUTATION_{p}");
                sb.DecreaseIndent();
            }

            // End statement
            sb.AppendLine("#endif");
        }
Пример #6
0
        public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
        {
            if (asset == null || hasError)
            {
                var outputSlots = new List <MaterialSlot>();
                GetOutputSlots(outputSlots);
                var outputPrecision = asset != null ? asset.outputPrecision : ConcretePrecision.Single;
                foreach (var slot in outputSlots)
                {
                    sb.AppendLine($"{slot.concreteValueType.ToShaderString(outputPrecision)} {GetVariableNameForSlot(slot.id)} = {slot.GetDefaultValue(GenerationMode.ForReals)};");
                }

                return;
            }

            var inputVariableName = $"_{GetVariableNameForNode()}";

            GenerationUtils.GenerateSurfaceInputTransferCode(sb, asset.requirements, asset.inputStructName, inputVariableName);

            foreach (var outSlot in asset.outputs)
            {
                sb.AppendLine("{0} {1};", outSlot.concreteValueType.ToShaderString(asset.outputPrecision), GetVariableNameForSlot(outSlot.id));
            }

            var arguments = new List <string>();

            foreach (var prop in asset.inputs)
            {
                prop.ValidateConcretePrecision(asset.graphPrecision);
                var inSlotId = m_PropertyIds[m_PropertyGuids.IndexOf(prop.guid.ToString())];

                arguments.Add(GetSlotValue(inSlotId, generationMode, prop.concretePrecision));
            }

            // pass surface inputs through
            arguments.Add(inputVariableName);

            foreach (var outSlot in asset.outputs)
            {
                arguments.Add(GetVariableNameForSlot(outSlot.id));
            }

            foreach (var feedbackSlot in asset.vtFeedbackVariables)
            {
                string feedbackVar = GetVariableNameForNode() + "_" + feedbackSlot;
                sb.AppendLine("{0} {1};", ConcreteSlotValueType.Vector4.ToShaderString(ConcretePrecision.Single), feedbackVar);
                arguments.Add(feedbackVar);
            }

            sb.AppendIndentation();
            sb.Append(asset.functionName);
            sb.Append("(");
            bool firstArg = true;

            foreach (var arg in arguments)
            {
                if (!firstArg)
                {
                    sb.Append(", ");
                }
                firstArg = false;
                sb.Append(arg);
            }
            sb.Append(");");
            sb.AppendNewLine();
        }
Пример #7
0
        public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
        {
            bool success = false;

            if (IsSlotConnected(VirtualTextureInputId))
            {
                var vtProperty = GetSlotProperty(VirtualTextureInputId) as VirtualTextureShaderProperty;
                if (vtProperty != null)
                {
                    var layerOutputVariables = new List <string>();
                    int layerCount           = vtProperty.value.layers.Count;
                    for (int i = 0; i < layerCount; i++)
                    {
                        if (IsSlotConnected(OutputSlotIds[i]))
                        {
                            // declare output variables up front
                            string layerOutputVariable = GetVariableNameForSlot(OutputSlotIds[i]);
                            sb.AppendLine("$precision4 " + layerOutputVariable + ";");
                            layerOutputVariables.Add(layerOutputVariable);
                        }
                    }

                    if (layerOutputVariables.Count > 0)
                    {
                        // assign feedback variable
                        sb.AppendIndentation();
                        if (!noFeedback)
                        {
                            sb.Append("float4 ");
                            sb.Append(GetFeedbackVariableName());
                            sb.Append(" = ");
                        }
                        sb.Append(GetFunctionName(out var unused));
                        sb.Append("(");
                        sb.Append(GetSlotValue(UVInputId, generationMode));
                        switch (lodCalculation)
                        {
                        case LodCalculation.VtLevel_Lod:
                        case LodCalculation.VtLevel_Bias:
                            sb.Append(", ");
                            sb.Append((lodCalculation == LodCalculation.VtLevel_Lod) ? GetSlotValue(LODInputId, generationMode) : GetSlotValue(BiasInputId, generationMode));
                            break;

                        case LodCalculation.VtLevel_Derivatives:
                            sb.Append(", ");
                            sb.Append(GetSlotValue(DxInputId, generationMode));
                            sb.Append(", ");
                            sb.Append(GetSlotValue(DyInputId, generationMode));
                            break;
                        }
                        sb.Append(", ");
                        sb.Append(vtProperty.referenceName);
                        foreach (string layerOutputVariable in layerOutputVariables)
                        {
                            sb.Append(", ");
                            sb.Append(layerOutputVariable);
                        }
                        sb.Append(");");
                        sb.AppendNewLine();
                        success = true;
                    }
                }
            }


            if (!success)
            {
                // set all outputs to zero
                for (int i = 0; i < kMaxLayers; i++)
                {
                    if (IsSlotConnected(OutputSlotIds[i]))
                    {
                        // declare output variables up front
                        string layerOutputVariable = GetVariableNameForSlot(OutputSlotIds[i]);
                        sb.AppendLine("$precision4 " + layerOutputVariable + " = 0;");
                    }
                }
                // TODO: should really just disable feedback in this case (need different feedback interface to do this)
                sb.AppendLine("$precision4 " + GetFeedbackVariableName() + " = 1;");
            }
        }
Пример #8
0
        public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
        {
            var outputGraphPrecision = asset?.outputGraphPrecision ?? GraphPrecision.Single;
            var outputPrecision      = outputGraphPrecision.ToConcrete(concretePrecision);

            if (asset == null || hasError)
            {
                var outputSlots = new List <MaterialSlot>();
                GetOutputSlots(outputSlots);

                foreach (var slot in outputSlots)
                {
                    sb.AppendLine($"{slot.concreteValueType.ToShaderString(outputPrecision)} {GetVariableNameForSlot(slot.id)} = {slot.GetDefaultValue(GenerationMode.ForReals)};");
                }

                return;
            }

            var inputVariableName = $"_{GetVariableNameForNode()}";

            GenerationUtils.GenerateSurfaceInputTransferCode(sb, asset.requirements, asset.inputStructName, inputVariableName);

            // declare output variables
            foreach (var outSlot in asset.outputs)
            {
                sb.AppendLine("{0} {1};", outSlot.concreteValueType.ToShaderString(outputPrecision), GetVariableNameForSlot(outSlot.id));
            }

            var arguments = new List <string>();

            foreach (AbstractShaderProperty prop in asset.inputs)
            {
                // setup the property concrete precision (fallback to node concrete precision when it's switchable)
                prop.SetupConcretePrecision(this.concretePrecision);
                var inSlotId = m_PropertyIds[m_PropertyGuids.IndexOf(prop.guid.ToString())];
                arguments.Add(GetSlotValue(inSlotId, generationMode, prop.concretePrecision));

                if (prop.isConnectionTestable)
                {
                    arguments.Add(IsSlotConnected(inSlotId) ? "true" : "false");
                }
            }

            var dropdowns = asset.dropdowns;

            foreach (var dropdown in dropdowns)
            {
                var name = GetDropdownEntryName(dropdown.referenceName);
                if (dropdown.ContainsEntry(name))
                {
                    arguments.Add(dropdown.IndexOfName(name).ToString());
                }
                else
                {
                    arguments.Add(dropdown.value.ToString());
                }
            }

            // pass surface inputs through
            arguments.Add(inputVariableName);

            foreach (var outSlot in asset.outputs)
            {
                arguments.Add(GetVariableNameForSlot(outSlot.id));
            }

            foreach (var feedbackSlot in asset.vtFeedbackVariables)
            {
                string feedbackVar = GetVariableNameForNode() + "_" + feedbackSlot;
                sb.AppendLine("{0} {1};", ConcreteSlotValueType.Vector4.ToShaderString(ConcretePrecision.Single), feedbackVar);
                arguments.Add(feedbackVar);
            }

            sb.AppendIndentation();
            sb.Append(asset.functionName);
            sb.Append("(");
            bool firstArg = true;

            foreach (var arg in arguments)
            {
                if (!firstArg)
                {
                    sb.Append(", ");
                }
                firstArg = false;
                sb.Append(arg);
            }
            sb.Append(");");
            sb.AppendNewLine();
        }