Beispiel #1
0
 /// <summary>
 /// Add a node to the list of of nodes to reduce.
 /// </summary>
 /// <param name="node">The node to add.</param>
 /// <param name="reduceList">The list of node to reduce.</param>
 private static void AddNodeToReduceList(IMaterialNode node, List <IMaterialNode> reduceList)
 {
     if (!(node is IMaterialValueNode || node is MaterialTextureNode || node is MaterialShaderClassNode))
     {
         reduceList.Add(node);
     }
 }
        /// <summary>
        /// Gather all the textures in the node hierarchy, even the ones behind the generics.
        /// </summary>
        /// <param name="node">The node to look into.</param>
        /// <returns>A collection of MaterialTextureNode.</returns>
        private IEnumerable <MaterialTextureNode> GatherTextureValuesWithGenerics(IMaterialNode node)
        {
            var materialContext = new MaterialContext {
                Material = Material, ExploreGenerics = true
            };

            return(GatherTextures(node, materialContext));
        }
 /// <summary>
 /// Inserts a new tree in the material
 /// </summary>
 /// <param name="referenceName">The name of the reference.</param>
 /// <param name="node">The material onde.</param>
 public void AddNode(string referenceName, IMaterialNode node)
 {
     if (Nodes.ContainsKey(referenceName))
     {
         throw new Exception("A reference with name " + referenceName + " already exists");
     }
     Nodes.Add(referenceName, node);
 }
 public static void VisitNodes(this IMaterialNode node, Action <object, MaterialNodeEntry> callback, object context = null)
 {
     if (callback == null)
     {
         throw new ArgumentNullException("callback");
     }
     VisitNode(new MaterialNodeEntry(node, DoNothing), callback, context);
 }
Beispiel #5
0
 /// <summary>
 /// Initializes a new instance of the <see cref="MaterialNodeEntry"/> struct.
 /// </summary>
 /// <param name="node">The node.</param>
 /// <param name="setter">The setter.</param>
 /// <exception cref="System.ArgumentNullException">setter</exception>
 public MaterialNodeEntry(IMaterialNode node, Action <IMaterialNode> setter)
 {
     if (setter == null)
     {
         throw new ArgumentNullException("setter");
     }
     this.node   = node;
     this.setter = setter;
 }
Beispiel #6
0
        /// <summary>
        /// Generate one shader.
        /// </summary>
        public ShaderMixinSource GenerateShaderForReduction(IMaterialNode materialNode)
        {
            shaderForReduction = true;

            var textureVisitor = new MaterialTextureVisitor(Material);
            var allTextures    = textureVisitor.GetAllTextureValues(materialNode);

            textureVisitor.AssignDefaultTextureKeys(allTextures.Distinct(), null);
            return(GetShaderMixinSource(GetShaderSource(materialNode)));
        }
 /// <summary>
 /// Replace all occurences of a node in a tree.
 /// </summary>
 public void Replace(IMaterialNode nodeToReplace, IMaterialNode replacementNode)
 {
     Material.VisitNodes((context, nodeEntry) =>
     {
         if (ReferenceEquals(nodeEntry.Node, nodeToReplace))
         {
             nodeEntry.Node = replacementNode;
         }
     });
 }
Beispiel #8
0
 /// <inheritdoc/>
 public override IEnumerable <MaterialNodeEntry> GetChildren(object context = null)
 {
     if (LeftChild != null)
     {
         yield return(new MaterialNodeEntry(LeftChild, node => LeftChild = node));
     }
     if (RightChild != null)
     {
         yield return(new MaterialNodeEntry(RightChild, node => RightChild = node));
     }
 }
