Текстурата, завъртяна от SDL2, е антиалиасирана неправилно

Опитвам се да смеся няколко текстури заедно с активирано антиалиасинг, работи добре, ако текстурите не са завъртани, но когато завъртя текстура, антиалиасингът създава „граница“ на ръба на текстурата. По-долу е даден пример.

Оригинална текстура, изображение 100x100px със син квадрат 50x50px в средата.

оригинална текстура

Изобразявам тази текстура два пъти: както е и завъртяна на 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 (почти прозрачно синьо) се смесва безпроблемно. Сигурен съм, че пропускам нещо важно, anti-aliasing не трябва да работи така, нали?   -  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