Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
TextureAlphaComponentSplitter.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 
5 using SiliconStudio.Assets;
6 using SiliconStudio.Core.IO;
7 using SiliconStudio.Core.Mathematics;
8 using SiliconStudio.Core.Serialization.Assets;
9 using SiliconStudio.Paradox.Assets.Effect;
10 using SiliconStudio.Paradox.Assets.Materials.Nodes;
11 using SiliconStudio.Paradox.Assets.Materials.Processor.Visitors;
12 using SiliconStudio.Paradox.Assets.Texture;
13 using SiliconStudio.Paradox.Graphics;
14 using SiliconStudio.TextureConverter;
15 
16 namespace SiliconStudio.Paradox.Assets.Materials
17 {
18  /// <summary>
19  /// Utility class to split this material texture containing alpha into two texture materials: one containing the rgb component and one containing only the alpha component.
20  /// More concretely, the class create the color channel and alpha channel textures from the original color/alpha texture
21  /// and replace the Material Texture Reference nodes containing an alpha component by a sub tree where:
22  /// - the parent is a binary operator <see cref="MaterialBinaryOperand.SubstituteAlpha"/>
23  /// - the left child is a Material Texture reference containing the color
24  /// - the right child is a Material Texture reference containing the alpha
25  /// </summary>
26  /// <remarks>Currently the output formats of the color and alpha textures are hard coded for android.</remarks>
28  {
29  public const string SplittedTextureNamePrefix = "__splitted_textures__";
30  public const string SplittedColorTextureNameSuffix = "__Color";
31  public const string SplittedAlphaTextureNameSuffix = "__Alpha";
32 
33  /// <summary>
34  /// The session containing all the texture references.
35  /// </summary>
36  private readonly PackageSession assetSession;
37 
39  {
40  this.assetSession = assetSession;
41  }
42 
43  public MaterialDescription Run(MaterialDescription material, UDirectory materialPath, PixelFormat outputFormat = PixelFormat.ETC1)
44  {
45  if (material == null) throw new ArgumentNullException("material");
46 
47  var assetManager = new AssetManager();
48  var modifiedMaterial = material.Clone();
49  var textureVisitor = new MaterialTextureVisitor(modifiedMaterial);
50  var nodeReplacer = new MaterialNodeReplacer(modifiedMaterial);
51  var textureNodes = textureVisitor.GetAllModelTextureValues();
52 
53  foreach (var textureNode in textureNodes)
54  {
55  var itemAsset = assetSession.FindAsset(textureNode.TextureReference.Id);
56  if(itemAsset == null)
57  throw new InvalidOperationException("The referenced texture is not included in the project session.");
58 
59  var textureAsset = (TextureAsset)itemAsset.Asset;
60  if (textureAsset.Format != TextureFormat.Compressed || textureAsset.Alpha == AlphaFormat.None)
61  continue; // the texture has no alpha so there is no need to divide the texture into two sub-textures
62 
63  var originalLocation = textureNode.TextureReference.Location;
64 
65  using (var image = assetManager.Load<Image>(originalLocation))
66  {
67  CreateAndSaveSeparateTextures(image, originalLocation, textureAsset.GenerateMipmaps, outputFormat);
68  assetManager.Unload(image); // matching unload to the previous asset manager load call
69  }
70 
71  // make new tree
72  var colorNode = new MaterialTextureNode(GenerateColorTextureURL(originalLocation), textureNode.TexcoordIndex, Vector2.One, Vector2.Zero);
73  var alphaNode = new MaterialTextureNode(GenerateAlphaTextureURL(originalLocation), textureNode.TexcoordIndex, Vector2.One, Vector2.Zero);
74  var substituteAlphaNode = new MaterialShaderClassNode { MixinReference = new AssetReference<EffectShaderAsset>(Guid.Empty, "ComputeColorSubstituteAlphaWithColor") };
75  substituteAlphaNode.CompositionNodes.Add("color1", colorNode);
76  substituteAlphaNode.CompositionNodes.Add("color2", alphaNode);
77 
78  // set the parameters of the children so that they match the original texture
79  var children = new[] { colorNode, alphaNode };
80  foreach (var childTexture in children)
81  {
82  childTexture.Sampler.AddressModeU = textureNode.Sampler.AddressModeU;
83  childTexture.Sampler.AddressModeV = textureNode.Sampler.AddressModeV;
84  childTexture.Sampler.Filtering = textureNode.Sampler.Filtering;
85  childTexture.Offset = textureNode.Offset;
86  childTexture.Sampler.SamplerParameterKey = textureNode.Sampler.SamplerParameterKey;
87  childTexture.Scale = textureNode.Scale;
88  childTexture.TexcoordIndex = textureNode.TexcoordIndex;
89  }
90 
91  // 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
92  colorNode.Key = textureNode.Key;
93  alphaNode.Key = null;
94 
95  // update all the material references to the new node
96  nodeReplacer.Replace(textureNode, substituteAlphaNode);
97  }
98 
99  return modifiedMaterial;
100  }
101 
102  public static string GenerateAlphaTextureURL(UFile originalLocation)
103  {
104  return GenerateSeparateTextureURL(originalLocation, SplittedAlphaTextureNameSuffix);
105  }
106 
107  public static string GenerateColorTextureURL(UFile originalLocation)
108  {
109  return GenerateSeparateTextureURL(originalLocation, SplittedColorTextureNameSuffix);
110  }
111 
112  private static string GenerateSeparateTextureURL(UFile originalLocation, string suffixName)
113  {
114  return originalLocation.GetDirectory() + "/" + SplittedTextureNamePrefix + originalLocation.GetFileName() + suffixName;
115  }
116 
117  public static void CreateAndSaveSeparateTextures(Image image, string originalTextureURL, bool shouldGenerateMipMaps, PixelFormat outputFormat = PixelFormat.ETC1)
118  {
119  using (var texTool = new TextureTool())
120  using (var texImage = texTool.Load(image))
121  {
122  CreateAndSaveSeparateTextures(texTool, texImage, originalTextureURL, shouldGenerateMipMaps, outputFormat);
123  }
124  }
125  public static void CreateAndSaveSeparateTextures(TextureTool texTool, TexImage texImage, string originalTextureURL, bool shouldGenerateMipMaps, PixelFormat outputFormat = PixelFormat.ETC1)
126  {
127  var assetManager = new AssetManager();
128  var alphaTextureURL = GenerateAlphaTextureURL(originalTextureURL);
129  var colorTextureURL = GenerateColorTextureURL(originalTextureURL);
130 
131  // create a new image containing only the alpha component
132  texTool.Decompress(texImage);
133  using (var alphaImage = texTool.CreateImageFromAlphaComponent(texImage))
134  {
135  // generate the mip-maps for the alpha component if required
136  if (shouldGenerateMipMaps)
137  texTool.GenerateMipMaps(alphaImage, Filter.MipMapGeneration.Box);
138 
139  // save the alpha component
140  texTool.Compress(alphaImage, outputFormat);
141  using (var outputImage = texTool.ConvertToParadoxImage(alphaImage))
142  assetManager.Save(alphaTextureURL, outputImage);
143  }
144 
145  // save the color component
146  texTool.Decompress(texImage);
147  texTool.Compress(texImage, outputFormat);
148  using (var outputImage = texTool.ConvertToParadoxImage(texImage))
149  assetManager.Save(colorTextureURL, outputImage);
150  }
151  }
152 }
static void CreateAndSaveSeparateTextures(TextureTool texTool, TexImage texImage, string originalTextureURL, bool shouldGenerateMipMaps, PixelFormat outputFormat=PixelFormat.ETC1)
static void CreateAndSaveSeparateTextures(Image image, string originalTextureURL, bool shouldGenerateMipMaps, PixelFormat outputFormat=PixelFormat.ETC1)
static readonly Vector2 Zero
A SiliconStudio.Core.Mathematics.Vector2 with all of its components set to zero.
Definition: Vector2.cs:52
Represents a two dimensional mathematical vector.
Definition: Vector2.cs:42
Provides method to load images or textures, to modify them and to convert them with different texture...
Definition: TextureTool.cs:24
Provides method to instantiate an image 1D/2D/3D supporting TextureArray and mipmaps on the CPU or to...
Definition: Image.cs:88
Utility class to split this material texture containing alpha into two texture materials: one contain...
A session for editing a package.
static readonly Vector2 One
A SiliconStudio.Core.Mathematics.Vector2 with all of its components set to one.
Definition: Vector2.cs:67
Defines a normalized directory path. See UPath for details. This class cannot be inherited.
Definition: UDirectory.cs:13
string GetFileName()
Gets the name of the file without its extension. Can be null.
Definition: UFile.cs:75
Temporary format containing texture data and information. Used as buffer between texture libraries...
Definition: TexImage.cs:13
MaterialDescription Run(MaterialDescription material, UDirectory materialPath, PixelFormat outputFormat=PixelFormat.ETC1)
PixelFormat
Defines various types of pixel formats.
Definition: PixelFormat.cs:32
Defines a normalized file path. See UPath for details. This class cannot be inherited.
Definition: UFile.cs:13