【发布时间】:2012-03-02 04:04:06
【问题描述】:
当我绘制一个拉伸的Texture2D 时,像素会收到类似模糊的效果。
我想在我的游戏中使用“像素化”图形,并且想知道如何禁用它以支持最简单的最近邻缩放。
我创建了这张图片用于说明:(x4 缩放)
我可以通过什么方式做到这一点?
【问题讨论】:
-
+1 用于星控精灵。
当我绘制一个拉伸的Texture2D 时,像素会收到类似模糊的效果。
我想在我的游戏中使用“像素化”图形,并且想知道如何禁用它以支持最简单的最近邻缩放。
我创建了这张图片用于说明:(x4 缩放)
我可以通过什么方式做到这一点?
【问题讨论】:
在 XNA 4 中,更改 SpriteBatch.Begin() 以将采样器状态设置为 SamplerState.PointClamp
【讨论】:
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, DepthStencilState.None, RasterizerState.CullCounterClockwise);,它工作得很好。谢谢!
如果您使用着色器来绘制图像,您可以修改采样器状态:
sampler2D mySampler = sampler_state
{
Texture=<SomeTexture>;
Filter=POINT;
};
点采样应防止 GPU 在对图像进行采样时进行插值,这可能是导致您的抗锯齿/模糊行为的原因。
如果您只是使用SpriteBatch 来绘制图像,您可以使用以下方式设置过滤器:
Device.SamplerStates[0] = SamplerState.PointClamp;
另外,您似乎必须将 SpriteBatch 设置为使用即时模式。 See this article on MSDN for more information,或this thread on the App Hub forums。
这是一个较早的 SO 线程,可能会有所帮助:
See this thread for more information.
使用归一化坐标 (0..1, 0..1) 而非纹素坐标对纹理进行采样。 GPU 将为给定的纹理坐标找到四个最接近的纹素,并根据该正方形内采样点的位置在它们之间进行插值。
所以,如果我有一个 10 x 10 像素的纹理,并且我尝试从 (0.15, 0.15) 读取,GPU 将在 (1,1),(2,1) 处的纹素之间进行插值),(1,2) 和 (2,2)。在这种情况下,0.05 应该导致屏幕上的结果像素只是周围四个像素的平均值。但是,如果在 (0.19, 0.19) 处对纹理进行采样,则生成的颜色将严重偏向 (2,2) 处的纹素。
点采样将导致 GPU 始终从底层纹理读取准确的颜色,而不是加权采样区域周围的坐标。
这是一个有效的 .Draw() 方法来说明所有这些:
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Black);
var largeRect = new Rectangle(50, 50, sprite.Width * 3, sprite.Height * 3);
/// start the batch, but in immediate mode to avoid antialiasing
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.Opaque);
/// set the filter to Point
GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp;
/// draw the sprite
spriteBatch.Draw(sprite, largeRect, Color.White);
/// done!
spriteBatch.End();
// TODO: Add your drawing code here
base.Draw(gameTime);
}
【讨论】:
spriteBatch.Draw(...) 方法。将其绘制到更大的矩形并使用scale 属性都会产生这种效果。
SamplerStates[0].Filter 的值会导致错误,指出它是只读属性。
Draw 方法或LoadContent 方法中分配这个每一帧吗? (目前两者似乎都不起作用......)
您需要确保您的 x,y 坐标是整数值。分数坐标或尺寸会导致应用抗锯齿来模拟“分数”像素偏移。
因此模糊。
【讨论】:
Rectangle 对象绘制仍然会产生不想要的效果。无论如何,问题得到了回答。 :)