Страницы

Поиск по вопросам

суббота, 11 января 2020 г.

Перерисовка окна при изменении его размера

#cpp #winapi #directx #resize


Только начал изучать DirectX и WinAPI. Написал простейшую программу: создаёт квадрат
на всё окно и "раскрашивает" его шейдером. Но при уменьшении размера окна изображение
сжимается, а при увеличении - растягивается. Как сделать, чтобы этого не происходило,
т.е. при уменьшении, например, изображение не сжималось, а просто показывалась его
меньшая область.
Пробывал сделать это так:

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    // ...

    switch (message)
    {
        // ...

        case WM_SIZE:
            D3D11_VIEWPORT vp;
            vp.Width = (FLOAT)LOWORD(lParam);
            vp.Height = (FLOAT)HIWORD(lParam);
            vp.MinDepth = 0.0f;
            vp.MaxDepth = 1.0f;
            vp.TopLeftX = 0;
            vp.TopLeftY = 0;
            if (g_pImmediateContext)
                g_pImmediateContext->RSSetViewports(1, &vp);
        break;

        // ...
    }

    return 0;
}


Думал, сработает, но получил странное поведение: при уменьшении размера окна изображение
ещё сильнее уменьшается, а при увеличении остаётся неизменным. Как реализовать описанное
ранее поведение правильно?
    


Ответы

Ответ 1



Вне зависимости от фактических размеров окна его DirectX-ная система координат всегда будет описывать прямоугольник (0, 0)-(1, 1) (DX10) или (-1, -1)-(1, 1) (DX9). Для этого DirectX будет специально масштабировать (а в DX9 ещё и перемещать) координаты на кадровом буфере. Соответственно, ваша задача заключается в применении матрицы трансформации, которая отменяла бы подобный эффект, «сжимая» обе координаты прямо пропорционально габаритам окна. Причём эта матрица должна применяться после применения всех остальных матриц, если они есть. Для DirectX 11 (упомянутого в вопросе) матрица будет иметь следующий вид: где: α — масштабный коэффициент, указывающий, сколько пикселей должно приходиться на единичный отрезок обзорной области. w, h — ширина и высота клиентской области окна; получать при каждом WM_SIZE с помощью LOWORD(lParam) и HIWORD(lParam) соответственно.

Комментариев нет:

Отправить комментарий