使用XNA ContentPipeline在没有完整XNA GS的计算机上导出文件


9

我的游戏使用内容管道在运行时加载spriteSheet。游戏的美术师将修改后的Spritesheet发送给我,然后在计算机中进行构建并向他发送了更新的项目。因此,我正在寻找一种在他的计算机中生成xnb文件的方法(这是内容管道的输出),而无需他安装完整的XNA Game studio。

1)我不希望我的艺术家安装VS + Xna(我知道有VS的免费版本,但是一旦我们向团队中添加更多人,它将无法扩展)。2)我对在Xbox中运行此编辑器/工具不感兴趣,因此只能使用Windows解决方案。3)我知道MSBuild选项,但它们需要完整的XNA

我研究了Shawn的博客,发现使用Msbuild Sample的选项或XNA 4.0中的新选项在这里看起来很有希望但似乎有相同的限制:需要安装完整的XNA GS,因为ContentPipeline不属于XNA redist。

那么有人找到了解决方法吗?

Answers:


11

似乎正确的答案是跳过ContentPipeline,并使用Texture2D.FromStream在运行时加载纹理。这种方法在PC上效果很好,即使性能影响不大,但在接近发布日期后,我就可以对其进行优化。就目前而言,具有为编辑器和游戏动态修改内容的能力正是我所需要的。内容冻结后,我可以通过返回ContentPipeline对其进行优化。

既然您选择了这条路线,我必须警告您,实际上这并不像仅仅使用Texture2D.FromStream两条路那样简单,原因有两个:

问题1-缺少预乘alpha支持

XNA4现在默认使用预乘alpha格式的颜色处理纹理。通过内容管道加载纹理时,该处理将自动为您完成。不幸的是,Texture2D.FromStream它不会做同样的事情,因此任何需要一定透明度的纹理都将被错误地加载和渲染。下面是说明问题的屏幕截图:

在此处输入图片说明

因此,为了获得正确的结果,您需要自己进行处理。我将展示的方法使用GPU进行处理,因此速度非常快。它基于这篇伟大的文章。当然,您也可以指示SpriteBatch以旧的NonPremultiplyAlpha模式进行渲染,但是我不建议这样做。

问题2-不支持的格式

内容管道支持的格式超过Texture2D.FromStream。特别是,Texture2D.FromStream仅支持png,jpg和gif。另一方面,内容管道支持bmp,dds,dib,hdr,jpg,pfm,png,ppm和tga。如果您尝试通过加载惯用的格式,Texture2D.FromStream则会获得InvalidOperationException很少的其他信息。

我确实需要引擎上的bmp支持,因此对于这种特殊情况,我发现了一种可行的解决方法。我不知道其他任何格式。我的方法的不足之处在于,您需要在工程中添加对该System.Drawing程序集的引用,因为它利用了GDI Image.FromStream,该GDI 支持的格式比的更多Texture2D.FromStream

如果您不关心支持bmp,则可以轻松删除该解决方案的这一部分,而只需进行预乘alpha处理即可。

解决方案-简单版本(较慢)

首先,如果您不关心支持bmp ,这是最简单的解决方案。在此示例中,处理阶段完全在CPU上完成。它比我将在下面显示的替代方案(我对两个解决方案都进行了基准测试)要慢一些,但更易于理解:

public static Texture2D FromStream(GraphicsDevice graphicsDevice, Stream stream)
{
    Texture2D texture = Texture2D.FromStream(graphicsDevice, stream);
    Color[] data = new Color[texture.Width * texture.Height];
    texture.GetData(data);
    for (int i = 0; i != data.Length; ++i)
        data[i] = Color.FromNonPremultiplied(data[i].ToVector4());
    texture.SetData(data);
    return texture;
}

如果您关心bmp,那么您需要做的就是先使用GDI加载图片,然后在内部将其转换为PNG之前将其传递给Texture2D.FromStream。这是执行此操作的代码:

// Load image using GDI because Texture2D.FromStream doesn't support BMP
using (Image image = Image.FromStream(stream))
{
    // Now create a MemoryStream which will be passed to Texture2D after converting to PNG internally
    using (MemoryStream ms = new MemoryStream())
    {
        image.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
        ms.Seek(0, SeekOrigin.Begin);
        texture = Texture2D.FromStream(_graphicsDevice, ms);
    }
}

解决方案-复杂版本(更快)

最后,我在项目中使用的方法是改为使用GPU进行处理。在此方法中,您需要创建一个渲染目标,正确设置一些混合状态,并使用SpriteBatch绘制两次图像。最后,我遍历整个RenderTarget2D并将内容克隆到一个单独的Texture2D对象中,因为RenderTarget2D是易失性的,无法忍受更改后缓冲区大小等事情,因此进行复制更安全。

