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);
        }
Exemple #3
0
        /// <summary>
        /// Performs the maximal reduction.
        /// </summary>
        //public Dictionary<UFile, Image> Run(EffectCompilerBase compiler)
        public bool Run(EffectCompilerBase compiler)
        {
            var result = true;

            if (commandList.Count > 0)
            {
                if (plane == null)
                {
                    plane = GeometricPrimitive.Plane.New(graphicsDevice, 2.0f, 2.0f);
                }

                var assetManager = new AssetManager();
                assetManager.Serializer.RegisterSerializer(new GpuTextureSerializer2(graphicsDevice));

                var textures = new Dictionary <string, Graphics.Texture>();
                var materialTreeShaderCreator = new MaterialTreeShaderCreator(Material);
                var textureVisitor            = new MaterialTextureVisitor(Material);
                var compilerParameters        = new CompilerParameters {
                    Platform = GraphicsPlatform.Direct3D11, Profile = GraphicsProfile.Level_11_0
                };

                foreach (var command in commandList)
                {
                    var computeColorShader = materialTreeShaderCreator.GenerateShaderForReduction(command.OldNode);
                    if (computeColorShader == null)
                    {
                        continue;
                    }

                    var finalShader = new ShaderMixinSource();
                    finalShader.Mixins.Add(new ShaderClassSource("FlattenLayers"));
                    finalShader.Compositions.Add("outColor", computeColorShader);
                    var results = compiler.Compile(finalShader, compilerParameters);

                    if (results.HasErrors)
                    {
                        continue;
                    }

                    command.TreeEffect = new Graphics.Effect(graphicsDevice, results.MainBytecode, results.MainUsedParameters);
                    command.Parameters = new ParameterCollection();
                    var maxWidth    = 0;
                    var maxHeight   = 0;
                    var allTextures = textureVisitor.GetAllTextureValues(command.OldNode);
                    foreach (var texSlot in allTextures)
                    {
                        Graphics.Texture tex;
                        if (!textures.TryGetValue(texSlot.TextureName, out tex))
                        {
                            //TODO: change load so that texture can be unloaded.
                            tex = assetManager.Load <Graphics.Texture>(texSlot.TextureName);
                            textures.Add(texSlot.TextureName, tex);
                        }

                        if (tex == null)
                        {
                            throw new FileNotFoundException("Texture " + texSlot.TextureName + " not found");
                        }

                        command.Parameters.Set(texSlot.UsedParameterKey, tex);
                        maxWidth  = Math.Max(maxWidth, tex.ViewWidth);
                        maxHeight = Math.Max(maxHeight, tex.ViewHeight);
                        // can take min, a user-defined size, or clamp the min/max
                        // exclude mask?
                    }

                    command.RenderTarget = Graphics.Texture.New2D(graphicsDevice, maxWidth, maxHeight, PixelFormat.R8G8B8A8_UNorm, TextureFlags.ShaderResource | TextureFlags.RenderTarget);
                    command.ToExecute    = true;
                }

                // remove wrong commands
                commandList.RemoveAll(x => !x.ToExecute);

                var nodeReplacer = new MaterialNodeReplacer(Material);

                foreach (var command in commandList.Where(x => x.ToExecute))
                {
                    lock (graphicsDevice)
                    {
                        graphicsDevice.Clear(command.RenderTarget, Color4.Black);
                        graphicsDevice.SetRenderTarget(command.RenderTarget);

                        graphicsDevice.SetRasterizerState(graphicsDevice.RasterizerStates.CullNone);
                        graphicsDevice.SetDepthStencilState(graphicsDevice.DepthStencilStates.None);

                        command.TreeEffect.Apply(command.Parameters);
                        plane.Draw();

                        // save texture
                        SaveTexture(command.RenderTarget, command.TextureUrl, assetManager);
                    }
                    // make new tree
                    var newNode = new MaterialTextureNode(command.TextureUrl.FullPath, command.TexcoordIndex, Vector2.One, Vector2.Zero);

                    nodeReplacer.Replace(command.OldNode, newNode);

                    // save new material?
                    command.ToExecute = false;
                }

                foreach (var command in commandList)
                {
                    command.TreeEffect.Dispose();
                    command.RenderTarget.Dispose();
                }

                foreach (var texture in textures)
                {
                    texture.Value.Dispose();
                }
                textures.Clear();

                foreach (var tex in textures)
                {
                    assetManager.Unload(tex);
                }

                textures.Clear();
                result = commandList.All(x => !x.ToExecute);
                commandList.Clear();
            }

            return(result);
        }