如何使用Texture2D.FromStream加载透明PNG

时间:2016-10-22 16:11:54

标签: c# xna

我想问一下如何从文件中加载Texture2D图像(我不想使用XNA的内容管道),同时保留图像的透明度,因为我想要在游戏中进行蒙皮。

我的代码:

使用_cursor.Texture = _helper.LoadPicture("skin\\cursor.png");

初始化纹理

使用spriteBatch.Draw(Texture, rectangle, Color.BlanchedAlmond);

绘制纹理
public Texture2D LoadPicture(string filename) {
    FileStream setStream = File.Open(filename, FileMode.Open);
    StreamReader reader = new StreamReader(setStream);
    Texture2D NewTexture = Texture2D.FromStream(_graphicsDevice, setStream);
    setStream.Dispose();
    return NewTexture;
 }

屏幕截图1(结果):http://prntscr.com/cxjzwu

屏幕截图2(预期):http://prntscr.com/cxk065

2 个答案:

答案 0 :(得分:2)

您也可以通过加载来处理它,因此您可以将BlendState保持为AlphaBlend。

这是我用来从文件中加载纹理的函数:

private Texture2D PremultiplyTexture(String FilePath, GraphicsDevice device)
{
    Texture2D texture;

    FileStream titleStream = File.OpenRead(FilePath);
    texture = Texture2D.FromStream(device, titleStream);
    titleStream.Close();
    Color[] buffer = new Color[texture.Width * texture.Height];
    texture.GetData(buffer);
    for (int i = 0; i < buffer.Length; i++)
        buffer[i] = Color.FromNonPremultiplied(buffer[i].R, buffer[i].G, buffer[i].B, buffer[i].A);
    texture.SetData(buffer);

    return texture;
}

答案 1 :(得分:1)

我试图重新创建你的问题,但它对我来说很好用:

enter image description here

我的幕后代码:

    #region Usings

using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

#endregion

namespace OpacityTest
{
    /// <summary>
    ///     This is the main type for your game
    /// </summary>
    public class Game1 : Game
    {
        private static Texture2D Tested;
        private GraphicsDeviceManager graphics;
        private SpriteBatch spriteBatch;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        /// <summary>
        ///     Allows the game to perform any initialization it needs to before starting to run.
        ///     This is where it can query for any required services and load any non-graphic
        ///     related content.  Calling base.Initialize will enumerate through any components
        ///     and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            base.Initialize();
        }

        /// <summary>
        ///     LoadContent will be called once per game and is the place to load
        ///     all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            using (var fileStream = new FileStream("test.png", FileMode.Open))
            {
                Tested = Texture2D.FromStream(GraphicsDevice, fileStream);
            }
        }

        /// <summary>
        ///     UnloadContent will be called once per game and is the place to unload
        ///     all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // Important!!!
            Tested.Dispose();
        }

        /// <summary>
        ///     Allows the game to run logic such as updating the world,
        ///     checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                Exit();

            base.Update(gameTime);
        }

        /// <summary>
        ///     This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);
            spriteBatch.Draw(Tested, Vector2.Zero, Color.White);
            spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}

我正在使用这个纹理:

enter image description here

并将其放入我的构建文件夹中。

[编辑]

现在我看到你的问题所在 - 颜色alpha值设置为最大值。我已经尝试了一些事情并得出结论,你必须更换这一行:

        spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);

用那一行:

        spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.NonPremultiplied);

之后我获得了您的Content.Load结果:

enter image description here

如果你想了解更多关于&#34;预乘alpha&#34;点击me! :)

我已经使用了第二个纹理光标:

enter image description here