Путаница по поводу SDL_SetSurfaceAlphaMod - PullRequest
0 голосов
/ 28 октября 2019

Я прочитал документацию по SDL_SetSurfaceAlphaMod. Хотя формула альфа-модуляции выглядит очень просто, я не могу предсказать результаты ее использования в коде. Ясно, что мое понимание неполно.

Чтобы прояснить свое мышление, я написал фрагмент кода (см. Ниже). Идея состоит в том, чтобы поместить четыре черных квадрата на красный фон в две строки по два.

Верхние два квадрата черные, потому что это то, чем по умолчанию соответствует поверхность, созданная с использованием SDL_CreateRGBSurface. SDL_FillRect не используется.

Два нижних квадрата используют SDL_FillRect, чтобы установить их черным после их создания (даже если они все равно будут черными).

Квадраты слева имеют альфазначение модуляции 0.

Квадраты справа имеют значение альфа-модуляции 255.

int main(int argc, char ** argv)
{
    SDL_Window * windowMain;
    SDL_Surface * surfaceMain;
    Uint32 rmask, gmask, bmask, amask;

    // Main window suface - red background
    windowMain = SDL_CreateWindow("Test Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 480, 360, 0);
    surfaceMain = SDL_GetWindowSurface(windowMain);
    Uint32 redBG = SDL_MapRGB(surfaceMain->format, 255, 0, 0);
    SDL_FillRect(surfaceMain, NULL, redBG);

#if SDL_BYTEORDER == SDL_BIG_ENDIAN
    rmask = 0xff000000;
    gmask = 0x00ff0000;
    bmask = 0x0000ff00;
    amask = 0x000000ff;
#else
    rmask = 0x000000ff;
    gmask = 0x0000ff00;
    bmask = 0x00ff0000;
    amask = 0xff000000;
#endif

    SDL_Surface * noFillSquare = SDL_CreateRGBSurface(0, 100, 100, 32, rmask, gmask, bmask, amask);
    SDL_Surface * blackFillSquare = SDL_CreateRGBSurface(0, 100, 100, 32, rmask, gmask, bmask, amask);
    Uint32 blackFG = SDL_MapRGB(blackFillSquare->format, 0, 0, 0);
    SDL_FillRect(blackFillSquare, NULL, blackFG);

    while (true)
    {
        showSurface(noFillSquare, surfaceMain, 0, 0, 100, 50); // Top left rectangle
        showSurface(noFillSquare, surfaceMain, 255, 0, 300, 50); // Top right rectangle (not displayed)
        showSurface(blackFillSquare, surfaceMain, 0, 0, 100, 200); // Bottom left rectangle
        showSurface(blackFillSquare, surfaceMain, 255, 0, 300, 200); // Bottom right rectangle

        SDL_UpdateWindowSurface(windowMain);
    }

    return 1;
}

void showSurface(SDL_Surface * srcSurface, SDL_Surface * dstSurface, Uint8 srcAlpha, Uint8 dstAlpha, int x, int y)
{
    SDL_Rect rect = { x, y, srcSurface->w, srcSurface->h };
    SDL_SetSurfaceAlphaMod(srcSurface, srcAlpha);
    SDL_SetSurfaceAlphaMod(dstSurface, dstAlpha);
    SDL_BlitSurface(srcSurface, NULL, dstSurface, &rect);
}

Запуск кода приводит к отображению:

Отображение сверху кода

Как видите, верхний правый черный квадрат не показан.

Я хотел бы попросить пошаговую разбивку попочему этот квадрат не отображается, в то время как остальные три появляются.

Я считаю документацию по SDL 2.0 довольно схематичной, особенно когда речь идет о поверхностях.

Ответы [ 2 ]

0 голосов
/ 29 октября 2019

Я переписал SDL 2.0.9, включаю файлы и библиотеки с версиями 2.0.10, и проблема немедленно исчезла.

Теперь я получаю ожидаемый вывод.

Правильный вывод

Не совсем уверен, что раньше было не так - возможно, некоторые несоответствующие файлы библиотеки?

0 голосов
/ 29 октября 2019

При создании поверхностей SDL делает memset(0) в массиве пикселей. Это действительно приводит к черному цвету, но альфа тоже становится 0 - что полностью прозрачно. Умножение 0 на модификатор альфа по-прежнему приводит к 0.

FillRect заменяет альфа полностью непрозрачным цветом, потому что вы используете SDL_MapRGB, а не, например, SDL_MapRGBA с 0 альфа.

...