有趣的是,即使有所有这些,在我的测试中,这种方法的执行速度也比CPU方法快约3倍。因此,它绝对比遍历每个像素并自己计算颜色快。该代码有点长,所以我将其放在了pastebin中:

http://pastie.org/3651642

只需将该类添加到您的项目中,即可使用它,方法很简单:

TextureLoader textureLoader = new TextureLoader(GraphicsDevice);
Texture2D texture = textureLoader.FromFile("Content/texture.png");

注意:您只需要TextureLoader为整个游戏创建一个实例。另外,我正在使用BMP修复程序,但是如果不需要并获得大量性能,或者仅将needsBmp参数保留为false ,则可以将其删除。


哇,太好了!这将对我有很大帮助:)非常感谢David,我很感激。
krolth 2012年

+1实际上,FromStream就像您的其他示例一样,我正在使用包含32位位图(保存为png)的内存流,但是此方法未创建预乘纹理。明确地将每种颜色预乘就可以了,谢谢。
Groo

3

我认为大多数团队都会将xnb更改(实际上,所有更改实际上都是xnb includud)提交给他们的svn服务器(可以免费设置),并允许其他人(艺术家等)更新自己的工作副本。

实际上,对于艺术家来说,这是对原始(pre-xnb)艺术进行版本控制的好机制。他将对此进行更改,您将更新它的工作副本,对其进行构建(在过程中使其成为xnb),提交您的更改,他更新其工作的工作副本,每个人都有所有更改。(您有最新的原始艺术品,他有xnb。

这也很好地扩展。


所以你是说你不认为这可以做到吗?您的建议是将版本控制添加到XNB和Sprite,我们已经在这样做了。但是我不喜欢它,因为我成了他们的瓶颈。我已经为他们编写了一个工具来编辑动画,他们可以在游戏中尝试它们。但是,如果他们对Spritesheet进行了更改,则需要等到我构建它之后才能看到它。您可以想象,如果他们犯错了,他们需要再次犯错。
krolth 2012年

@krolth让您的艺术家获得VS Express和XNA作为将他们设置为可以在项目上工作的一部分有什么大不了的?我认为在这一点上,必须编写指南并帮助人们完成指南的权衡将远远超过您现在正在失去的生产力,因为艺术家无法在引擎中看到他们的作品。要简化此过程,请给他们一个.BAT文件,他们可以双击以重新编译所有内容,而无需打开IDE。而且,如果他们仅运行OS X,那就很难了。欢迎来到游戏开发者。他们可以提交其sprite,并等待下一个提交的XNB。
michael.bartnett 2012年

没什么大不了的,只是痛苦。但是我想这是必须要做的。感谢大家的回答/评论!
krolth 2012年

1

我一直在对此进行调查,并将其发布给有相同问题的人。

似乎正确的答案是跳过ContentPipeline,并使用Texture2D.FromStream在运行时加载纹理。这种方法在PC上效果很好,即使性能影响不大,但在接近发布日期后,我就可以对其进行优化。

就目前而言,具有为编辑器和游戏动态修改内容的能力正是我所需要的。内容冻结后,我可以通过返回ContentPipeline对其进行优化。


你测试正确了吗?仅凭我的经验Texture2D.FromStream是不够的。这样做的原因是,由于版本4 XNA具有预乘的alpha纹理,并且内容管道会自动为您处理此过程,Texture2D.FromStream因此不会这样做,因此在绘制具有透明度的精灵时您可能会遇到问题。如果您愿意,我可以发布有效的解决方案。
David Gouveia,2012年

另外,在内容管道Texture2D.FromStream支持.BMP时不支持加载文件。如果您之前使用过任何.BMP资产然后切换到,这可能会使您失望Texture2D.FromStream。对于该限制,我也有一种解决方法。我将继续发布它。
David Gouveia 2012年

0

检查该项目

这将使您的艺术家可以使用默认XNA内容管道支持的几乎所有内容创建XNB。尽管您的艺术家不需要Visual Studio,但仍需要重新分发XNA框架。


感谢您的指导。查看代码似乎是对我引用的Microsoft示例的修改。这取决于是否已安装完整的XNA Game Studio(请参阅ContentBuilder.cs)。您为什么不这样认为?
krolth 2012年

我不认为不是。如果要使用内容管道,则必须拥有完整的游戏工作室。但是,该项目确实使您的艺术家不必使用Visual Studio。唯一的其他选择是重写内容管道。
ClassicThunder2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.