/// <summary> /// Build the ShaderMixinSource to evaluate the binaryNode. /// </summary> /// <param name="node">The MaterialTextureNode binaryNode used as source to find the ShaderMixinSource.</param> /// <returns>The corresponding ShaderMixinSource.</returns> private ShaderSource GetShaderSource(MaterialTextureNode node) { string usedTexcoord; if (shaderForReduction) { usedTexcoord = "TEXCOORD0"; } else { usedTexcoord = "TEXCOORD" + GetTextureIndex(node.TexcoordIndex); } // "TTEXTURE", "TStream" ShaderClassSource shaderSource; if (displacementShader) { shaderSource = new ShaderClassSource("ComputeColorTextureDisplacement", node.UsedParameterKey, usedTexcoord); } else if (node.Offset != Vector2.Zero) { shaderSource = new ShaderClassSource("ComputeColorTextureScaledOffsetSampler", node.UsedParameterKey, usedTexcoord, GetAsShaderString(node.Scale), GetAsShaderString(node.Offset), node.Sampler.SamplerParameterKey); } else if (node.Scale != Vector2.One) { shaderSource = new ShaderClassSource("ComputeColorTextureScaledSampler", node.UsedParameterKey, usedTexcoord, GetAsShaderString(node.Scale), node.Sampler.SamplerParameterKey); } else { shaderSource = new ShaderClassSource("ComputeColorTextureSampler", node.UsedParameterKey, usedTexcoord, node.Sampler.SamplerParameterKey); } return(shaderSource); }
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> /// 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); }
private bool IsTextureReferenceValid(MaterialTextureNode node) { return(assetItem.Package.Session.FindAsset(node.TextureReference.Location) != null); }