2015-05-17 11 views
7

Rutynowo znajduję w OpenGL, kiedy próbuję narysować coś na fakturze, a następnie na innej powierzchni, używając glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA), niezmiennie kończę kolorowym halo (zwykle ciemno zabarwione pasmo) w półprzeźroczystych częściach mojego obrazu źródłowego przy jego krawędziach. Jest to ewidentnie spowodowane problemami z robieniem tego, co jest w istocie premipliplied alfa spowodowanym przez ten styl mieszania. W przypadku scen 3D zwykle używam algorytmu malowania, a do renderowania treści 2d lubię rysować najpierw obiekty z tyłu i nakładać na nie dodatkowe obiekty. Warto zauważyć, że podczas wykonywania takiego rysunku 2d nie mogę w ogóle polegać na funkcjach takich jak bufor az, tak jak ja w 3d, dlatego jest to większy problem z renderowaniem rzeczy takich jak guis, niż byłoby to w przypadku wykresów 3D scenyCiemne halo wokół częściowych przezroczystych części obrazów w opengl

Myślę, że warto zauważyć, że powyższy styl mieszania jest rzeczywiście idealny, gdy bufor docelowy jest już całkowicie nieprzejrzysty, ale jeśli miejsce docelowe jest przezroczyste, to naprawdę potrzebne jest w tym przypadku glBlendFunc(GL_SRC,GL_ZERO) .. ponieważ dowolne w pełni białe piksele, które są częściowo przezroczyste w źródle, na przykład powinny pozostać w pełni nasycone kolorem i nie mogą być "zmieszane" z tłem, które jeszcze nie istnieje, ponieważ użycie wartości glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) spowodowałoby, że obraz byłby częściowo przezroczysty i w pełni biały piksel jako mieszanka pierwszego planu i tła, który jest tym, czego chcę, ale nie w takim stopniu, w jakim tracą informacje alfa, ani w takim stopniu, w jakim kolory są faktycznie zmieniane.

Wydaje mi się więc, tego rodzaju funkcję mieszania, że ​​prawdopodobnie byłby idealny byłby taki, który faktycznie łączy między tym, co jest spowodowane glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) inaczej i to, co jest spowodowane glBlendFunc(GL_SRC,GL_ZERO) inaczej w zależności od wartości samego DST_ALPHA.

ten sposób, w idealnym:

Cr = Cs * (1 - Ad) + (Cs * As + Cd * (1 - As)) * Ad 
Ar = As * (1 - Ad) + Ad * Ad 

ten sposób, jeśli cel jest już nieprzezroczysta, normalny alfa mnożenie łączy odpowiednio, podczas gdy cel jest przezroczysta albo częściowo przezroczysta, używa się więcej źródła rzeczywisty kolor obrazu zamiast korzystania z postaci kolorów z premikatem alfa.

Jednak wydaje się, że nie ma wyraźnego sposobu opisania takiego mechanizmu mieszania dla OpenGL. Wydaje się, że takie problemy nie powinny być jedyne w mojej sytuacji, a ponadto wydaje mi się niezwykłe, że wydaje się, że nie ma sposobu, aby to osiągnąć ... nawet w ramach programowalnego rurociągu.

Jedyne obejście, które znalazłem do tej pory, polega na odwróceniu kolejności rysowania za każdym razem, gdy rysuję teksturę, którą później narysuję gdzie indziej i używam glBlendFuncSeparate(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA, GL_SRC_ALPHA, GL_DST_ALPHA).

Tworzenie specjalnego przypadku dla kolejności rysowania w przypadkach, w których rysuję coś na teksturach, które później zostaną renderowane, jest zwykle kompromisem, ale jest to dla mnie nieprzyjemne, ponieważ brakuje mu możliwości ponownego użycia, chyba że kod, który wykonuje rysunek zawsze należy uświadomić sobie, jaki jest typ miejsca docelowego, aby mógł on odwrócić swój zwykły porządek rysowania, który mogę skompliko- wać niepotrzebnie.

Na koniec, chociaż cofnięcie kolejności rysowania całej sceny niekoniecznie jest niemożliwe, wymaga to ustalenia pełnej listy obiektów, które będą wyświetlane w każdej ramce graficznej, zanim zostanie narysowany pierwszy obiekt. . Głównym problemem, jaki mam z tym, jest to, że chociaż może to być trwałe podczas renderowania scen 3D, podczas rysowania takich rzeczy jak 2d gui, sama różnorodność rzeczy, które są rysowane i sposób, w jaki są rysowane, jest po prostu tak ogromna, że ​​nie ma sposób na uogólnienie ich na listę pojedynczych obiektów, która zawsze może być później przesuwana w odwrotnej kolejności.Wydaje mi się, że wymagałoby to tak radykalnie odmiennego poglądu na temat konstruowania scen 2d w tym "wstecznym" porządku z tego, do czego jestem przyzwyczajony, że po prostu nie jestem w stanie nawet pojąć możliwego do utrzymania rozwiązania.

