DirectWrite 渲染问题 - 四边形似乎重叠,有一些锯齿

DirectWrite rendering issues - quads seem to be overlapping, with some aliasing

问题截图:

以下是相关的代码位 - 为清楚起见,省略了错误处理等。

D2D1_BITMAP_PROPERTIES1 bp;
bp.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
bp.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
bp.dpiX = 96.0f;
bp.dpiY = 96.0f;
bp.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
bp.colorContext = nullptr;

...

d2dDeviceContext->SetTarget(targetBitmap);

....

writeFactory->CreateTextFormat(L"Arial", nullptr, DWRITE_FONT_WEIGHT_LIGHT, DWRITE_FONT_STYLE_NORMAL, 
DWRITE_FONT_STRETCH_NORMAL, 32.0f, L"en-US", &textFormatAccountCreds);
textFormatAccountCreds->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING);
textFormatAccountCreds->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_NEAR);

std::wostringstream outAccountName;
outAccountName << "Account Name:";
writeFactory->CreateTextLayout(outAccountName.str().c_str(), (UINT32)outAccountName.str().size(), textFormatAccountCreds, (float)800, 
(float)600, &textLayoutAccountName);

const float color[4] = { 1.0f, 0.5f, 0.3f, 1.0f };
immediateContext->ClearRenderTargetView(renderTargetView, color);

d2dDeviceContext->BeginDraw();
d2dDeviceContext->DrawTextLayout(D2D1::Point2F(2.0f, 5.0f), textLayoutAccountName, blackBrush);
d2dDeviceContext->EndDraw();

swapChain->Present(0, 0);

如您在屏幕截图中所见,文本呈现效果很差 - 具体来说,第一个 "n" 似乎在左侧被截断,第一个 "u" 也是如此,并且首都 "N" 出现了一些奇怪的别名。我可以更改文本的 size/position,渲染问题的表现有所不同,但它们仍然存在。

我在这里错过了什么?我浏览了 MSDN 上的大部分 DirectWrite 文档,但不清楚我的问题是什么。我确实看到有人提到我应该指定我的文本相对于 dpi 比例的起始位置,但是这个例子非常模糊。

还值得一提的是,我将 Direct3D 和 DirectWrite 与 Direct2D 一起使用,其方式与 this tutorial 中所见类似。不确定这是否会导致我的问题。

如有任何帮助,我将不胜感激。非常感谢。

我明白了。为 VTT 干杯,为我指明了正确的方向。

HWND hWnd = CreateWindow(
    szWindowClass,
    szTitle,
    WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    800,
    600,
    NULL,
    NULL,
    hInstance,
    NULL
);

...

DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory(&sd, sizeof(sd));
sd.BufferCount = 1;
sd.BufferDesc.Width = 800;
sd.BufferDesc.Height = 600;
sd.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = hWnd;
sd.SampleDesc.Count = 4;
sd.SampleDesc.Quality = m4xMsaaQuality - 1;
sd.Windowed = TRUE;
sd.Flags = 0;

显然,您传递给 CreateWindow 的尺寸包括 space 用于 window 的菜单和边框,因此您可以在 [=23] 中绘制 space 的实际尺寸=] 更小。

RECT rect;
GetClientRect(hWnd, &rect);
// Returns 784 x 561

所以解决方案是: -省略在 DXGI_SWAP_CHAIN_DESC 中指定 sd.BufferDesc.Width 和 sd.BufferDesc.Height,因为当它们设置为 0 时,它们将从父 window 继承尺寸。 - 当稍后需要实际 window 尺寸时,使用 GetClientRect 获取实际尺寸。