windowsdirectxdirect3ddirect2ddirectwrite

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


Screenshot of the problem:

here

Here are the relevant bits of code - error handling etc. are omitted for clarity.

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);

As you can see in the screenshot, the text is rendering very poorly - specifically, the first "n" seems to be cut off on the left, as well as the first "u", and the capital "N" has some weird aliasing going on. I can change the size/position of the text, and the rendering issues manifest differently, but they still persist.

What am I missing here? I've been through most of the DirectWrite docs on MSDN and it's not clear what my problem is. I do see some mention that I should specify the starting position of my text relative to the dpi scale, but the example is very vague.

It's also worth mentioning that I'm using Direct3D and DirectWrite with Direct2D all together, in a similar fashion as seen in this tutorial. Not sure if that's causing my problem.

I would be very grateful for any assistance. Thanks much.


Solution

  • I figured it out. Cheers to VTT for pointing me in the right direction.

    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;
    

    Apparently the dimensions you pass into CreateWindow INCLUDE space for the window's menu and borders, so the ACTUAL dimensions of the space you can draw within the window are smaller.

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

    So the solution was to: -Omit specifying sd.BufferDesc.Width and sd.BufferDesc.Height in DXGI_SWAP_CHAIN_DESC, because when they're set to 0, they will inherit dimensions from the parent window. -Get the actual dimensions using GetClientRect when actual window dimensions are needed later on.