diff --git a/spine-csharp/spine-csharp.csproj b/spine-csharp/spine-csharp.csproj index 79a02999e..beff1de63 100644 --- a/spine-csharp/spine-csharp.csproj +++ b/spine-csharp/spine-csharp.csproj @@ -60,12 +60,12 @@ + - diff --git a/spine-csharp/src/BaseAtlas.cs b/spine-csharp/src/Atlas.cs similarity index 51% rename from spine-csharp/src/BaseAtlas.cs rename to spine-csharp/src/Atlas.cs index 61aee0eb7..e2b54335b 100644 --- a/spine-csharp/src/BaseAtlas.cs +++ b/spine-csharp/src/Atlas.cs @@ -22,101 +22,133 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ - using System; using System.Collections.Generic; using System.IO; namespace Spine { - abstract public class BaseAtlas { - List pages = new List(); - List regions = new List(); + public class Atlas { + public Format Format; + public TextureFilter MinFilter; + public TextureFilter MagFilter; + public TextureWrap UWrap; + public TextureWrap VWrap; + public int TextureWidth; + public int TextureHeight; + public List Regions; + public Object Texture; - abstract protected AtlasPage NewAtlasPage (String path); + public Atlas (String path, Object texture, int textureWidth, int textureHeight) { + using (Stream input = new FileStream(path, FileMode.Open, FileAccess.Read)) { + try { + initialize(input, texture, textureWidth, textureHeight); + } catch (Exception ex) { + throw new Exception("Error reading atlas file: " + path, ex); + } + } + } - public void load (StreamReader reader, String imagesDir) { + public Atlas (Stream input, Object texture, int textureWidth, int textureHeight) { + initialize(input, texture, textureWidth, textureHeight); + } + + private void initialize (Stream input, Object texture, int textureWidth, int textureHeight) { + TextureWidth = textureWidth; + TextureHeight = textureHeight; + Texture = texture; + + Regions = new List(); + float invTexWidth = 1f / textureWidth; + float invTexHeight = 1f / textureHeight; String[] tuple = new String[4]; - AtlasPage page = null; + + StreamReader reader = new StreamReader(input); + // Skip to first page entry. while (true) { String line = reader.ReadLine(); - if (line == null) break; if (line.Trim().Length == 0) - page = null; - else if (page == null) { - page = NewAtlasPage(Path.Combine(imagesDir, line)); + break; + } + reader.ReadLine(); // Skip first page name. - page.Format = (Format)Enum.Parse(typeof(Format), readValue(reader), false); + Format = (Format)Enum.Parse(typeof(Format), readValue(reader), false); - readTuple(reader, tuple); - page.MinFilter = (TextureFilter)Enum.Parse(typeof(TextureFilter), tuple[0]); - page.MagFilter = (TextureFilter)Enum.Parse(typeof(TextureFilter), tuple[1]); + readTuple(reader, tuple); + MinFilter = (TextureFilter)Enum.Parse(typeof(TextureFilter), tuple[0]); + MagFilter = (TextureFilter)Enum.Parse(typeof(TextureFilter), tuple[1]); - String direction = readValue(reader); - page.UWrap = TextureWrap.ClampToEdge; - page.VWrap = TextureWrap.ClampToEdge; - if (direction == "x") - page.UWrap = TextureWrap.Repeat; - else if (direction == "y") - page.VWrap = TextureWrap.Repeat; - else if (direction == "xy") - page.UWrap = page.VWrap = TextureWrap.Repeat; + String direction = readValue(reader); + UWrap = TextureWrap.ClampToEdge; + VWrap = TextureWrap.ClampToEdge; + if (direction == "x") + UWrap = TextureWrap.Repeat; + else if (direction == "y") + VWrap = TextureWrap.Repeat; + else if (direction == "xy") + UWrap = VWrap = TextureWrap.Repeat; - pages.Add(page); + while (true) { + String line = reader.ReadLine(); + if (line == null || line.Trim().Length == 0) break; - } else { - AtlasRegion region = new AtlasRegion(); - region.Name = line; - region.Page = page; + AtlasRegion region = new AtlasRegion(); + region.Atlas = this; + region.Name = line; - region.Rotate = Boolean.Parse(readValue(reader)); + region.Rotate = Boolean.Parse(readValue(reader)); - readTuple(reader, tuple); - int x = int.Parse(tuple[0]); - int y = int.Parse(tuple[1]); + readTuple(reader, tuple); + int x = int.Parse(tuple[0]); + int y = int.Parse(tuple[1]); - readTuple(reader, tuple); - int width = int.Parse(tuple[0]); - int height = int.Parse(tuple[1]); + readTuple(reader, tuple); + int width = int.Parse(tuple[0]); + int height = int.Parse(tuple[1]); - float invTexWidth = 1f / page.GetTextureWidth(); - float invTexHeight = 1f / page.GetTextureHeight(); - region.U = x * invTexWidth; - region.V = y * invTexHeight; - region.U2 = (x + width) * invTexWidth; - region.V2 = (y + height) * invTexHeight; - region.Width = Math.Abs(width); - region.Height = Math.Abs(height); + region.U = x * invTexWidth; + region.V = y * invTexHeight; + region.U2 = (x + width) * invTexWidth; + region.V2 = (y + height) * invTexHeight; + region.Width = Math.Abs(width); + region.Height = Math.Abs(height); - if (readTuple(reader, tuple) == 4) { // split is optional - region.Splits = new int[] {int.Parse(tuple[0]), int.Parse(tuple[1]), + if (readTuple(reader, tuple) == 4) { // split is optional + region.Splits = new int[] {int.Parse(tuple[0]), int.Parse(tuple[1]), int.Parse(tuple[2]), int.Parse(tuple[3])}; - if (readTuple(reader, tuple) == 4) { // pad is optional, but only present with splits - region.Pads = new int[] {int.Parse(tuple[0]), int.Parse(tuple[1]), + if (readTuple(reader, tuple) == 4) { // pad is optional, but only present with splits + region.Pads = new int[] {int.Parse(tuple[0]), int.Parse(tuple[1]), int.Parse(tuple[2]), int.Parse(tuple[3])}; - readTuple(reader, tuple); - } + readTuple(reader, tuple); } - - region.OriginalWidth = int.Parse(tuple[0]); - region.OriginalHeight = int.Parse(tuple[1]); - - readTuple(reader, tuple); - region.OffsetX = int.Parse(tuple[0]); - region.OffsetY = int.Parse(tuple[1]); - - region.Index = int.Parse(readValue(reader)); - - regions.Add(region); } + + region.OriginalWidth = int.Parse(tuple[0]); + region.OriginalHeight = int.Parse(tuple[1]); + + readTuple(reader, tuple); + region.OffsetX = int.Parse(tuple[0]); + region.OffsetY = int.Parse(tuple[1]); + + region.Index = int.Parse(readValue(reader)); + + Regions.Add(region); + } + + while (true) { + String line = reader.ReadLine(); + if (line == null) + break; + if (line.Trim().Length != 0) throw new Exception("An atlas with multiple images is not supported."); } } static String readValue (StreamReader reader) { String line = reader.ReadLine(); int colon = line.IndexOf(':'); - if (colon == -1) throw new Exception("Invalid line: " + line); + if (colon == -1) + throw new Exception("Invalid line: " + line); return line.Substring(colon + 1).Trim(); } @@ -124,12 +156,14 @@ namespace Spine { static int readTuple (StreamReader reader, String[] tuple) { String line = reader.ReadLine(); int colon = line.IndexOf(':'); - if (colon == -1) throw new Exception("Invalid line: " + line); + if (colon == -1) + throw new Exception("Invalid line: " + line); int i = 0, lastMatch = colon + 1; for (i = 0; i < 3; i++) { int comma = line.IndexOf(',', lastMatch); if (comma == -1) { - if (i == 0) throw new Exception("Invalid line: " + line); + if (i == 0) + throw new Exception("Invalid line: " + line); break; } tuple[i] = line.Substring(lastMatch, comma - lastMatch).Trim(); @@ -143,8 +177,9 @@ namespace Spine { * should be cached rather than calling this method multiple times. * @return The region, or null. */ public AtlasRegion FindRegion (String name) { - for (int i = 0, n = regions.Count; i < n; i++) - if (regions[i].Name == name) return regions[i]; + for (int i = 0, n = Regions.Count; i < n; i++) + if (Regions[i].Name == name) + return Regions[i]; return null; } } @@ -175,19 +210,8 @@ namespace Spine { Repeat } - abstract public class AtlasPage { - public Format Format; - public TextureFilter MinFilter; - public TextureFilter MagFilter; - public TextureWrap UWrap; - public TextureWrap VWrap; - - abstract public int GetTextureWidth (); - abstract public int GetTextureHeight (); - } - public class AtlasRegion { - public AtlasPage Page; + public Atlas Atlas; public float U, V; public float U2, V2; public int Width, Height; diff --git a/spine-csharp/src/Attachments/AtlasAttachmentLoader.cs b/spine-csharp/src/Attachments/AtlasAttachmentLoader.cs index 4e31d1dcf..58a0fd5fc 100644 --- a/spine-csharp/src/Attachments/AtlasAttachmentLoader.cs +++ b/spine-csharp/src/Attachments/AtlasAttachmentLoader.cs @@ -27,9 +27,9 @@ using System; namespace Spine { public class AtlasAttachmentLoader : AttachmentLoader { - private BaseAtlas atlas; + private Atlas atlas; - public AtlasAttachmentLoader (BaseAtlas atlas) { + public AtlasAttachmentLoader (Atlas atlas) { if (atlas == null) throw new ArgumentNullException("atlas cannot be null."); this.atlas = atlas; } diff --git a/spine-csharp/src/Attachments/RegionAttachment.cs b/spine-csharp/src/Attachments/RegionAttachment.cs index 48d634adb..0226b04a7 100644 --- a/spine-csharp/src/Attachments/RegionAttachment.cs +++ b/spine-csharp/src/Attachments/RegionAttachment.cs @@ -96,16 +96,18 @@ namespace Spine { float localX = -localX2; float localY = -localY2; AtlasRegion region = Region; - if (region.Rotate) { - localX += region.OffsetX / region.OriginalWidth * height; - localY += region.OffsetY / region.OriginalHeight * width; - localX2 -= (region.OriginalWidth - region.OffsetX - region.Height) / region.OriginalWidth * width; - localY2 -= (region.OriginalHeight - region.OffsetY - region.Width) / region.OriginalHeight * height; - } else { - localX += region.OffsetX / region.OriginalWidth * width; - localY += region.OffsetY / region.OriginalHeight * height; - localX2 -= (region.OriginalWidth - region.OffsetX - region.Width) / region.OriginalWidth * width; - localY2 -= (region.OriginalHeight - region.OffsetY - region.Height) / region.OriginalHeight * height; + if (region != null) { + if (region.Rotate) { + localX += region.OffsetX / region.OriginalWidth * height; + localY += region.OffsetY / region.OriginalHeight * width; + localX2 -= (region.OriginalWidth - region.OffsetX - region.Height) / region.OriginalWidth * width; + localY2 -= (region.OriginalHeight - region.OffsetY - region.Width) / region.OriginalHeight * height; + } else { + localX += region.OffsetX / region.OriginalWidth * width; + localY += region.OffsetY / region.OriginalHeight * height; + localX2 -= (region.OriginalWidth - region.OffsetX - region.Width) / region.OriginalWidth * width; + localY2 -= (region.OriginalHeight - region.OffsetY - region.Height) / region.OriginalHeight * height; + } } float scaleX = ScaleX; float scaleY = ScaleY; diff --git a/spine-csharp/src/Json.cs b/spine-csharp/src/Json.cs index 9fcbd3f3d..376dd7ef7 100644 --- a/spine-csharp/src/Json.cs +++ b/spine-csharp/src/Json.cs @@ -81,12 +81,10 @@ namespace Spine /// /// A JSON string. /// An List<object>, a Dictionary<string, object>, a float, an integer,a string, null, true, or false - public static object Deserialize(string json) { - // save the string for debug information + public static object Deserialize (TextReader json) { if (json == null) { return null; - } - + } return Parser.Parse(json); } @@ -109,14 +107,14 @@ namespace Spine NULL }; - StringReader json; + TextReader json; - Parser(string jsonString) { - json = new StringReader(jsonString); + Parser(TextReader reader) { + json = reader; } - - public static object Parse(string jsonString) { - using (var instance = new Parser(jsonString)) { + + public static object Parse (TextReader reader) { + using (var instance = new Parser(reader)) { return instance.ParseValue(); } } @@ -288,14 +286,6 @@ namespace Spine object ParseNumber() { string number = NextWord; - - //NO!! always serialize to a float - //if (number.IndexOf('.') == -1) { - // long parsedInt; - // Int64.TryParse(number, out parsedInt); - // return parsedInt; - //} - float parsedFloat; float.TryParse(number, NumberStyles.Float, CultureInfo.InvariantCulture, out parsedFloat); return parsedFloat; diff --git a/spine-csharp/src/SkeletonJson.cs b/spine-csharp/src/SkeletonJson.cs index 97e60e0ca..dd96c55f1 100644 --- a/spine-csharp/src/SkeletonJson.cs +++ b/spine-csharp/src/SkeletonJson.cs @@ -41,7 +41,7 @@ namespace Spine { private AttachmentLoader attachmentLoader; public float Scale { get; set; } - public SkeletonJson (BaseAtlas atlas) { + public SkeletonJson (Atlas atlas) { this.attachmentLoader = new AtlasAttachmentLoader(atlas); Scale = 1; } @@ -51,14 +51,21 @@ namespace Spine { Scale = 1; } - public SkeletonData readSkeletonData (String name, String json) { - if (json == null) + public SkeletonData ReadSkeletonData (String path) { + using (Stream input = new FileStream(path, FileMode.Open, FileAccess.Read)) { + SkeletonData skeletonData = ReadSkeletonData(input); + skeletonData.Name = Path.GetFileNameWithoutExtension(path); + return skeletonData; + } + } + + public SkeletonData ReadSkeletonData (Stream input) { + if (input == null) throw new ArgumentNullException("json cannot be null."); SkeletonData skeletonData = new SkeletonData(); - skeletonData.Name = name; - var root = Json.Deserialize(json) as Dictionary; + var root = Json.Deserialize(new StreamReader(input)) as Dictionary; // Bones. foreach (Dictionary boneMap in (List)root["bones"]) { diff --git a/spine-xna/example/src/ExampleGame.cs b/spine-xna/example/src/ExampleGame.cs index 80642271e..5d210c150 100644 --- a/spine-xna/example/src/ExampleGame.cs +++ b/spine-xna/example/src/ExampleGame.cs @@ -58,11 +58,13 @@ namespace Spine { protected override void LoadContent () { skeletonRenderer = new SkeletonRenderer(GraphicsDevice); - Atlas atlas = new Atlas(GraphicsDevice, "data/goblins.atlas"); + + Texture2D texture = Util.LoadTexture(GraphicsDevice, "data/goblins.png"); + Atlas atlas = new Atlas("data/goblins.atlas", texture, texture.Width, texture.Height); SkeletonJson json = new SkeletonJson(atlas); - skeleton = new Skeleton(json.readSkeletonData("goblins", File.ReadAllText("data/goblins.json"))); + skeleton = new Skeleton(json.ReadSkeletonData("data/goblins.json")); skeleton.SetSkin("goblingirl"); - skeleton.SetSlotsToBindPose(); + skeleton.SetSlotsToBindPose(); // Without this the skin attachments won't be attached. See SetSkin. animation = skeleton.Data.FindAnimation("walk"); skeleton.RootBone.X = 320; diff --git a/spine-xna/spine-xna.csproj b/spine-xna/spine-xna.csproj index 92851d9df..450d8efdc 100644 --- a/spine-xna/spine-xna.csproj +++ b/spine-xna/spine-xna.csproj @@ -93,7 +93,7 @@ - + diff --git a/spine-xna/src/Atlas.cs b/spine-xna/src/Atlas.cs deleted file mode 100644 index 75b7af640..000000000 --- a/spine-xna/src/Atlas.cs +++ /dev/null @@ -1,109 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2013, Esoteric Software - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ******************************************************************************/ - -using System; -using System.IO; -using System.Collections.Generic; -using System.Linq; -using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Audio; -using Microsoft.Xna.Framework.Content; -using Microsoft.Xna.Framework.GamerServices; -using Microsoft.Xna.Framework.Graphics; -using Microsoft.Xna.Framework.Input; -using Microsoft.Xna.Framework.Media; - -namespace Spine { - public class Atlas : BaseAtlas { - private GraphicsDevice device; - - public Atlas (GraphicsDevice device, String atlasFile) { - this.device = device; - using (StreamReader reader = new StreamReader(atlasFile)) { - load(reader, Path.GetDirectoryName(atlasFile)); - } - } - - override protected AtlasPage NewAtlasPage (String path) { - XnaAtlasPage page = new XnaAtlasPage(); - page.Texture = loadTexture(path); - return page; - } - - private Texture2D loadTexture (string path) { - Texture2D file; - using (Stream fileStream = new FileStream(path, FileMode.Open)) { - file = Texture2D.FromStream(device, fileStream); - } - - // Setup a render target to hold our final texture which will have premulitplied alpha values - RenderTarget2D result = new RenderTarget2D(device, file.Width, file.Height); - device.SetRenderTarget(result); - device.Clear(Color.Black); - - // Multiply each color by the source alpha, and write in just the color values into the final texture - BlendState blendColor = new BlendState(); - blendColor.ColorWriteChannels = ColorWriteChannels.Red | ColorWriteChannels.Green | ColorWriteChannels.Blue; - blendColor.AlphaDestinationBlend = Blend.Zero; - blendColor.ColorDestinationBlend = Blend.Zero; - blendColor.AlphaSourceBlend = Blend.SourceAlpha; - blendColor.ColorSourceBlend = Blend.SourceAlpha; - - SpriteBatch spriteBatch = new SpriteBatch(device); - spriteBatch.Begin(SpriteSortMode.Immediate, blendColor); - spriteBatch.Draw(file, file.Bounds, Color.White); - spriteBatch.End(); - - // Now copy over the alpha values from the PNG source texture to the final one, without multiplying them - BlendState blendAlpha = new BlendState(); - blendAlpha.ColorWriteChannels = ColorWriteChannels.Alpha; - blendAlpha.AlphaDestinationBlend = Blend.Zero; - blendAlpha.ColorDestinationBlend = Blend.Zero; - blendAlpha.AlphaSourceBlend = Blend.One; - blendAlpha.ColorSourceBlend = Blend.One; - - spriteBatch.Begin(SpriteSortMode.Immediate, blendAlpha); - spriteBatch.Draw(file, file.Bounds, Color.White); - spriteBatch.End(); - - // Release the GPU back to drawing to the screen - device.SetRenderTarget(null); - - return result as Texture2D; - } - } - - public class XnaAtlasPage : AtlasPage { - public Texture2D Texture { get; set; } - - override public int GetTextureWidth () { - return Texture.Width; - } - - override public int GetTextureHeight () { - return Texture.Height; - } - } -} diff --git a/spine-xna/src/SkeletonRenderer.cs b/spine-xna/src/SkeletonRenderer.cs index e3e64772b..2d3587adb 100644 --- a/spine-xna/src/SkeletonRenderer.cs +++ b/spine-xna/src/SkeletonRenderer.cs @@ -34,6 +34,7 @@ namespace Spine { SpriteBatcher batcher; BasicEffect effect; RasterizerState rasterizerState; + public BlendState BlendState { get; set; } public SkeletonRenderer (GraphicsDevice device) { this.device = device; @@ -49,12 +50,14 @@ namespace Spine { rasterizerState = new RasterizerState(); rasterizerState.CullMode = CullMode.None; + BlendState = BlendState.AlphaBlend; + Bone.yDown = true; } public void Begin () { device.RasterizerState = rasterizerState; - device.BlendState = BlendState.AlphaBlend; + device.BlendState = BlendState; effect.Projection = Matrix.CreateOrthographicOffCenter(0, device.Viewport.Width, device.Viewport.Height, 0, 1, 0); } @@ -71,13 +74,11 @@ namespace Spine { for (int i = 0, n = drawOrder.Count; i < n; i++) { Slot slot = drawOrder[i]; Attachment attachment = slot.Attachment; - if (attachment == null) - continue; if (attachment is RegionAttachment) { RegionAttachment regionAttachment = (RegionAttachment)attachment; SpriteBatchItem item = batcher.CreateBatchItem(); - item.Texture = ((XnaAtlasPage)regionAttachment.Region.Page).Texture; + item.Texture = (Texture2D)regionAttachment.Region.Atlas.Texture; byte r = (byte)(slot.R * 255); byte g = (byte)(slot.G * 255); diff --git a/spine-xna/src/Util.cs b/spine-xna/src/Util.cs new file mode 100644 index 000000000..0a3173641 --- /dev/null +++ b/spine-xna/src/Util.cs @@ -0,0 +1,57 @@ +using System; +using System.IO; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace Spine { + static public class Util { + static public Texture2D LoadTexture (GraphicsDevice device, String path) { + using (Stream input = new FileStream(path, FileMode.Open, FileAccess.Read)) { + try { + return Util.LoadTexture(device, input); + } catch (Exception ex) { + throw new Exception("Error reading texture file: " + path, ex); + } + } + } + + static public Texture2D LoadTexture (GraphicsDevice device, Stream input) { + Texture2D file = Texture2D.FromStream(device, input); + + // Setup a render target to hold our final texture which will have premulitplied alpha values + RenderTarget2D result = new RenderTarget2D(device, file.Width, file.Height); + device.SetRenderTarget(result); + device.Clear(Color.Black); + + // Multiply each color by the source alpha, and write in just the color values into the final texture + BlendState blendColor = new BlendState(); + blendColor.ColorWriteChannels = ColorWriteChannels.Red | ColorWriteChannels.Green | ColorWriteChannels.Blue; + blendColor.AlphaDestinationBlend = Blend.Zero; + blendColor.ColorDestinationBlend = Blend.Zero; + blendColor.AlphaSourceBlend = Blend.SourceAlpha; + blendColor.ColorSourceBlend = Blend.SourceAlpha; + + SpriteBatch spriteBatch = new SpriteBatch(device); + spriteBatch.Begin(SpriteSortMode.Immediate, blendColor); + spriteBatch.Draw(file, file.Bounds, Color.White); + spriteBatch.End(); + + // Now copy over the alpha values from the PNG source texture to the final one, without multiplying them + BlendState blendAlpha = new BlendState(); + blendAlpha.ColorWriteChannels = ColorWriteChannels.Alpha; + blendAlpha.AlphaDestinationBlend = Blend.Zero; + blendAlpha.ColorDestinationBlend = Blend.Zero; + blendAlpha.AlphaSourceBlend = Blend.One; + blendAlpha.ColorSourceBlend = Blend.One; + + spriteBatch.Begin(SpriteSortMode.Immediate, blendAlpha); + spriteBatch.Draw(file, file.Bounds, Color.White); + spriteBatch.End(); + + // Release the GPU back to drawing to the screen + device.SetRenderTarget(null); + + return result as Texture2D; + } + } +}