Текстура, повернутая SDL2, неправильно сглажена

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

Исходная текстура, изображение размером 100x100 пикселей с синим квадратом 50x50 пикселей посередине.

исходная текстура

Я визуализирую эту текстуру дважды: как есть, повернутую на 45 градусов. Это дает следующий результат:

изображение результата

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

Есть ли способ добиться того и другого: текстуры со сглаживанием и бесшовного смешивания?

Я выполняю рендеринг с помощью SDL2 и OpenGL. Ниже приведен пример программы, демонстрирующей этот эффект.

#include <assert.h>

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>

void render(SDL_Renderer *renderer, SDL_Texture *tex) {
    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0xFF);
    SDL_RenderClear(renderer);

    SDL_Rect dst_rect = { 0, 0, 100, 100 };

    SDL_RenderCopyEx(renderer, tex, 0, &dst_rect,
        0, 0, SDL_FLIP_NONE);
    SDL_RenderCopyEx(renderer, tex, 0, &dst_rect,
        45, 0, SDL_FLIP_NONE);

    SDL_RenderPresent(renderer);
}

int main() {
    SDL_Window *window;
    SDL_Renderer *renderer;

    SDL_Init(SDL_INIT_VIDEO);
    SDL_CreateWindowAndRenderer(100, 100, SDL_WINDOW_OPENGL, &window, &renderer);

    /* comment the following line for blended images */
    SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best");

    SDL_Texture *tex = IMG_LoadTexture(renderer, "./sample.png" );
    assert(tex != 0);

    SDL_SetTextureBlendMode(tex, SDL_BLENDMODE_BLEND);

    render(renderer, tex);

    SDL_Event event = { 0 };
    while (1) {
        if (SDL_PollEvent(&event) == 0) {
            SDL_Delay(100);
            continue;
        }

        if (event.type == SDL_QUIT) {
            SDL_Quit();
            break;
        }
    }

    return 0;
}

Изменить: я обнаружил, что если я поверну текстуру на 45 градусов внутри SDL_RenderCopyEx, он добавит полупрозрачную границу другого цвета, см. Рисунок ниже.

введите описание изображения здесь

Обратите внимание, как меняется цвет по краям повернутого изображения.


person plasmatron    schedule 24.07.2014    source источник
comment
В первом примере не серые цвета, а разные оттенки синего. В примере с секундами создается граница с тремя разными оттенками синего, от более яркого (куб) до более темного (черный фон).   -  person this    schedule 25.07.2014
comment
Вы абсолютно правы, он выглядит серовато-серым, но на самом деле это другие оттенки синего. Это другой синий цвет, исходный синий - # 87ceeb, но он трансформируется в # 6aa2b9 - более темный синий вместо полупрозрачного # 87ceeb, который должен сливаться с нижележащими пикселями того же цвета.   -  person plasmatron    schedule 25.07.2014
comment
Попробуйте с другим фоном.   -  person this    schedule 25.07.2014
comment
При # 00000000 фон (ARGB, прозрачный черный) цвет границы меняется на черный (как в примерах), при # 00ffffff цвет фона (прозрачный белый) также меняется на черный, при # 01ffffff (почти прозрачный белый) цвет меняется на белый, с # Текстура 0187ceeb (почти прозрачно-синяя) плавно перетекает. Я уверен, что упускаю что-то важное, сглаживание не должно так работать, верно?   -  person plasmatron    schedule 25.07.2014
comment
Может дело в прозрачности, попробуйте полностью прозрачный фон.   -  person this    schedule 25.07.2014
comment
Изначально он был полностью прозрачным (# 00000000), так рендерятся примеры изображений. Я думаю, что это как-то связано со значением цвета (полу) прозрачного пикселя, я считаю, что сглаживание принимает средний цвет непрозрачного синего пикселя и прозрачного пикселя, но # 00000000 на самом деле прозрачный черный , создавая неожиданное сочетание синего и черного.   -  person plasmatron    schedule 25.07.2014
comment
Вы уверены, что 0xFF ... не полностью прозрачен, некоторые версии могут быть.   -  person this    schedule 25.07.2014


Ответы (1)


Рабочее решение, которое я нашел, - заполнить прозрачную часть изображения почти прозрачными пикселями того же цвета. Эталонное изображение:

введите описание изображения здесь

«Прозрачный» цвет на этом изображении - 0x0187ceeb (ARGB). Затем он создает смешанное изображение, как и ожидалось:

введите описание изображения здесь

Некоторые подробности этого обходного пути описаны здесь: http://www.saschahlusiak.de/2012/10/opengl-antialiasing-in-android-with-transparent-textures/

person plasmatron    schedule 28.07.2014