PageRenderTime 40ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/Graphics/Basics/Texture.cs

#
C# | 280 lines | 138 code | 24 blank | 118 comment | 8 complexity | 97fffe27dfff258117a3f394d2b9b92f MD5 | raw file
Possible License(s): Apache-2.0
  1. using Delta.Engine.Dynamic;
  2. using Delta.Utilities;
  3. using Delta.Utilities.Datatypes;
  4. using Delta.Utilities.Graphics;
  5. namespace Delta.Graphics.Basics
  6. {
  7. /// <summary>
  8. /// Based on the Content class, this is a specific implementation for
  9. /// images with some extra data like PixelSize, BlendMode, UseFiltering, UV
  10. /// and NumberOfAnimatedImages (all from the ContentData meta data).
  11. /// <para />
  12. /// You can use this class to extend texture functionality for all platforms.
  13. /// If you just change OpenTKTexture, your game will not be able to use that
  14. /// changes on any other graphic platform.
  15. /// </summary>
  16. public abstract class Texture : BaseTexture
  17. {
  18. #region Constants
  19. /// <summary>
  20. /// The dimension size (in both directions) of the default texture.
  21. /// </summary>
  22. protected const int DefaultTextureDimension = 4;
  23. /// <summary>
  24. /// The default texture should not use linear filtering (it is just 4x4).
  25. /// </summary>
  26. protected const bool DefaultTextureShouldUseLinearFiltering = false;
  27. #endregion
  28. #region Create (Static)
  29. /// <summary>
  30. /// Create texture with given RGB or RGBA data, this can be used to create
  31. /// textures programmatically (e.g. mini-maps). You can also use
  32. /// RenderToTexture to render onto textures, which can also be used in
  33. /// Materials and Shaders. RenderToTexture is much more efficient if you
  34. /// want to change the texture data and should always be used for post
  35. /// screen shaders. This method is only useful for static data.
  36. /// <para />
  37. /// Note: This method creates the texture dynamically, each graphics
  38. /// implementation must provide this constructor, else this will fail.
  39. /// </summary>
  40. /// <param name="setByteData">RGB (24 bit per pixel, no alpha) or RGBA
  41. /// (32 bit per pixel, with alpha) data, you can use the ConvertColorToRgb
  42. /// or ConvertColorToRgba to get byte data from colors.</param>
  43. /// <param name="setSize">Size of the texture in pixels,
  44. /// Width * Height must match rgbData.Length / 3</param>
  45. /// <param name="setMode">Blend mode to use for this created texture
  46. /// </param>
  47. /// <param name="setUseLinearFiltering">True if we want the normal linear
  48. /// filtering enabled or false for sharp blocky looking textures.</param>
  49. /// <param name="setIsRgba">Set true whether setByteData is RGBA or RGB.
  50. /// </param>
  51. public static Texture Create(byte[] setByteData, Size setSize,
  52. BlendMode setMode, bool setUseLinearFiltering, bool setIsRgba)
  53. {
  54. return Factory.Create<Texture>(new object[]
  55. {
  56. setByteData, setSize,
  57. setMode, setUseLinearFiltering, setIsRgba
  58. });
  59. }
  60. /// <summary>
  61. /// Create texture with given RGB data, this can be used to create
  62. /// textures programmatically (e.g. mini-maps). You can also use
  63. /// RenderToTexture to render onto textures, which can also be used in
  64. /// Materials and Shaders. RenderToTexture is much more efficient if you
  65. /// want to change the texture data and should always be used for post
  66. /// screen shaders. This method is only useful for static data.
  67. /// <para />
  68. /// Note: This method creates the texture dynamically, each graphics
  69. /// implementation must provide this constructor, else this will fail.
  70. /// </summary>
  71. /// <param name="setRgbData">RGB data (24 bit per pixel, no alpha), you
  72. /// can use the ConvertColorToRgb to get byte data from colors.</param>
  73. /// <param name="setSize">Size of the texture in pixels,
  74. /// Width * Height must match rgbData.Length / 3</param>
  75. /// <param name="setMode">Blend mode to use for this created texture
  76. /// </param>
  77. /// <param name="setUseLinearFiltering">True if we want the normal linear
  78. /// filtering enabled or false for sharp blocky looking textures.</param>
  79. public static Texture Create(byte[] setRgbData, Size setSize,
  80. BlendMode setMode, bool setUseLinearFiltering)
  81. {
  82. return Factory.Create<Texture>(new object[]
  83. {
  84. setRgbData, setSize,
  85. setMode, setUseLinearFiltering, false
  86. });
  87. }
  88. #endregion
  89. #region ConvertColorToRgb (Static)
  90. /// <summary>
  91. /// Helper method to convert color information into a RGB byte array.
  92. /// </summary>
  93. /// <param name="pixelColors">Pixel colors, just RGB values are used
  94. /// </param>
  95. /// <returns>Byte array with the RGB data (24 bits per pixel)</returns>
  96. public static byte[] ConvertColorToRgb(Color[] pixelColors)
  97. {
  98. const int numOfBytes = 3;
  99. byte[] opaqueColorBytes = new byte[pixelColors.Length * numOfBytes];
  100. for (int num = 0; num < pixelColors.Length; num++)
  101. {
  102. opaqueColorBytes[num * numOfBytes + 0] = pixelColors[num].RedByte;
  103. opaqueColorBytes[num * numOfBytes + 1] = pixelColors[num].GreenByte;
  104. opaqueColorBytes[num * numOfBytes + 2] = pixelColors[num].BlueByte;
  105. }
  106. return opaqueColorBytes;
  107. }
  108. #endregion
  109. #region ConvertColorToRgba (Static)
  110. /// <summary>
  111. /// Helper method to convert color information into a RGBA byte array.
  112. /// </summary>
  113. /// <param name="pixelColors">Pixel colors in the RGBA format.</param>
  114. /// <returns>Byte array with the RGBA data (32 bits per pixel)</returns>
  115. public static byte[] ConvertColorToRgba(Color[] pixelColors)
  116. {
  117. const int numOfBytes = 4;
  118. byte[] colorBytes = new byte[pixelColors.Length * numOfBytes];
  119. for (int num = 0; num < pixelColors.Length; num++)
  120. {
  121. colorBytes[num * numOfBytes + 0] = pixelColors[num].RedByte;
  122. colorBytes[num * numOfBytes + 1] = pixelColors[num].GreenByte;
  123. colorBytes[num * numOfBytes + 2] = pixelColors[num].BlueByte;
  124. colorBytes[num * numOfBytes + 3] = pixelColors[num].AlphaByte;
  125. }
  126. return colorBytes;
  127. }
  128. #endregion
  129. #region Private
  130. #region generatedTextureNumber (Private)
  131. /// <summary>
  132. /// Helper for the generated texture name for dynamically created textures.
  133. /// </summary>
  134. private static int generatedTextureNumber;
  135. #endregion
  136. #endregion
  137. #region Constructors
  138. /// <summary>
  139. /// Create an image, will just pass the image name on to the Texture
  140. /// class, which will load the image content. Use Get to create and load
  141. /// images (this makes sure we only create one instance per image).
  142. /// </summary>
  143. /// <param name="imageContentName">Image content name to load. If this is
  144. /// empty no content will be loaded (just fallback data will be set).
  145. /// </param>
  146. protected Texture(string imageContentName)
  147. : base(imageContentName)
  148. {
  149. }
  150. /// <summary>
  151. /// Create texture with given RGB or RGBA data, this can be used to create
  152. /// textures programmatically (e.g. mini-maps). You can also use
  153. /// RenderToTexture to render onto textures, which can also be used in
  154. /// Materials and Shaders. RenderToTexture is much more efficient if you
  155. /// want to change the texture data and should always be used for post
  156. /// screen shaders. This constructor is only useful for static data.
  157. /// </summary>
  158. /// <param name="setByteData">
  159. /// RGB (24 bit per pixel, no alpha) or RGBA (32 bit per pixel, with alpha)
  160. /// data.
  161. /// </param>
  162. /// <param name="setSize">Size of the texture in pixels,
  163. /// Width * Height must match rgbData.Length / 3</param>
  164. /// <param name="setMode">Blend mode to use for this texture</param>
  165. /// <param name="setUseLinearFiltering">True if we want the normal linear
  166. /// filtering enabled or false for sharp blocky looking textures.</param>
  167. /// <param name="setIsRgba">Set true whether setByteData is RGBA or RGB.</param>
  168. protected Texture(byte[] setByteData, Size setSize, BlendMode setMode,
  169. bool setUseLinearFiltering, bool setIsRgba)
  170. : base(false, "GeneratedTexture" + (generatedTextureNumber++) + "_" +
  171. setSize.Width + "_" + setSize.Height)
  172. {
  173. // Note: image and all the stuff from the other constructor is unused
  174. // for created textures. Instead setup all the needed image data here.
  175. PixelSize = setSize;
  176. BlendMode = setMode;
  177. UseLinearFiltering = setUseLinearFiltering;
  178. AllowTiling = false;
  179. UV = Rectangle.One;
  180. InnerDrawArea = Rectangle.One;
  181. useInnerDrawArea = InnerDrawArea != Rectangle.One;
  182. // And finally create the texture with the rgb data
  183. FillTextureData(PixelSize, setByteData, setByteData.Length,
  184. setIsRgba
  185. ? 4
  186. : 3, 1,
  187. false, false, false, false, false, false, false, false, false);
  188. }
  189. #endregion
  190. #region Methods (Private)
  191. #region Create
  192. /// <summary>
  193. /// Create and load texture dynamically, this is important because in the
  194. /// platform independent rendering system does not know about each texture
  195. /// implementation. Internal because only used in Delta.Rendering, which
  196. /// is our friend :)
  197. /// </summary>
  198. /// <param name="imageName">Image content name we want for creation</param>
  199. /// <returns>Loaded texture from the internal ImageData (or the created
  200. /// fallback texture if that failed)</returns>
  201. internal static Texture Create(string imageName)
  202. {
  203. return Factory.Create<Texture>(imageName);
  204. }
  205. #endregion
  206. #region CreateDefaultTexture
  207. /// <summary>
  208. /// Helper method to create the default texture with help of the abstract
  209. /// CreateTexture2D method that is implemented in each implementation.
  210. /// </summary>
  211. protected override void CreateDefaultTexture()
  212. {
  213. // We create here just a "checker map" as default texture
  214. // we use two variations of gray for our 4x4 pixels checker map
  215. Color[] checkerMapColors =
  216. {
  217. Color.LightGrey, Color.DarkGrey, Color.LightGrey, Color.DarkGrey,
  218. Color.DarkGrey, Color.LightGrey, Color.DarkGrey, Color.LightGrey,
  219. Color.LightGrey, Color.DarkGrey, Color.LightGrey, Color.DarkGrey,
  220. Color.DarkGrey, Color.LightGrey, Color.DarkGrey, Color.LightGrey
  221. };
  222. // We are creating a dummy 4x4 default opaque texture here.
  223. PixelSize = new Size(DefaultTextureDimension);
  224. BlendMode = BlendMode.Opaque;
  225. UseLinearFiltering = false;
  226. UV = Rectangle.One;
  227. InnerDrawArea = Rectangle.One;
  228. useInnerDrawArea = InnerDrawArea != Rectangle.One;
  229. if (Graphic.IsFullyInitialized == false)
  230. {
  231. Log.Warning("Unable to create texture for CreateDefaultTexture " +
  232. "because the Graphic device is not fully initialized yet!");
  233. return;
  234. }
  235. // Check if the size is correct
  236. if ((int)PixelSize.Width * (int)PixelSize.Height !=
  237. checkerMapColors.Length)
  238. {
  239. Log.Warning("Invalid data to create 2D texture, pixel size width=" +
  240. PixelSize.Width + ", height=" + PixelSize.Height +
  241. " (24 bit) does" +
  242. " not match size of checkerMapColors=" +
  243. (checkerMapColors == null
  244. ? "null"
  245. : checkerMapColors.Length.ToString()));
  246. // Continue anyway, might still work with slightly invalid data ..
  247. }
  248. // Generate our checker map with the bytes from above.
  249. byte[] rgbData = ConvertColorToRgb(checkerMapColors);
  250. FillTextureData(PixelSize, rgbData, rgbData.Length, 3, 1,
  251. false, false, false, false, false, false, false, false, false);
  252. }
  253. #endregion
  254. #endregion
  255. }
  256. }