【问题标题】:'Nearest Neighbor' zoom“最近邻”缩放
【发布时间】:2012-03-02 04:04:06
【问题描述】:

当我绘制一个拉伸的Texture2D 时,像素会收到类似模糊的效果。

我想在我的游戏中使用“像素化”图形,并且想知道如何禁用它以支持最简单的最近邻缩放。

我创建了这张图片用于说明:(x4 缩放)

我可以通过什么方式做到这一点?

【问题讨论】:

  • +1 用于星控精灵。

标签: c# image xna xna-4.0


【解决方案1】:

在 XNA 4 中,更改 SpriteBatch.Begin() 以将采样器状态设置为 SamplerState.PointClamp

【讨论】:

  • 在 MSDN 上查找默认值后,我以这种方式使用了该方法:spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, DepthStencilState.None, RasterizerState.CullCounterClockwise);,它工作得很好。谢谢!
【解决方案2】:

如果您使用着色器来绘制图像,您可以修改采样器状态:

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 属性都会产生这种效果。
  • @Acidic 已更新。 SpriteBatch 提供了一个用于设置过滤方法的属性。
  • 尝试更改SamplerStates[0].Filter 的值会导致错误,指出它是只读属性。
  • @Acidic 再次更新;您必须创建一个新的 SamplerState 对象并将其分配给 device.SamplerStates[0],或者使用预定义的 SamplerState.* 成员之一。
  • 感谢您到目前为止的帮助。我应该在Draw 方法或LoadContent 方法中分配这个每一帧吗? (目前两者似乎都不起作用......)
【解决方案3】:

您需要确保您的 x,y 坐标是整数值。分数坐标或尺寸会导致应用抗锯齿来模拟“分数”像素偏移。

因此模糊。

【讨论】:

  • 使用Rectangle 对象绘制仍然会产生不想要的效果。无论如何,问题得到了回答。 :)
猜你喜欢
  • 2021-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-11
  • 2021-12-26
  • 1970-01-01
  • 1970-01-01
  • 2016-10-08
相关资源
最近更新 更多