C# 用于创建JPG图像的XNA图形设备

C# 用于创建JPG图像的XNA图形设备,c#,unit-testing,xna,rendering,C#,Unit Testing,Xna,Rendering,我想编写一些生成JPG图像的单元测试。我正在使用XNA开发一个游戏,希望有一些渲染测试,我可以运行并目视检查我是否破坏了任何东西等等 我有一个单元测试项目,它调用我的代码来生成XNA对象,比如三角形条,但是所有的渲染示例似乎都假设我有一个游戏对象,并且正在渲染到关联的GraphicsDevice,它是屏幕上的一个窗口 如果可能的话,我想在内存中渲染,只保存JPG图像,以便在测试完成后检查。或者,我想我可以在单元测试中实例化一个游戏对象,渲染到屏幕上,然后转储到JPG,如下所述: 但这听起来不是很

我想编写一些生成JPG图像的单元测试。我正在使用XNA开发一个游戏,希望有一些渲染测试,我可以运行并目视检查我是否破坏了任何东西等等

我有一个单元测试项目,它调用我的代码来生成XNA对象,比如三角形条,但是所有的渲染示例似乎都假设我有一个游戏对象,并且正在渲染到关联的GraphicsDevice,它是屏幕上的一个窗口

如果可能的话,我想在内存中渲染,只保存JPG图像,以便在测试完成后检查。或者,我想我可以在单元测试中实例化一个游戏对象,渲染到屏幕上,然后转储到JPG,如下所述:

但这听起来不是很有效


那么,简单地说,有没有一种方法可以在XNA游戏之外实例化一个写入内存缓冲区的GraphicsDevice对象?

我最后从System.Windows.Forms实例化了一个控件对象。我将此作为单元测试项目的一部分,因此我的游戏不依赖于Windows窗体

这是我用来为测试生成JPG的功能的类:

public class JPGGraphicsDeviceProvider
{
    private Control _c;
    private RenderTarget2D _renderTarget;
    private int _width;
    private int _height;

    public JPGGraphicsDeviceProvider(int width, int height)
    {
        _width = width;
        _height = height;
        _c = new Control();

        PresentationParameters parameters = new PresentationParameters()
        {
            BackBufferWidth = width,
            BackBufferHeight = height,
            BackBufferFormat = SurfaceFormat.Color,
            DepthStencilFormat = DepthFormat.Depth24,
            DeviceWindowHandle = _c.Handle,
            PresentationInterval = PresentInterval.Immediate,
            IsFullScreen = false,
        };

        GraphicsDevice = new GraphicsDevice(GraphicsAdapter.DefaultAdapter,
                                            GraphicsProfile.Reach,
                                            parameters);

        // Got this idea from here: http://xboxforums.create.msdn.com/forums/t/67895.aspx
        _renderTarget = new RenderTarget2D(GraphicsDevice,
            GraphicsDevice.PresentationParameters.BackBufferWidth,
            GraphicsDevice.PresentationParameters.BackBufferHeight);

        GraphicsDevice.SetRenderTarget(_renderTarget);
    }

    /// <summary>
    /// Gets the current graphics device.
    /// </summary>
    public GraphicsDevice GraphicsDevice { get; private set; }

    public void SaveCurrentImage(string jpgFilename)
    {
        GraphicsDevice.SetRenderTarget(null);
        int w = GraphicsDevice.PresentationParameters.BackBufferWidth;
        int h = GraphicsDevice.PresentationParameters.BackBufferHeight;

        using (Stream stream = new FileStream(jpgFilename, FileMode.Create))
        {
            _renderTarget.SaveAsJpeg(stream, w, h);
        }
        GraphicsDevice.SetRenderTarget(_renderTarget);
    }
}

我肯定它不是没有bug的,但它现在似乎可以工作了

我尝试使用它唯一的构造函数实例化一个新的GraphicsDevice,它抛出一个异常,说“PresentationParameters.DeviceWindowHandle”不能为null。我应该尝试构建一个只用于渲染的窗口,还是有其他方法?我将System.Windows.Forms添加到我的单元测试项目中,并实例化了一个控件对象。现在,当我尝试获取后缓冲区数据以抓取屏幕截图时,我得到了一个例外:XNA Framework Reach配置文件不支持GetBackBufferData如果要使用
GetBackBufferData()
,可以使用
HiDef
配置文件创建图形设备。不过,拍摄屏幕截图的更好方法是编写代码,使其可以输出到渲染目标而不是后台缓冲区,然后使用其
SaveAsJpeg()
方法保存该渲染目标。
[TestClass]
public class RenderTests
{
    private JPGGraphicsDeviceProvider _jpgDevice;
    private RenderPanel _renderPanel;
    public RenderTests()
    {
        _jpgDevice = new JPGGraphicsDeviceProvider(512, 360);
        _renderPanel = new RenderPanel(_jpgDevice.GraphicsDevice);
    }

    [TestMethod]
    public void InstantiatePrism6()
    {
        ColorPrism p = new ColorPrism(6, Color.RoyalBlue, Color.Pink);

        _renderPanel.Add(p);
        _renderPanel.Draw();

        _jpgDevice.SaveCurrentImage("six-Prism.jpg");
    }
}