/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
- using Delta.Engine.Dynamic;
- using Delta.Utilities;
- using Delta.Utilities.Datatypes;
- using Delta.Utilities.Graphics;
-
- namespace Delta.Graphics.Basics
- {
- /// <summary>
- /// Based on the Content class, this is a specific implementation for
- /// images with some extra data like PixelSize, BlendMode, UseFiltering, UV
- /// and NumberOfAnimatedImages (all from the ContentData meta data).
- /// <para />
- /// You can use this class to extend texture functionality for all platforms.
- /// If you just change OpenTKTexture, your game will not be able to use that
- /// changes on any other graphic platform.
- /// </summary>
- public abstract class Texture : BaseTexture
- {
- #region Constants
- /// <summary>
- /// The dimension size (in both directions) of the default texture.
- /// </summary>
- protected const int DefaultTextureDimension = 4;
-
- /// <summary>
- /// The default texture should not use linear filtering (it is just 4x4).
- /// </summary>
- protected const bool DefaultTextureShouldUseLinearFiltering = false;
- #endregion
-
- #region Create (Static)
- /// <summary>
- /// Create texture with given RGB or RGBA data, this can be used to create
- /// textures programmatically (e.g. mini-maps). You can also use
- /// RenderToTexture to render onto textures, which can also be used in
- /// Materials and Shaders. RenderToTexture is much more efficient if you
- /// want to change the texture data and should always be used for post
- /// screen shaders. This method is only useful for static data.
- /// <para />
- /// Note: This method creates the texture dynamically, each graphics
- /// implementation must provide this constructor, else this will fail.
- /// </summary>
- /// <param name="setByteData">RGB (24 bit per pixel, no alpha) or RGBA
- /// (32 bit per pixel, with alpha) data, you can use the ConvertColorToRgb
- /// or ConvertColorToRgba to get byte data from colors.</param>
- /// <param name="setSize">Size of the texture in pixels,
- /// Width * Height must match rgbData.Length / 3</param>
- /// <param name="setMode">Blend mode to use for this created texture
- /// </param>
- /// <param name="setUseLinearFiltering">True if we want the normal linear
- /// filtering enabled or false for sharp blocky looking textures.</param>
- /// <param name="setIsRgba">Set true whether setByteData is RGBA or RGB.
- /// </param>
- public static Texture Create(byte[] setByteData, Size setSize,
- BlendMode setMode, bool setUseLinearFiltering, bool setIsRgba)
- {
- return Factory.Create<Texture>(new object[]
- {
- setByteData, setSize,
- setMode, setUseLinearFiltering, setIsRgba
- });
- }
-
- /// <summary>
- /// Create texture with given RGB data, this can be used to create
- /// textures programmatically (e.g. mini-maps). You can also use
- /// RenderToTexture to render onto textures, which can also be used in
- /// Materials and Shaders. RenderToTexture is much more efficient if you
- /// want to change the texture data and should always be used for post
- /// screen shaders. This method is only useful for static data.
- /// <para />
- /// Note: This method creates the texture dynamically, each graphics
- /// implementation must provide this constructor, else this will fail.
- /// </summary>
- /// <param name="setRgbData">RGB data (24 bit per pixel, no alpha), you
- /// can use the ConvertColorToRgb to get byte data from colors.</param>
- /// <param name="setSize">Size of the texture in pixels,
- /// Width * Height must match rgbData.Length / 3</param>
- /// <param name="setMode">Blend mode to use for this created texture
- /// </param>
- /// <param name="setUseLinearFiltering">True if we want the normal linear
- /// filtering enabled or false for sharp blocky looking textures.</param>
- public static Texture Create(byte[] setRgbData, Size setSize,
- BlendMode setMode, bool setUseLinearFiltering)
- {
- return Factory.Create<Texture>(new object[]
- {
- setRgbData, setSize,
- setMode, setUseLinearFiltering, false
- });
- }
- #endregion
-
- #region ConvertColorToRgb (Static)
- /// <summary>
- /// Helper method to convert color information into a RGB byte array.
- /// </summary>
- /// <param name="pixelColors">Pixel colors, just RGB values are used
- /// </param>
- /// <returns>Byte array with the RGB data (24 bits per pixel)</returns>
- public static byte[] ConvertColorToRgb(Color[] pixelColors)
- {
- const int numOfBytes = 3;
-
- byte[] opaqueColorBytes = new byte[pixelColors.Length * numOfBytes];
- for (int num = 0; num < pixelColors.Length; num++)
- {
- opaqueColorBytes[num * numOfBytes + 0] = pixelColors[num].RedByte;
- opaqueColorBytes[num * numOfBytes + 1] = pixelColors[num].GreenByte;
- opaqueColorBytes[num * numOfBytes + 2] = pixelColors[num].BlueByte;
- }
-
- return opaqueColorBytes;
- }
- #endregion
-
- #region ConvertColorToRgba (Static)
- /// <summary>
- /// Helper method to convert color information into a RGBA byte array.
- /// </summary>
- /// <param name="pixelColors">Pixel colors in the RGBA format.</param>
- /// <returns>Byte array with the RGBA data (32 bits per pixel)</returns>
- public static byte[] ConvertColorToRgba(Color[] pixelColors)
- {
- const int numOfBytes = 4;
-
- byte[] colorBytes = new byte[pixelColors.Length * numOfBytes];
- for (int num = 0; num < pixelColors.Length; num++)
- {
- colorBytes[num * numOfBytes + 0] = pixelColors[num].RedByte;
- colorBytes[num * numOfBytes + 1] = pixelColors[num].GreenByte;
- colorBytes[num * numOfBytes + 2] = pixelColors[num].BlueByte;
- colorBytes[num * numOfBytes + 3] = pixelColors[num].AlphaByte;
- }
-
- return colorBytes;
- }
- #endregion
-
- #region Private
-
- #region generatedTextureNumber (Private)
- /// <summary>
- /// Helper for the generated texture name for dynamically created textures.
- /// </summary>
- private static int generatedTextureNumber;
- #endregion
-
- #endregion
-
- #region Constructors
- /// <summary>
- /// Create an image, will just pass the image name on to the Texture
- /// class, which will load the image content. Use Get to create and load
- /// images (this makes sure we only create one instance per image).
- /// </summary>
- /// <param name="imageContentName">Image content name to load. If this is
- /// empty no content will be loaded (just fallback data will be set).
- /// </param>
- protected Texture(string imageContentName)
- : base(imageContentName)
- {
- }
-
- /// <summary>
- /// Create texture with given RGB or RGBA data, this can be used to create
- /// textures programmatically (e.g. mini-maps). You can also use
- /// RenderToTexture to render onto textures, which can also be used in
- /// Materials and Shaders. RenderToTexture is much more efficient if you
- /// want to change the texture data and should always be used for post
- /// screen shaders. This constructor is only useful for static data.
- /// </summary>
- /// <param name="setByteData">
- /// RGB (24 bit per pixel, no alpha) or RGBA (32 bit per pixel, with alpha)
- /// data.
- /// </param>
- /// <param name="setSize">Size of the texture in pixels,
- /// Width * Height must match rgbData.Length / 3</param>
- /// <param name="setMode">Blend mode to use for this texture</param>
- /// <param name="setUseLinearFiltering">True if we want the normal linear
- /// filtering enabled or false for sharp blocky looking textures.</param>
- /// <param name="setIsRgba">Set true whether setByteData is RGBA or RGB.</param>
- protected Texture(byte[] setByteData, Size setSize, BlendMode setMode,
- bool setUseLinearFiltering, bool setIsRgba)
- : base(false, "GeneratedTexture" + (generatedTextureNumber++) + "_" +
- setSize.Width + "_" + setSize.Height)
- {
- // Note: image and all the stuff from the other constructor is unused
- // for created textures. Instead setup all the needed image data here.
- PixelSize = setSize;
- BlendMode = setMode;
- UseLinearFiltering = setUseLinearFiltering;
- AllowTiling = false;
- UV = Rectangle.One;
- InnerDrawArea = Rectangle.One;
- useInnerDrawArea = InnerDrawArea != Rectangle.One;
-
- // And finally create the texture with the rgb data
- FillTextureData(PixelSize, setByteData, setByteData.Length,
- setIsRgba
- ? 4
- : 3, 1,
- false, false, false, false, false, false, false, false, false);
- }
- #endregion
-
- #region Methods (Private)
-
- #region Create
- /// <summary>
- /// Create and load texture dynamically, this is important because in the
- /// platform independent rendering system does not know about each texture
- /// implementation. Internal because only used in Delta.Rendering, which
- /// is our friend :)
- /// </summary>
- /// <param name="imageName">Image content name we want for creation</param>
- /// <returns>Loaded texture from the internal ImageData (or the created
- /// fallback texture if that failed)</returns>
- internal static Texture Create(string imageName)
- {
- return Factory.Create<Texture>(imageName);
- }
- #endregion
-
- #region CreateDefaultTexture
- /// <summary>
- /// Helper method to create the default texture with help of the abstract
- /// CreateTexture2D method that is implemented in each implementation.
- /// </summary>
- protected override void CreateDefaultTexture()
- {
- // We create here just a "checker map" as default texture
- // we use two variations of gray for our 4x4 pixels checker map
- Color[] checkerMapColors =
- {
- Color.LightGrey, Color.DarkGrey, Color.LightGrey, Color.DarkGrey,
- Color.DarkGrey, Color.LightGrey, Color.DarkGrey, Color.LightGrey,
- Color.LightGrey, Color.DarkGrey, Color.LightGrey, Color.DarkGrey,
- Color.DarkGrey, Color.LightGrey, Color.DarkGrey, Color.LightGrey
- };
-
- // We are creating a dummy 4x4 default opaque texture here.
- PixelSize = new Size(DefaultTextureDimension);
- BlendMode = BlendMode.Opaque;
- UseLinearFiltering = false;
- UV = Rectangle.One;
- InnerDrawArea = Rectangle.One;
- useInnerDrawArea = InnerDrawArea != Rectangle.One;
-
- if (Graphic.IsFullyInitialized == false)
- {
- Log.Warning("Unable to create texture for CreateDefaultTexture " +
- "because the Graphic device is not fully initialized yet!");
- return;
- }
-
- // Check if the size is correct
- if ((int)PixelSize.Width * (int)PixelSize.Height !=
- checkerMapColors.Length)
- {
- Log.Warning("Invalid data to create 2D texture, pixel size width=" +
- PixelSize.Width + ", height=" + PixelSize.Height +
- " (24 bit) does" +
- " not match size of checkerMapColors=" +
- (checkerMapColors == null
- ? "null"
- : checkerMapColors.Length.ToString()));
- // Continue anyway, might still work with slightly invalid data ..
- }
-
- // Generate our checker map with the bytes from above.
- byte[] rgbData = ConvertColorToRgb(checkerMapColors);
- FillTextureData(PixelSize, rgbData, rgbData.Length, 3, 1,
- false, false, false, false, false, false, false, false, false);
- }
- #endregion
-
- #endregion
- }
- }