【问题标题】:Windows uses Point sampling when stretching from a DirectX BackBuffer to the WIndow从 DirectX BackBuffer 拉伸到窗口时,Windows 使用点采样
【发布时间】:2012-07-12 20:35:41
【问题描述】:

Windows7 使用点过滤从我的 DirectX9 后台缓冲区延伸到窗口客户区。当窗口调整大小时,拉伸的伪影看起来很糟糕。我们可以通过更改后台缓冲区大小来避免这种情况,但这需要调用 IDirect3DDevice9::Reset()。这会导致在调整大小时出现黑屏和一小段延迟。

有什么方法可以改进 windows 使用的过滤方法吗?或者,有什么方法可以从不同的 DirectX 表面(例如渲染目标)更新窗口?


我正在使用非托管 C++ DirectX 代码。假设我有一个 1280 x 720 的后缓冲表面:

D3DPRESENT_PARAMETERS  presentParams;
presentParams.BackBufferWidth  = 1280;
presentParams.BackBufferHeight = 720;
gD3D->CreateDevice(
    0, D3DDEVTYPE_HAL, hWnd,               
    D3DCREATE_HARDWARE_VERTEXPROCESSING,
    &presentParams,
    &pD3D9Device);

但我有一个 1920 x 1080 的窗口:

hWnd = CreateWindowExA(NULL, "WindowClass", winName,
                flags, 0, 0, 1920, 1080,
                NULL, NULL, hInstance, NULL);

当我调用 Present() 时,窗口会将我的 DirectX 后台缓冲区拉伸到窗口。但是,它们的拉伸似乎没有执行任何过滤。

pD3D9Device->Present(NULL, NULL, NULL, NULL);

我可以调整后备缓冲区的大小,但这需要调用 Reset() 和 Reset() 会导致视频内存表面丢失。

【问题讨论】:

  • 我删除了windowswindows-7 标签,因为它们毫无意义。问题是关于 DirectX9,这显然是特定于 Windows 的,DirectX 正在进行采样/渲染,而不是 Windows 本身(如果 Windows 这样做,你就不需要 DirectX)。
  • Windows 只是对窗口进行拉伸 blt(渲染后)。
  • 通常的做法是让后台缓冲区和窗口大小相同——如果不能改变缓冲区,就改变窗口。我认为 DirectX 正在使用最快的方式将图像显示到窗口,这不涉及过滤。您可以通过使缓冲区成为窗口大小的整数除法来最小化失真。
  • 是的,这是有道理的。在用户将窗口大小调整为任意大小的情况下,我们试图优雅而快速地处理它。

标签: c++ directx directx-9


【解决方案1】:

如果您发布您所询问的特定操作的一些代码片段会很有帮助,但是如果您使用 GDI(非托管 Win32)StretchBlt 函数,您可以使用 HALFTONE 获得更好的调整大小行为,根据这篇文章:Is StretchBlt HALFTONE == BILINEAR for all scaling?

如果您使用 GDI+ (WinForms/C#),您可以使用 g.InterpolationMode = InterpolationMode.Bilinear 获得双线性(或更好的)插值(查看 MSDN 了解所有选项)。请注意,GDI+ 通常比 GDI(或 DX)慢

(本文中有些相关信息:Bilinear interpolation - DirectX vs. GDI+

【讨论】:

  • 感谢您的信息。但是我没有使用 GDI,只是使用 DirectX。我只是想避免在 DirectX 中调整我的后备缓冲区的大小,但似乎这是唯一的方法。
【解决方案2】:

您是否尝试过 IDirect3DDevice9::SetSamplerState?

http://msdn.microsoft.com/en-us/library/windows/desktop/bb174698(v=vs.85).aspx

实际上,我正在寻找类似的问题。我使用 D3D9 纹理来渲染一些图像。在 Vista 上,SetSamplerState 加上线性纹理过滤有助于减少因大量调整窗口大小而导致的伪影。但在 Windows7 上并非如此。我不确定这两个平台的处理方式有何不同。

【讨论】:

    【解决方案3】:

    当我尝试在窗口中播放视频时遇到这个问题,并且想要调整窗口大小而不需要重置设备。

    我从mpc-hc源代码中找到了解决方案:https://github.com/mpc-hc/mpc-hc/blob/develop/src/filters/renderer/VideoRenderers/SyncRenderer.cpp

    1) 使后缓冲区变大(您期望窗口的最大尺寸)-> 我选择了屏幕尺寸

    2) 仅在大小等于窗口的矩形上绘制

    3) 使用 Device.Present(srcrect, destrect)。 srcrect 和 destrect 是同一个矩形,都是窗口大小。

    我是 directX 的新手,但这个解决方案对我有用。

    【讨论】:

    • 看来应该可以了!我得试试看。
    猜你喜欢
    • 2012-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-11
    • 1970-01-01
    相关资源
    最近更新 更多