Beispiel #9
0
        /// <summary>
        /// Get the list of all the reducible sub-trees for this tree. If a tree is entirely reducible, only the rootnode will appear
        /// </summary>
        /// <returns>The list of all the reducible sub-trees</returns>
        public List <IMaterialNode> GetReducibleSubTrees(IMaterialNode node)
        {
            var resultList = new List <IMaterialNode>();
            var criterion  = new ReductionCriteria {
                TexcoordIndex = TextureCoordinate.TexcoordNone
            };

            if (BuildReducibleSubTreesList(node, resultList, out criterion))
            {
                AddNodeToReduceList(node, resultList);
            }
            return(resultList);
        }
        /// <summary>
        /// Common gather texture function.
        /// </summary>
        /// <param name="node">The node to look into.</param>
        /// <param name="materialContext">The visitor context.</param>
        /// <returns>A collection of MaterialTextureNode.</returns>
        private IEnumerable <MaterialTextureNode> GatherTextures(IMaterialNode node, MaterialContext materialContext)
        {
            var textureValues = new List <MaterialTextureNode>();

            node.VisitNodes((context, nodeEntry) =>
            {
                var textureValue = nodeEntry.Node as MaterialTextureNode;
                if (textureValue != null)
                {
                    textureValues.Add(textureValue);
                }
            }, materialContext);
            return(textureValues);
        }
        /// <summary>
        /// Test if the tree can be reduced to a single texture or color.
        /// </summary>
        /// <param name="node">The node to explore.</param>
        /// <param name="texcoord">The unique texcoord if applicable.</param>
        /// <returns>A boolean stating this test.</returns>
        public bool HasUniqueTexcoord(IMaterialNode node, out TextureCoordinate texcoord)
        {
            var allTextures = GatherTextureValues(node).Distinct().ToList();

            texcoord = TextureCoordinate.TexcoordNone;

            foreach (var texSlot in allTextures)
            {
                if (texcoord == TextureCoordinate.TexcoordNone)
                {
                    texcoord = texSlot.TexcoordIndex;
                }

                if (texcoord != texSlot.TexcoordIndex)
                {
                    return(false);
                }
            }
            return(true);
        }
        /// <summary>
        /// Create a reference to a node.
        /// </summary>
        /// <param name="node">The material node.</param>
        /// <param name="referenceName">The name of the reference.</param>
        public void MakeReference(IMaterialNode node, string referenceName)
        {
            IMaterialNode prevNode;

            if (Nodes.TryGetValue(referenceName, out prevNode))
            {
                if (!ReferenceEquals(node, prevNode))
                {
                    throw new Exception("Unable to create a reference with the name " + referenceName + " because there is already a reference with that name.");
                }
            }
            else
            {
                var matReference = new MaterialReferenceNode(referenceName);
                foreach (var tree in Nodes.Select(x => x.Value))
                {
                    //var replacer = new MaterialNodeReplacer.
                }
                Nodes.Add(referenceName, node);
            }
        }
Beispiel #13
0
        /// <summary>
        /// Gather all the parameters in the node hierarchy.
        /// </summary>
        /// <param name="node">The node to look into.</param>
        /// <param name="parameters">The parameter collection to fill.</param>
        private void GetParametersFromNode(IMaterialNode node, ParameterCollectionData parameters)
        {
            if (node == null)
            {
                return;
            }

            node.VisitNodes((context, nodeEntry) =>
            {
                var shaderNode = nodeEntry.Node as MaterialShaderClassNode;
                if (shaderNode != null)
                {
                    //foreach (var member in shaderNode.Members)
                    foreach (var member in shaderNode.GetParameters(context))
                    {
                        parameters.Set(member.Key, member.Value);
                    }
                }
            }, new MaterialContext {
                Material = Material, ExploreGenerics = false
            });
        }
Beispiel #14
0
        /// <summary>
        /// Reduce the binaryNode to its most compact form.
        /// </summary>
        /// <param name="node">The IMaterialNode binaryNode to reduce.</param>
        /// <returns>The reduced binaryNode.</returns>
        private IMaterialNode Reduce(IMaterialNode node)
        {
            if (node is MaterialBinaryNode)
            {
                return(Reduce(node as MaterialBinaryNode));
            }
            if (node is MaterialReferenceNode)
            {
                var referenceName = (node as MaterialReferenceNode).Name;
                if (referenceName != null)
                {
                    BeginReduction(referenceName);

                    if (ReducedTrees.ContainsKey(referenceName))
                    {
                        return(ReducedTrees[referenceName]);
                    }

                    return(null);
                }
            }
            return(node);
        }
        /// <summary>
        /// Assign the Keys to the textures in the tree.
        /// </summary>
        /// <param name="node">The node to look into.</param>
        /// <param name="getTextureKey">The delegate function to get the correct key.</param>
        private void AssignParameterKeys(IMaterialNode node, TextureKeyGetter getTextureKey)
        {
            var allTextures = GatherTextureValues(node).Distinct().ToList();
            var textureKeys = new Dictionary <string, ParameterKey <Graphics.Texture> >();

            foreach (var texSlot in allTextures)
            {
                //TODO: compare texture sampling method
                ParameterKey <Graphics.Texture> pk;
                var textureName = texSlot.TextureName;
                if (textureName == null || !textureKeys.TryGetValue(textureName, out pk))
                {
                    pk = getTextureKey(this);
                    if (textureName != null)
                    {
                        textureKeys.Add(textureName, pk);
                    }
                }

                texSlot.UsedParameterKey            = pk;
                texSlot.Sampler.SamplerParameterKey = TexturingKeys.Sampler;
            }
        }
        /// <summary>
        /// Gather all the sampler generics in the node hierarchy.
        /// </summary>
        /// <param name="node">The node to look into.</param>
        /// <returns>A collection of NodeParameterSampler.</returns>
        private IEnumerable <NodeParameterSampler> GatherSamplerValues(IMaterialNode node)
        {
            var samplerValues = new List <NodeParameterSampler>();

            node.VisitNodes((context, nodeEntry) =>
            {
                var shaderClassNode = nodeEntry.Node as MaterialShaderClassNode;
                if (shaderClassNode != null)
                {
                    foreach (var gen in shaderClassNode.Generics)
                    {
                        var genSampler = gen.Value as NodeParameterSampler;
                        if (genSampler != null)
                        {
                            samplerValues.Add(genSampler);
                        }
                    }
                }
            }, new MaterialContext {
                Material = Material, ExploreGenerics = false
            });
            return(samplerValues);
        }
