PageRenderTime 104ms CodeModel.GetById 60ms app.highlight 11ms RepoModel.GetById 29ms app.codeStats 1ms

/Graphics/Basics/Texture.cs

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