2013-02-06 61 views
0

我正在为Windows Phone XNA开发,并且希望加载较小尺寸的纹理以减少不需要完整图像时的内存影响。加载纹理在XNA中调整

我目前的解决方案是使用一个渲染目标绘制并返回渲染目标作为一个较小的质地使用方法:

public static Texture2D LoadResized(string texturePath, float scale) 
{ 
    Texture2D texLoaded = Content.Load<Texture2D>(texturePath); 
    Vector2 resizedSize = new Vector2(texLoaded.Width * scale, texLoaded.Height * scale); 
    Texture2D resized = ResizeTexture(texLoaded, resizedSize); 
    //texLoaded.Dispose(); 
    return resized; 
} 

public static Texture2D ResizeTexture(Texture2D toResize, Vector2 targetSize) 
{ 
    RenderTarget2D renderTarget = new RenderTarget2D(
     GraphicsDevice, (int)targetSize.X, (int)targetSize.Y); 

    Rectangle destinationRectangle = new Rectangle(
     0, 0, (int)targetSize.X, (int)targetSize.Y); 

    GraphicsDevice.SetRenderTarget(renderTarget); 
    GraphicsDevice.Clear(Color.Transparent); 

    SpriteBatch.Begin(); 
    SpriteBatch.Draw(toResize, destinationRectangle, Color.White); 
    SpriteBatch.End(); 
    GraphicsDevice.SetRenderTarget(null); 

    return renderTarget; 
} 

这工作,因为纹理被调整,但是从内存使用,它看起来像纹理“ texLoaded“不会被释放。当使用未注释的Dispose方法时,SpriteBatch.End()将抛出一个处置的异常。

加载纹理的任何其他方式调整大小以减少内存使用量?

回答

0

您的代码是差不多好的。它有一个小错误。

您可能会注意到它只会抛出异常第二个时间,您称为LoadResized对于任何给定的纹理。这是因为ContentManager保留了它加载的内容的内部缓存 - 它“拥有”它加载的所有内容。这样,如果你加载了两次,它只是让你回到缓存的对象。通过调用Dispose您正在将对象放置在其缓存中!

那么,解决方案是不要使用ContentManager加载您的内容 - 至少不是默认实现。您可以从ContentManager是不缓存的项目,像这样(代码是基于this blog post)继承自己的类:在Game.Services

class FreshLoadContentManager : ContentManager 
{ 
    public FreshLoadContentManager(IServiceProvider s) : base(s) { } 

    public override T Load<T>(string assetName) 
    { 
     return ReadAsset<T>(assetName, (d) => { }); 
    } 
} 

通创建一个。不要忘记设置RootDirectory属性。

然后使用此衍生内容管理器加载您的内容。您现在可以安全(现在应该!)Dispose您自己加载的所有内容。

您可能还希望将事件处理程序附加到RenderTarget2D.ContentLost事件,以便在图形设备“丢失”的情况下重新调整大小的纹理。