Beispiel #17
0
 /// <summary>
 /// Initializes a new instance of the <see cref="MaterialBinaryNode"/> class.
 /// </summary>
 /// <param name="leftChild">The left child.</param>
 /// <param name="rightChild">The right child.</param>
 /// <param name="materialBinaryOperand">The material binary operand.</param>
 public MaterialBinaryNode(IMaterialNode leftChild, IMaterialNode rightChild, MaterialBinaryOperand materialBinaryOperand)
 {
     LeftChild  = leftChild;
     RightChild = rightChild;
     Operand    = materialBinaryOperand;
 }
 private static void DoNothing(IMaterialNode node)
 {
 }
Beispiel #19
0
        /// <summary>
        /// Checks if the node can be reduced and adds to the list the ones that cannot be reduced further.
        /// </summary>
        /// <param name="node">The node to visit.</param>
        /// <param name="resultList">The list of node to reduce.</param>
        /// <param name="criterion">The current criteria to reduce the node.</param>
        /// <returns>True if the node can be reduced, false otherwise.</returns>
        private bool BuildReducibleSubTreesList(IMaterialNode node, List <IMaterialNode> resultList, out ReductionCriteria criterion)
        {
            if (node is IMaterialValueNode)
            {
                criterion.TexcoordIndex = node is MaterialTextureNode ? ((MaterialTextureNode)node).TexcoordIndex : TextureCoordinate.TexcoordNone;
                criterion.AddressModeU  = node is MaterialTextureNode ? ((MaterialTextureNode)node).Sampler.AddressModeU : (TextureAddressMode?)null;
                criterion.AddressModeV  = node is MaterialTextureNode ? ((MaterialTextureNode)node).Sampler.AddressModeV : (TextureAddressMode?)null;

                var isSingleReducible = node.IsReducible;
                if (node is MaterialFloatNode)
                {
                    isSingleReducible &= (((MaterialFloatNode)node).Key == null);
                }
                if (node is MaterialFloat4Node)
                {
                    isSingleReducible &= (((MaterialFloat4Node)node).Key == null);
                }
                if (node is MaterialColorNode)
                {
                    isSingleReducible &= (((MaterialColorNode)node).Key == null);
                }

                return(isSingleReducible);
            }

            var refNode = node as MaterialReferenceNode;

            if (refNode != null)
            {
                return(BuildReducibleSubTreesList(Material.FindNode(refNode.Name), resultList, out criterion));
            }

            criterion.TexcoordIndex = TextureCoordinate.TexcoordNone;
            criterion.AddressModeU  = (TextureAddressMode?)null;
            criterion.AddressModeV  = (TextureAddressMode?)null;

            bool?checkIsReducible            = null;
            ReductionCriteria?checkCriterion = null;
            var reducibleNodes = new List <IMaterialNode>();

            foreach (var subNodeIt in node.GetChildren(Material))
            {
                var subNode = subNodeIt.Node;
                ReductionCriteria childCriterion;
                var childIsReducible = BuildReducibleSubTreesList(subNode, resultList, out childCriterion);
                if (!checkIsReducible.HasValue)
                {
                    checkIsReducible = childIsReducible;
                    checkCriterion   = childCriterion;
                }
                else
                {
                    checkIsReducible = checkIsReducible.Value && childIsReducible && CompatibleCriteria(childCriterion, checkCriterion.Value);
                    checkCriterion   = MergeCriteria(checkCriterion.Value, childCriterion);
                }

                if (childIsReducible)
                {
                    reducibleNodes.Add(subNode);
                }
            }

            if (checkCriterion.HasValue)
            {
                criterion = checkCriterion.Value;
            }

            if (checkIsReducible.HasValue && !checkIsReducible.Value)
            {
                // if one child is not reducible, add all the reducible ones to the list
                foreach (var reducibleNode in reducibleNodes)
                {
                    AddNodeToReduceList(reducibleNode, resultList);
                }

                return(false);
            }

            return(node.IsReducible);
        }
        /// <summary>
        /// Adds a tree in the model.
        /// </summary>
        /// <param name="key">The key of the slot in the model.</param>
        /// <param name="referenceName">The name of the tree.</param>
        /// <param name="node">The node to add.</param>
        public void AddColorNode(ParameterKey <ShaderMixinSource> key, string referenceName, IMaterialNode node)
        {
            if (ColorNodes.ContainsKey(key))
            {
                ColorNodes[key] = referenceName;
            }
            else
            {
                ColorNodes.Add(key, referenceName);
            }

            AddNode(referenceName, node);
        }
 /// <summary>
 /// Assign the default texture keys to the texture slots.
 /// </summary>
 /// <param name="node">The node to look into.</param>
 public void AssignDefaultTextureKeys(IMaterialNode node)
 {
     AssignParameterKeys(node, GetNextDefaultTextureKey);
 }
 /// <summary>
 /// Get all the textures needed for this node.
 /// </summary>
 /// <param name="node">The node to explore.</param>
 /// <returns>The list containing all the textures.</returns>
 public List <NodeParameterSampler> GetAllSamplerValues(IMaterialNode node)
 {
     return(GatherSamplerValues(node).Distinct().ToList());
 }
 /// <summary>
 /// Assign the diffuse texture keys to the texture slots.
 /// </summary>
 /// <param name="node">The node to look into.</param>
 public void AssignDiffuseTextureKeys(IMaterialNode node)
 {
     AssignParameterKeys(node, GetNextDiffuseTextureKey);
 }
 /// <summary>
 /// Assign the specular texture keys to the texture slots.
 /// </summary>
 /// <param name="node">The node to look into.</param>
 public void AssignSpecularTextureKeys(IMaterialNode node)
 {
     AssignParameterKeys(node, GetNextSpecularTextureKey);
 }
 /// <summary>
 /// Assign the displacement texture keys to the texture slots.
 /// </summary>
 /// <param name="node">The node to look into.</param>
 public void AssignDisplacementTextureKeys(IMaterialNode node)
 {
     AssignParameterKeys(node, GetNextDisplacementTextureKey);
 }
 /// <summary>
 /// Assign the normal map texture keys to the texture slots.
 /// </summary>
 /// <param name="node">The node to look into.</param>
 public void AssignNormalMapTextureKeys(IMaterialNode node)
 {
     AssignParameterKeys(node, GetNextNormalMapTextureKey);
 }
 /// <summary>
 /// Get all the textures needed for this node with the potential generic parameters.
 /// </summary>
 /// <param name="node">The node to explore.</param>
 /// <returns>The list containing all the textures.</returns>
 public List <MaterialTextureNode> GetAllTextureValuesWithGenerics(IMaterialNode node)
 {
     return(GatherTextureValuesWithGenerics(node).Distinct().ToList());
 }
