我想写一些生成JPG图像的单元测试。 我正在使用XNA开发一款游戏,并希望进行一些渲染测试,我可以运行并目视检查我没有破坏任何东西等。
我有一个单元测试项目,它调用我的代码来生成 XNA 对象,如三角形条带,但所有渲染示例似乎都假设我有一个游戏对象,并且正在渲染到相关的 GraphicsDevice,这是屏幕上的一个窗口。
如果可能的话,我想在内存中渲染,只保存 JPG 图像,以便在测试完成运行后进行检查。 或者,我想我可以在单元测试中实例化一个 Game 对象,渲染到屏幕,然后转储到 JPG,如下所述:如何使用 C# 和 XNA 制作屏幕截图?
但这听起来不是很有效。
那么,简单地说,有没有办法在写入内存缓冲区的 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);
}
}
然后在我的测试中,我只是实例化它并使用提供的图形设备:
[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");
}
}
我确定它不是没有错误的,但它现在似乎有效。