Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
TextureCommandHelper.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 using System.Threading;
5 
6 using SiliconStudio.BuildEngine;
7 using SiliconStudio.Core;
8 using SiliconStudio.Core.Diagnostics;
9 using SiliconStudio.Core.IO;
10 using SiliconStudio.Core.Mathematics;
11 using SiliconStudio.Core.Serialization.Assets;
12 using SiliconStudio.Paradox.Assets.Materials;
13 using SiliconStudio.Paradox.Graphics;
14 using SiliconStudio.TextureConverter;
15 
16 namespace SiliconStudio.Paradox.Assets.Texture
17 {
18  /// <summary>
19  /// An helper for the compile commands that needs to process textures.
20  /// </summary>
21  public static class TextureCommandHelper
22  {
23  /// <summary>
24  /// Returns true if the provided int is a power of 2.
25  /// </summary>
26  /// <param name="x">the int value to test</param>
27  /// <returns>true if power of two</returns>
28  public static bool IsPowerOfTwo(int x)
29  {
30  return (x & (x - 1)) == 0;
31  }
32 
33  /// <summary>
34  /// Returns true if the PVRTC can be used for the provided texture size.
35  /// </summary>
36  /// <param name="textureSize">the size of the texture</param>
37  /// <returns>true if PVRTC is supported</returns>
38  public static bool SupportPVRTC(Int2 textureSize)
39  {
40  return textureSize.X == textureSize.Y && IsPowerOfTwo(textureSize.X);
41  }
42 
43  /// <summary>
44  /// Utility function to check that the texture size is supported on the graphics platform for the provided graphics profile.
45  /// </summary>
46  /// <param name="textureFormat">The desired type of format for the output texture</param>
47  /// <param name="textureSize">The size of the texture</param>
48  /// <param name="graphicsProfile">The graphics profile</param>
49  /// <param name="platform">The graphics platform</param>
50  /// <param name="generateMipmaps">Indicate if mipmaps should be generated for the output texture</param>
51  /// <param name="logger">The logger used to log messages</param>
52  /// <returns>true if the texture size is supported</returns>
53  public static bool TextureSizeSupported(TextureFormat textureFormat, GraphicsPlatform platform, GraphicsProfile graphicsProfile, Int2 textureSize, bool generateMipmaps, Logger logger)
54  {
55  // compressed DDS files has to have a size multiple of 4.
56  if (platform == GraphicsPlatform.Direct3D11 && textureFormat == TextureFormat.Compressed
57  && ((textureSize.X % 4) != 0 || (textureSize.Y % 4) != 0))
58  {
59  logger.Error("DDS compression does not support texture files that do not have a size multiple of 4." +
60  "Please disable texture compression or adjust your texture size to multiple of 4.");
61  return false;
62  }
63 
64  // determine if the desired size if valid depending on the graphics profile
65  switch (graphicsProfile)
66  {
67  case GraphicsProfile.Level_9_1:
68  case GraphicsProfile.Level_9_2:
69  case GraphicsProfile.Level_9_3:
70  if (generateMipmaps && (!IsPowerOfTwo(textureSize.Y) || !IsPowerOfTwo(textureSize.X)))
71  {
72  logger.Error("Graphic profiles 9.1/9.2/9.3 do not support mipmaps with textures that are not power of 2. " +
73  "Please disable mipmap generation, modify your texture resolution or upgrade your graphic profile to a value >= 10.0.");
74  return false;
75  }
76  break;
77  case GraphicsProfile.Level_10_0:
78  case GraphicsProfile.Level_10_1:
79  case GraphicsProfile.Level_11_0:
80  case GraphicsProfile.Level_11_1:
81  break;
82  default:
83  throw new ArgumentOutOfRangeException("graphicsProfile");
84  }
85 
86  return true;
87  }
88 
89  /// <summary>
90  /// Determine the output format of the texture depending on the platform and asset properties.
91  /// </summary>
92  /// <param name="textureFormat">The desired texture output format type</param>
93  /// <param name="graphicsPlatform">The graphics platform</param>
94  /// <param name="alphaFormat">The alpha format desired in output</param>
95  /// <param name="platform">The platform type</param>
96  /// <param name="imageSize">The texture output size</param>
97  /// <param name="inputImageFormat">The pixel format of the input image</param>
98  /// <returns>The pixel format to use as output</returns>
99  public static PixelFormat DetermineOutputFormat(TextureFormat textureFormat, AlphaFormat alphaFormat, PlatformType platform, GraphicsPlatform graphicsPlatform, Int2 imageSize, PixelFormat inputImageFormat)
100  {
101  PixelFormat outputFormat;
102  switch (textureFormat)
103  {
104  case TextureFormat.Compressed:
105  switch (platform)
106  {
107  case PlatformType.Android:
108  outputFormat = alphaFormat == AlphaFormat.None ? PixelFormat.ETC1 : PixelFormat.R8G8B8A8_UNorm;
109  break;
110 
111  case PlatformType.iOS:
112  // PVRTC works only for square POT textures
113  if (SupportPVRTC(imageSize))
114  {
115  switch (alphaFormat)
116  {
117  case AlphaFormat.None:
118  // DXT1 handles 1-bit alpha channel
119  outputFormat = PixelFormat.PVRTC_4bpp_RGB;
120  break;
121  case AlphaFormat.Mask:
122  // DXT1 handles 1-bit alpha channel
123  // TODO: Not sure about the equivalent here?
124  outputFormat = PixelFormat.PVRTC_4bpp_RGBA;
125  break;
126  case AlphaFormat.Explicit:
127  case AlphaFormat.Interpolated:
128  // DXT3 is good at sharp alpha transitions
129  // TODO: Not sure about the equivalent here?
130  outputFormat = PixelFormat.PVRTC_4bpp_RGBA;
131  break;
132  default:
133  throw new ArgumentOutOfRangeException();
134  }
135  }
136  else
137  {
138  outputFormat = PixelFormat.R8G8B8A8_UNorm;
139  }
140  break;
141  case PlatformType.Windows:
142  case PlatformType.WindowsPhone:
143  case PlatformType.WindowsStore:
144  switch (graphicsPlatform)
145  {
146  case GraphicsPlatform.Direct3D11:
147  switch (alphaFormat)
148  {
149  case AlphaFormat.None:
150  case AlphaFormat.Mask:
151  // DXT1 handles 1-bit alpha channel
152  outputFormat = PixelFormat.BC1_UNorm;
153  break;
154  case AlphaFormat.Explicit:
155  // DXT3 is good at sharp alpha transitions
156  outputFormat = PixelFormat.BC2_UNorm;
157  break;
158  case AlphaFormat.Interpolated:
159  // DXT5 is good at alpha gradients
160  outputFormat = PixelFormat.BC3_UNorm;
161  break;
162  default:
163  throw new ArgumentOutOfRangeException();
164  }
165  break;
166  default:
167  // OpenGL & OpenGL ES on Windows
168  // TODO: Need to handle OpenGL Desktop compression
169  outputFormat = PixelFormat.R8G8B8A8_UNorm;
170  break;
171  }
172  break;
173  default:
174  throw new NotSupportedException("Platform " + platform + " is not supported by TextureTool");
175  }
176  break;
177  case TextureFormat.HighColor:
178  if (alphaFormat == AlphaFormat.None)
179  outputFormat = PixelFormat.B5G6R5_UNorm;
180  else if (alphaFormat == AlphaFormat.Mask)
181  outputFormat = PixelFormat.B5G5R5A1_UNorm;
182  else
183  throw new NotImplementedException("This alpha format requires a TrueColor texture format.");
184  break;
185  case TextureFormat.TrueColor:
186  outputFormat = PixelFormat.R8G8B8A8_UNorm;
187  break;
188  //case TextureFormat.Custom:
189  // throw new NotSupportedException();
190  // break;
191  case TextureFormat.AsIs:
192  outputFormat = inputImageFormat;
193  break;
194  default:
195  throw new ArgumentOutOfRangeException();
196  }
197  return outputFormat;
198  }
199 
200  public static ResultStatus ImportAndSaveTextureImage(UFile sourcePath, string outputUrl, TextureAsset textureAsset, TextureConvertParameters parameters, bool separateAlpha, CancellationToken cancellationToken, Logger logger)
201  {
202  var assetManager = new AssetManager();
203 
204  using (var texTool = new TextureTool())
205  using (var texImage = texTool.Load(sourcePath))
206  {
207  // Apply transformations
208  texTool.Decompress(texImage);
209 
210  if (cancellationToken.IsCancellationRequested) // abort the process if cancellation is demanded
211  return ResultStatus.Cancelled;
212 
213  // Resize the image
214  if (textureAsset.IsSizeInPercentage)
215  texTool.Rescale(texImage, textureAsset.Width / 100.0f, textureAsset.Height / 100.0f, Filter.Rescaling.Lanczos3);
216  else
217  texTool.Resize(texImage, (int)textureAsset.Width, (int)textureAsset.Height, Filter.Rescaling.Lanczos3);
218 
219  if (cancellationToken.IsCancellationRequested) // abort the process if cancellation is demanded
220  return ResultStatus.Cancelled;
221 
222  // texture size is now determined, we can cache it
223  var textureSize = new Int2(texImage.Width, texImage.Height);
224 
225  // Check that the resulting texture size is supported by the targeted graphics profile
226  if (!TextureSizeSupported(textureAsset.Format, parameters.GraphicsPlatform, parameters.GraphicsProfile, textureSize, textureAsset.GenerateMipmaps, logger))
227  return ResultStatus.Failed;
228 
229 
230  // Apply the color key
231  if (textureAsset.ColorKeyEnabled)
232  texTool.ColorKey(texImage, textureAsset.ColorKeyColor);
233 
234  if (cancellationToken.IsCancellationRequested) // abort the process if cancellation is demanded
235  return ResultStatus.Cancelled;
236 
237 
238  // Pre-multiply alpha
239  if (textureAsset.PremultiplyAlpha)
240  texTool.PreMultiplyAlpha(texImage);
241 
242  if (cancellationToken.IsCancellationRequested) // abort the process if cancellation is demanded
243  return ResultStatus.Cancelled;
244 
245 
246  // Generate mipmaps
247  if (textureAsset.GenerateMipmaps)
248  texTool.GenerateMipMaps(texImage, Filter.MipMapGeneration.Box);
249 
250  if (cancellationToken.IsCancellationRequested) // abort the process if cancellation is demanded
251  return ResultStatus.Cancelled;
252 
253 
254  // Convert/Compress to output format
255  // TODO: Change alphaFormat depending on actual image content (auto-detection)?
256  var outputFormat = DetermineOutputFormat(textureAsset.Format, textureAsset.Alpha, parameters.Platform, parameters.GraphicsPlatform, textureSize, texImage.Format);
257  texTool.Compress(texImage, outputFormat, (TextureConverter.Requests.TextureQuality)parameters.TextureQuality);
258 
259  if (cancellationToken.IsCancellationRequested) // abort the process if cancellation is demanded
260  return ResultStatus.Cancelled;
261 
262 
263  // Save the texture
264  if (separateAlpha)
265  {
266  TextureAlphaComponentSplitter.CreateAndSaveSeparateTextures(texTool, texImage, outputUrl, textureAsset.GenerateMipmaps);
267  }
268  else
269  {
270  using (var outputImage = texTool.ConvertToParadoxImage(texImage))
271  {
272  if (cancellationToken.IsCancellationRequested) // abort the process if cancellation is demanded
273  return ResultStatus.Cancelled;
274 
275  assetManager.Save(outputUrl, outputImage);
276 
277  logger.Info("Compression successful [{3}] to ({0}x{1},{2})", outputImage.Description.Width, outputImage.Description.Height, outputImage.Description.Format, outputUrl);
278  }
279  }
280  }
281 
282  return ResultStatus.Successful;
283  }
284  }
285 }
PlatformType
Describes the platform operating system.
Definition: PlatformType.cs:9
Provides method to load images or textures, to modify them and to convert them with different texture...
Definition: TextureTool.cs:24
AlphaFormat Alpha
Gets or sets the alpha format.
int Y
The Y component of the vector.
Definition: Int2.cs:78
int X
The X component of the vector.
Definition: Int2.cs:72
GraphicsPlatform
The graphics platform.
static PixelFormat DetermineOutputFormat(TextureFormat textureFormat, AlphaFormat alphaFormat, PlatformType platform, GraphicsPlatform graphicsPlatform, Int2 imageSize, PixelFormat inputImageFormat)
Determine the output format of the texture depending on the platform and asset properties.
TextureFormat Format
Gets or sets the texture format.
static bool TextureSizeSupported(TextureFormat textureFormat, GraphicsPlatform platform, GraphicsProfile graphicsProfile, Int2 textureSize, bool generateMipmaps, Logger logger)
Utility function to check that the texture size is supported on the graphics platform for the provide...
TextureQuality
The desired texture quality.
ResultStatus
Status of a command.
Definition: ResultStatus.cs:8
static bool SupportPVRTC(Int2 textureSize)
Returns true if the PVRTC can be used for the provided texture size.
bool GenerateMipmaps
Gets or sets a value indicating whether to generate mipmaps.
Base implementation for ILogger.
Definition: Logger.cs:10
An helper for the compile commands that needs to process textures.
Parameters used for converting/processing the texture in the storage.
Represents a three dimensional mathematical vector.
Definition: Int2.cs:41
static ResultStatus ImportAndSaveTextureImage(UFile sourcePath, string outputUrl, TextureAsset textureAsset, TextureConvertParameters parameters, bool separateAlpha, CancellationToken cancellationToken, Logger logger)
bool ColorKeyEnabled
Gets or sets a value indicating whether to enable color key. Default is false.
Definition: TextureAsset.cs:83
bool PremultiplyAlpha
Gets or sets a value indicating whether to convert the texture in premultiply alpha.
GraphicsProfile
Identifies the set of supported devices for the demo based on device capabilities.
PixelFormat
Defines various types of pixel formats.
Definition: PixelFormat.cs:32
bool IsSizeInPercentage
Gets or sets a value indicating whether this instance is using size in percentage. Default is true. See remarks.
Definition: TextureAsset.cs:72
Defines a normalized file path. See UPath for details. This class cannot be inherited.
Definition: UFile.cs:13
Base class for texture resources.
Definition: Texture.cs:38
static bool IsPowerOfTwo(int x)
Returns true if the provided int is a power of 2.