Beispiel #28
0
        /// <summary>
        /// Gets the shader source.
        /// </summary>
        /// <param name="node">The node to process.</param>
        /// <returns>The shader source.</returns>
        private ShaderSource GetShaderSource(IMaterialNode node)
        {
            if (node == null)
            {
                return(new ShaderClassSource("ComputeColor"));
            }

            if (node is MaterialFloatNode)
            {
                return(GetShaderSource(node as MaterialFloatNode));
            }
            if (node is MaterialFloat4Node)
            {
                return(GetShaderSource(node as MaterialFloat4Node));
            }
            if (node is MaterialColorNode)
            {
                return(GetShaderSource(node as MaterialColorNode));
            }
            if (node is MaterialTextureNode)
            {
                return(GetShaderSource(node as MaterialTextureNode));
            }
            if (node is MaterialShaderClassNode)
            {
                return(GetShaderSource(node as MaterialShaderClassNode));
            }
            if (node is MaterialBinaryNode)
            {
                return(GetShaderSource(node as MaterialBinaryNode));
            }
            if (node is MaterialReferenceNode)
            {
                var referenceName = (node as MaterialReferenceNode).Name;
                if (shaderForReduction)
                {
                    var refNode = Material.FindNode(referenceName);
                    return(GetShaderSource(refNode));
                }
                else
                {
                    if (referenceName == null)
                    {
                        Logger.Warning("[Material] The MaterialReferenceNode [" + node + "] doesn't reference anything.");
                        return(null);
                    }

                    BeginShaderCreation(referenceName, displacementShader);

                    ShaderSource shaderSource;
                    if (!ModelShaderSources.TryGetValue(referenceName, out shaderSource))
                    {
                        return(null);
                    }

                    return(shaderSource);
                }
            }

            // TODO: error?
            throw new Exception("[Material] An unsupported material node was encountered during shader creation.");
        }