所以我用XNA 3.1做了一件事,我有很多通过像素着色器应用的单独效果.它们来自各种来源,例如特殊攻击,环境等.我遇到的问题是我注意到帧速率的显着降低.
目前,我正在将整个场景绘制到RenderTarget2D,然后我将所有效果应用到.我存储了一个包含效果及其ID的SortedDictionary(这些ID用于在运行时更改参数),我正在迭代它并逐个应用每个效果:
foreach(KeyValuePair<Ref<int>,Effect> p in renderEffects)
{
Effect r = p.Value;
g.SetRenderTarget(0, MainGame.MainRenderTarget);
//Change RenderTarget to allow code to grab existing texture in the same draw area.
levelDraw = MainGame.LevelRenderTarget.GetTexture();
//Change back to draw back to this texture, allowing render effects to be layered.
g.SetRenderTarget(0, MainGame.LevelRenderTarget);
MainGame.StartDraw(MainGame.GameBatch);
//Starts the sprite batch and sets some parameters
r.Begin();
r.CurrentTechnique.Passes[0].Begin();
MainGame.GameBatch.Draw(levelDraw, new Rectangle(0, 0, levelDraw.Width, levelDraw.Height), Color.White);
r.CurrentTechnique.Passes[0].End();
r.End();
MainGame.GameBatch.End();
}
Run Code Online (Sandbox Code Playgroud)
现在,当仅分层3个效果时,这会产生明显的帧丢失,当应用10时,它会从60FPS下降到16FPS,这当然是不可接受的.我想知道是否有更有效的方法来做到这一点.考虑到我只有一个纹理,我认为我可以将效果组合到一个文件中并执行多次传递而不会重新获取纹理.但是,我不确定这是否可行.
我不确定最好的方法是如何做到这一点,尽管我认为必须有一种比我正在做的更好的方式.
我正在使用XNA中的一个项目,我正在使用一些相当大的纹理,我将其作为Texture2D对象加载到游戏中,并且在屏幕上绘制的内容比它们加载的要小得多.原因是我需要在不同的地方以各种不同的尺寸绘制它们,虽然我可以用多个纹理来做这个,但这样做是不切实际的.
我的问题是,在缩小它们时,XNA似乎不会对这些Texture2D对象进行抗锯齿处理.我已经设定:
graphics.PreferMultiSampling = true;
Run Code Online (Sandbox Code Playgroud)
并且
spriteBatch.Begin(SpriteBlendMode.AlphaBlend);
Run Code Online (Sandbox Code Playgroud)
但无济于事.我也尝试过各种涉及GraphicsDevice过滤器的东西,但老实说,我并不知道自己在做什么.
显然,我正在使用spriteBatch绘制它,但除此之外,我绘制它的方式没什么特别有趣的.
这是一个(放大的)例子,说明正在发生的事情,以及我正在努力实现的目标:
如您所见,XNA在重新缩放图像时不提供任何抗锯齿功能.有没有办法可以强制它这样做,以使边缘看起来更干净?
好的,我们走了.我正在尝试创建一个应用程序,因为它的渲染器使用XNA作为基础.此项目中必需的一件事是打开一个新窗口(作为对话框),其中嵌入了一个单独的XNA渲染面板.我正在使用它作为交互式预览面板,所以我绝对需要XNA来渲染.然而,似乎XNA并没有很好地做到这一点.我自己尝试了各种各样的东西,但无济于事(产生错误,无法正确渲染,或渲染错误的宽高比等).通常情况下,我会在这里发布代码,但由于我运气不好,所以发布的内容并不多.
我的应用程序目前包含一个嵌入在Form中的XNA应用程序,我有一个按钮来打开预览面板,理论上它应该弹出一个包含XNA渲染器的Form对话框,以允许我绘制预览.我已经尝试了好几个小时,无处可去,所以我在这里要求一些帮助.
不管怎么说,还是要谢谢你.
编辑:好的,我已经取得了一些进展,但我有两个问题.首先,使用精灵批处理绘制的任何纹理都显示正确的尺寸,但是填充了纯黑色.此外,当我打开对话框,然后关闭它,并关闭应用程序时,我得到一个AccessViolationException.我强烈怀疑这两个错误是以某种方式联系在一起的.
这是我的代码初始化预览对话框.(a是一个自定义类,基本上由Texture2D对象的LinkedList组成).
animPrev = new AnimationPreview(a);
animPrev.Show();
Run Code Online (Sandbox Code Playgroud)
我的AnimationPreview类是Form类的扩展,包含一个PreviewControl对象,它是XNA Winforms示例中的GraphicsDeviceControl的扩展.请注意,由于各种原因,我的主窗体扩展了XNA Game类.
PreviewControl对象设置如下:
protected override void Initialize()
{
sb = new SpriteBatch(GraphicsDevice);
Application.Idle += delegate { Invalidate(); };
}
Run Code Online (Sandbox Code Playgroud)
Draw方法包含:
protected override void Draw()
{
GraphicsDevice.Clear(Microsoft.Xna.Framework.Graphics.Color.Violet);
if (frame != null)
{
sb.Begin();
sb.Draw(Image, Vector2.Zero, Color.White);
sb.End();
}
}
Run Code Online (Sandbox Code Playgroud)
这会像预期的那样清除紫罗兰色的背景,并绘制一个与Image相同大小的黑盒子.这不是预期的.希望有人可以帮助我.
注意:可接受的替代方法是将XNA Texture2D对象转换为System.Drawing.Image对象.但是,我使用XNA 3.1,所以我不能只将纹理保存到流并重新加载它.实际上,在尝试过这个之后,它有点狡猾,而且很慢,所以我宁愿不这样做.