public MaterialDescription Run(MaterialDescription material, UDirectory materialPath, PixelFormat outputFormat = PixelFormat.ETC1) { if (material == null) throw new ArgumentNullException("material"); var assetManager = new AssetManager(); var modifiedMaterial = material.Clone(); var textureVisitor = new MaterialTextureVisitor(modifiedMaterial); var nodeReplacer = new MaterialNodeReplacer(modifiedMaterial); var textureNodes = textureVisitor.GetAllModelTextureValues(); foreach (var textureNode in textureNodes) { var itemAsset = assetSession.FindAsset(textureNode.TextureReference.Id); if(itemAsset == null) throw new InvalidOperationException("The referenced texture is not included in the project session."); var textureAsset = (TextureAsset)itemAsset.Asset; if (textureAsset.Format != TextureFormat.Compressed || textureAsset.Alpha == AlphaFormat.None) continue; // the texture has no alpha so there is no need to divide the texture into two sub-textures var originalLocation = textureNode.TextureReference.Location; throw new NotImplementedException("TODO: Need to reimplement this with removed data layer."); using (var image = assetManager.Load<Image>(originalLocation)) { CreateAndSaveSeparateTextures(image, originalLocation, textureAsset.GenerateMipmaps, outputFormat); assetManager.Unload(image); // matching unload to the previous asset manager load call } // make new tree var colorNode = new MaterialTextureNode(GenerateColorTextureURL(originalLocation), textureNode.TexcoordIndex, Vector2.One, Vector2.Zero); var alphaNode = new MaterialTextureNode(GenerateAlphaTextureURL(originalLocation), textureNode.TexcoordIndex, Vector2.One, Vector2.Zero); var substituteAlphaNode = new MaterialShaderClassNode { MixinReference = new AssetReference<EffectShaderAsset>(Guid.Empty, "ComputeColorSubstituteAlphaWithColor") }; substituteAlphaNode.CompositionNodes.Add("color1", colorNode); substituteAlphaNode.CompositionNodes.Add("color2", alphaNode); // set the parameters of the children so that they match the original texture var children = new[] { colorNode, alphaNode }; foreach (var childTexture in children) { childTexture.Sampler.AddressModeU = textureNode.Sampler.AddressModeU; childTexture.Sampler.AddressModeV = textureNode.Sampler.AddressModeV; childTexture.Sampler.Filtering = textureNode.Sampler.Filtering; childTexture.Offset = textureNode.Offset; childTexture.Sampler.SamplerParameterKey = textureNode.Sampler.SamplerParameterKey; childTexture.Scale = textureNode.Scale; childTexture.TexcoordIndex = textureNode.TexcoordIndex; } // copy the parameter key on the color and let the one of the alpha null so that it is set automatically to available value later colorNode.Key = textureNode.Key; alphaNode.Key = null; // update all the material references to the new node nodeReplacer.Replace(textureNode, substituteAlphaNode); } return modifiedMaterial; }
public MaterialDescription Run(MaterialDescription material, UDirectory materialPath, PixelFormat outputFormat = PixelFormat.ETC1) { if (material == null) { throw new ArgumentNullException("material"); } var assetManager = new AssetManager(); var modifiedMaterial = material.Clone(); var textureVisitor = new MaterialTextureVisitor(modifiedMaterial); var nodeReplacer = new MaterialNodeReplacer(modifiedMaterial); var textureNodes = textureVisitor.GetAllModelTextureValues(); foreach (var textureNode in textureNodes) { var itemAsset = assetSession.FindAsset(textureNode.TextureReference.Id); if (itemAsset == null) { throw new InvalidOperationException("The referenced texture is not included in the project session."); } var textureAsset = (TextureAsset)itemAsset.Asset; if (textureAsset.Format != TextureFormat.Compressed || textureAsset.Alpha == AlphaFormat.None) { continue; // the texture has no alpha so there is no need to divide the texture into two sub-textures } var originalLocation = textureNode.TextureReference.Location; throw new NotImplementedException("TODO: Need to reimplement this with removed data layer."); using (var image = assetManager.Load <Image>(originalLocation)) { CreateAndSaveSeparateTextures(image, originalLocation, textureAsset.GenerateMipmaps, outputFormat); assetManager.Unload(image); // matching unload to the previous asset manager load call } // make new tree var colorNode = new MaterialTextureNode(GenerateColorTextureURL(originalLocation), textureNode.TexcoordIndex, Vector2.One, Vector2.Zero); var alphaNode = new MaterialTextureNode(GenerateAlphaTextureURL(originalLocation), textureNode.TexcoordIndex, Vector2.One, Vector2.Zero); var substituteAlphaNode = new MaterialShaderClassNode { MixinReference = new AssetReference <EffectShaderAsset>(Guid.Empty, "ComputeColorSubstituteAlphaWithColor") }; substituteAlphaNode.CompositionNodes.Add("color1", colorNode); substituteAlphaNode.CompositionNodes.Add("color2", alphaNode); // set the parameters of the children so that they match the original texture var children = new[] { colorNode, alphaNode }; foreach (var childTexture in children) { childTexture.Sampler.AddressModeU = textureNode.Sampler.AddressModeU; childTexture.Sampler.AddressModeV = textureNode.Sampler.AddressModeV; childTexture.Sampler.Filtering = textureNode.Sampler.Filtering; childTexture.Offset = textureNode.Offset; childTexture.Sampler.SamplerParameterKey = textureNode.Sampler.SamplerParameterKey; childTexture.Scale = textureNode.Scale; childTexture.TexcoordIndex = textureNode.TexcoordIndex; } // copy the parameter key on the color and let the one of the alpha null so that it is set automatically to available value later colorNode.Key = textureNode.Key; alphaNode.Key = null; // update all the material references to the new node nodeReplacer.Replace(textureNode, substituteAlphaNode); } return(modifiedMaterial); }
/// <summary> /// Build the ShaderMixinSource to evaluate the binaryNode. /// </summary> /// <param name="node">The MaterialShaderClassNode binaryNode used as source to find the ShaderMixinSource.</param> /// <returns>The corresponding ShaderMixinSource.</returns> private ShaderSource GetShaderSource(MaterialShaderClassNode node) { if (!node.MixinReference.HasLocation()) { return(new ShaderClassSource("ComputeColor")); } var mixinName = Path.GetFileNameWithoutExtension(node.MixinReference.Location); object[] generics = null; if (node.Generics.Count > 0) { // TODO: correct generic order var mixinGenerics = new List <object>(); foreach (var genericKey in node.Generics.Keys) { var generic = node.Generics[genericKey]; if (generic is NodeParameterTexture) { var textureReference = ((NodeParameterTexture)generic).Reference; var foundNode = Material.FindNode(textureReference); while (foundNode != null && !(foundNode is MaterialTextureNode)) { var refNode = foundNode as MaterialReferenceNode; if (refNode == null) { break; } foundNode = Material.FindNode(refNode.Name); } var foundTextureNode = foundNode as MaterialTextureNode; if (foundTextureNode == null || foundTextureNode.UsedParameterKey == null) { Logger.Warning("[Material] The generic texture reference in node [" + node + "] is incorrect."); mixinGenerics.Add("Texturing.Texture0"); } else { mixinGenerics.Add(foundTextureNode.UsedParameterKey.ToString()); } } else if (generic is NodeParameterSampler) { var pk = ((NodeParameterSampler)generic).SamplerParameterKey; if (pk == null) { Logger.Warning("[Material] The generic sampler reference in node [" + node + "] is incorrect."); mixinGenerics.Add("Texturing.Sampler"); } else { mixinGenerics.Add(pk.ToString()); } } else if (generic is NodeParameterFloat) { mixinGenerics.Add(((NodeParameterFloat)generic).Value.ToString(CultureInfo.InvariantCulture)); } else if (generic is NodeParameterInt) { mixinGenerics.Add(((NodeParameterInt)generic).Value.ToString(CultureInfo.InvariantCulture)); } else if (generic is NodeParameterFloat2) { mixinGenerics.Add(GetAsShaderString(((NodeParameterFloat2)generic).Value)); } else if (generic is NodeParameterFloat3) { mixinGenerics.Add(GetAsShaderString(((NodeParameterFloat3)generic).Value)); } else if (generic is NodeParameterFloat4) { mixinGenerics.Add(GetAsShaderString(((NodeParameterFloat4)generic).Value)); } else if (generic is NodeParameter) { mixinGenerics.Add(((NodeParameter)generic).Reference); } else { throw new Exception("[Material] Unknown node type: " + generic.GetType()); } } generics = mixinGenerics.ToArray(); } var shaderClassSource = new ShaderClassSource(mixinName, generics); if (node.CompositionNodes.Count == 0) { return(shaderClassSource); } var mixin = new ShaderMixinSource(); mixin.Mixins.Add(shaderClassSource); foreach (var comp in node.CompositionNodes) { if (comp.Value != null) { var compShader = GetShaderSource(comp.Value); if (compShader != null) { mixin.Compositions.Add(comp.Key, compShader); } } } return(mixin); }