精灵渲染速度模糊


9

在为游戏增加速度之后,我感觉我的纹理在抽搐。我以为只是我的眼睛,直到最终在屏幕截图中捕获了它:

在此处输入图片说明

左边的是我的游戏中呈现的内容;右边的是粘贴的原始精灵。(这是Photoshop的屏幕截图,放大了6倍。)

请注意,边缘是混叠的-看起来几乎像是亚像素渲染。实际上,如果我没有强迫我的精灵(位置和速度为整数)使用整数值进行绘制,我会发誓MonoGame使用浮点值进行绘制。但事实并非如此。

这些事情看起来模糊的原因可能是什么?没有施加速度就不会发生这种情况。

确切地说,我的SpriteComponent班级有一个Vector2 Position领域。当我致电时Draw,我实际上是使用new Vector2((int)Math.Round(this.Position.X), (int)Math.Round(this.Position.Y))该职位。

我之前有个bug,即使静止的物体也会抖动-这是由于我使用了直线Position向量,而不是将值四舍五入到ints。如果我使用Floor/ Ceiling而不是圆形,则精灵会下沉/悬停(两种方式各有一个像素差异),但仍会模糊。


1
这可能与所应用的纹理过滤有关吗?
OriginalDaemon

您有着色器代码吗?有人在两个轴上都添加了半个像素,以使像素居中。不过不确定,我认为这只是DirectX的事情。
William Mariager

3
停用过滤是一种解决方法,而不是解决方案。
阿奇

1
渲染对速度一无所知,因此传递给SpriteBatch.Draw的位置,大小或其他任何东西都不一样,或者在添加速度之前存在错误。你怎么称呼SpriteBatch.Draw呢?
阿奇

1
@ ashes999您是否调试了此调用并检查了this.X,this.Y和this.origin?this.origin设置为什么?当此Draw调用相同时,渲染结果基本上是没有办法的。
阿奇

Answers:


3

好吧,这很尴尬。

事实证明,我不是在使用整数位置进行绘制,而是使用浮动位置。阿奇以他的评论向我指出了正确的道路@ashes999 did you debug this call and checked this.X, this.Y and this.origin?

添加跟踪语句后,我注意到没有任何跟踪。事实证明,我的SpriteComponent类正确使用了整数值,但SpriteSheetComponent仍使用raw中的浮点值Vector2 Position

尽管我没有尝试纹理过滤和钳制,但是我怀疑这些不是正确的更改,因为我绘制的2D图像的宽度和高度与源图像的宽度和高度相同(没有缩放比例)。


1
完成,很高兴您找到了它!
阿奇

2

XNA使用DirectX9,它使用像素的中心作为其位置。当使用基于Vector2的draw类重载时,这一点很明显。我相信减去(.5,.5)应该可以解决您的问题。

更多信息在这里。


从技术上讲,我无法做到这一点,因为我传入了一个Vector2 int, int作为参数。除此之外,当我没有任何物体运动时,一切看起来都很好。
ashes999 2012年

物体在运动中是什么意思?XNA没有动作的概念,它也会在您所说的地方绘制内容。它是一系列固定的快照。还要尝试使用Rectangle重载,因为无论如何都要舍入到矩形。
ClassicThunder 2012年

我有自己的速度实现方式。SpriteComponent具有一个Vector2位置,该位置根据速度随着浮动而增加;绘制时,我Vector2positionX和Y的整数(四舍五入)版本创建了一个新对象。这不是问题,因为没有速度的静止对象看起来很好。
ashes999

因此,您说有一个位置矢量p和一个速度矢量v,将它们相加,例如p + = v,然后使用舍入值创建p的副本。而且尽管抽奖电话是相同的,这是否会产生与先前p + = v相同的位置而产生不同的值?因为那没有道理。
ClassicThunder12年

是的,@ Archy也是如此。让我调试并再次检查。我在p += v期间添加Update,然后使用渲染new Vector2((int)Math.Round(p.X), (int)Math.Round(p.Y)))
ashes999 2012年

2

渲染对速度一无所知,因此传递给SpriteBatch.Draw的位置,大小或其他任何东西都不相同,或者在添加速度之前存在错误。你怎么称呼SpriteBatch.Draw呢?

您是否调试了此调用并检查了this.X,this.Y和this.origin?this.origin设置为什么?当此Draw调用相同时,基本上没有办法使速度的渲染结果有所不同。


1

问题可能是纹理过滤已打开。如果不确定这意味着什么,请考虑以下情况:图像的宽度为2个像素:第一个像素为黑色,第二个像素为白色。如果放大此纹理,并且启用了纹理过滤,则会看到它变得模糊,并且黑白像素之间的区域使用渐变灰色。

具有过滤功能和不具有过滤功能的游戏的经典示例是Super Mario 64,它具有过滤功能,而Doom没有。

如果不使用速度,则可以将Sprite放置在适当的位置,以使纹理的中心位于XNA(或使用任何底层api)捕获颜色的采样点上。当您以浮动速度移动时,Sprite的位置会发生变化,因此采样点可能不会直接与像素中心对齐,因此最终结果是正在获得最近像素平均值的颜色用于渲染。

您可以通过简单地将Sprite真正呈现在屏幕上来验证筛选是否已打开。如果模糊,那就是问题所在。

如果您必须在渲染中具有像素完美的精度,则需要将float值存储在某个位置,但是要使用整数值作为要渲染的对象的位置...或者当然,您可以关闭过滤如果您的游戏不需要它。

您可能还需要阅读此内容


就像我在问题中提到的那样,当我调用时,我已经在使用整数作为位置以及原始图像大小了Draw。因此,我不确定情况可能会如何-但我将尝试大规模渲染并查看关闭纹理过滤是否会有所帮助。
ashes999

1

尝试在SpriteBatch.Begin调用中将SamplerState设置为SamplerState.PointClamp。

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.