Więc ... czy jest inny sposób na zrobienie tego? Czy czegoś brakuje? Czy muszę nauczyć się zupełnie innego sposobu konstruowania zdjęć 2D? Nie mogę być jedyną osobą, która ma ten problem, ale muszę jeszcze znaleźć dobre i czyste rozwiązanie.

Edit:

Jeśli nie istnieje żadnej powszechnie dostępne rozszerzenie OpenGL, NVIDIA lub w inny sposób, który pozwala na tryb mieszania, który może to zrobić:

Cr = Cs * (1 - Ad) + (Cs * As + Cd * (1 - As)) * Ad 
Ar = As * (1 - Ad) + Ad * Ad 

(Gdzie Cs i CD są kolory źródłowe i docelowe, As i Ad są źródłowymi i docelowymi wartościami alfa, a Cr i Ar są kolorami wynikowymi i wartościami alfa). Naprawdę chciałbym wiedzieć, jak nazywa się to rozszerzenie i jak go używać ... o ile można go produkować na sprzęcie konsumenckim.

Odpowiedz

1

Pisałem różne rzeczy compositing półprzezroczyste nakładki 2D na półprzezroczystej zawartości 3D i nigdy odczuwany OpenGL czegoś brakuje kluczową w obszarze glBlendFunc/glBlendFuncSeparate (a przynajmniej nie aż zaczniesz się martwić o gamma-poprawione compositingu sRGB content i framebuffers).

jestem podejrzliwy głównie z korzystaniem z glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) widocznie z premultiplied alfa (przepraszam, a pytanie jest długi, nie jestem faktycznie znalezienie go to jasne, niektóre obrazy prostych testów może pomóc). W przypadku kompilacji wstępnie wygenerowanych treści alfa spodziewam się, że jako jeden z argumentów GL_ONE (w zależności od tego, czy robisz operacje nad/pod).

W przypadku miksowania/komponowania jest bardzo dobry slajd (w tym poprawne użycie premipliplied vs. "straight" colors) here (slajdy 20-35 odpowiedni materiał).

(Pomimo mojego twierdzenia, że ​​to, co jest już dostępne, jest na ogół wystarczająco dobre ... Warto również wspomnieć, że NVidia ostatnio dodała w tym numerze new features).

+0

Wspominam o 'glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)', ponieważ faktycznie działa poprawnie w przypadku mieszania, gdy piksel w buforze docelowym jest już nieprzezroczysty. Chociaż zauważyłem, że 'glBlendFunc (GL_SRC, GL_ZERO) działa poprawnie w przypadku mieszania, gdy piksel w miejscu docelowym jest nadal przezroczysty, nie ma żadnego sposobu przełączania się między tymi dwoma, w zależności od tego, jaki cel faktycznie jest. Idealnie, co byłoby potrzebne IMO jest funkcją mieszania, która jest ważoną sumą tych dwóch, w oparciu o przejrzystość bufora docelowego. – markt1964

+0

Problem z użyciem glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA) polega na tym, że częściowo przezroczyste piksele nie będą poprawnie nakładane na nieprzejrzyste tła, które są ciemniejsze niż piksel źródłowy .... na przykład, jasny czerwony piksel źródłowy z 50% przezroczystością ponad nieprzezroczysty czarny piksel stałby się nieprzezroczystą jaskrawą czerwienią zamiast nieprzezroczystego ciemniejszego czerwonego piksela, co jest tym, co powinno być, gdy pozwala na pokazanie 50% czerni. – markt1964

+0

Twoje zrozumienie czegoś (premarplikowana alfa? To zdarza się każdemu) jest gdzieś złe; jeśli masz półprzezroczystą jasnoczerwoną (0,5, ..., 0,5) (R ... A, z przedwzmacnianą alfą), to kompozycja, która nad nieprzezroczystą czernią (0,0, ..., 1,0) powinna dać ci (0,5,. .., 1.0) nieprzejrzysty ciemniejszy czerwony ... co daje GL_ONE, GL_ONE_MINUS_SRC_ALPHA). – timday

Powiązane problemy