2012-07-24 11 views
11

Obecnie prowadzę badania dotyczące OpenGL i Shader, ale nie mogę się dowiedzieć, czy istnieją jakiekolwiek zasadnicze różnice między mieszaniem przy użyciu glBlendMode lub pisania własnych trybów mieszania w module cieniującym.Metody mieszania OpenGL i Shader Blending

Jakie są powody wyboru pierwszego lub drugiego? Czy istnieją jakieś wąskie gardła wydajności, wybierając jedno nad drugim? Czy to tylko kwestia osobistych preferencji?

Odpowiedz

13

Tradycyjne łączenie z glBlendFunc nie może być replikowane w module cieniującym. Mieszanie wymaga próbkowania docelowego bufora ramki przed modyfikacją, co nie jest możliwe do wykonania na obecnym sprzęcie.

Obecnie można przesłać tylko kolor i wybrać jedną z ograniczonej liczby trybów mieszania (glBlendFunc/glBlendEquation), które zostaną zastosowane przez rasteryzer GPU przed zapisaniem do bufora ramki.

+1

Czy oznacza to, że moduł cieniujący nie może mieszać dwóch tekstur i stosować do nich trybu mieszania i wyświetlać 1 nową teksturę? Uważam, że to trochę dziwne, jeśli ludzie publikują shadery trybu Photoshop Blend w Internecie. Czy mógłbyś to rozwinąć? Dzięki! – polyclick

+0

Nie, nadal można mieszać dwie tekstury w module cieniującym, ale to nie jest to, co robi mieszanie. Mieszanie miesza bieżący piksel z buforem ramki. Nadal możesz osiągnąć te same efekty innymi metodami (rysowanie na fakturze i miksowanie). @bartcla – Tim

+0

Ok, więc jeśli rozumiem poprawnie: mieszanie się przez 'glBlendFunc' jest czymś zupełnie innym niż mieszanie tekstur w module cieniującym? Powiedzmy, że chcę połączyć dwa zdjęcia z trybem mieszania "multiply". Powinno to zostać wykonane w module cieniującym, zamiast używać 'glBlendFunc'? Czy możesz podać przykład użycia 'glBlendFunc'? – polyclick

1

Jest możliwe, aby symulować OpenGL mieszania od wewnątrz modułu cieniującego w trzech okolicznościach jestem świadomy:

  1. Masz Direct3D11 lub OpenGL odpowiednik, i wiążą cel renderowania jako do odczytu i zapisu tekstury w twoim cieniującym pikselu. Umożliwia to dowolnie skomplikowane operacje mieszania, ale nie przynosi wysokiej wydajności przy prostym miksowaniu, ponieważ omijasz specjalny sprzęt GPU do prostego miksowania.

  2. Masz egzotyczny GPU oparty na płytkach, gdzie nawet proste mieszanie odbywa się przez "shader alfa". W tym przypadku nie ma różnicy w wydajności między prostym połączeniem w OpenGL i równoważnym kodem modułu cieniującego. Ale jest mało prawdopodobne, że masz taki procesor graficzny, a OpenGL i tak tego nie ujawnia.

  3. Przesuwać cały rurociąg rasteryzacji sprzętu o stałej funkcji i pisać własne jako kompleks "shaderów obliczeniowych". Jeśli zdołasz to wyciągnąć, coś takiego jak "alfa-shader" będzie częścią twojego potoku opartego na kafelkach, ale dotarcie do tego momentu to tyle pracy, że mieszanie się w alfę byłoby najmniejszym z twoich obaw.

+0

1: Nie wspominając, że musisz zająć się jawnie synchronizowaniem dostępu, jeśli wiele wywołań modułu cieniującego ma dostęp do tego samego piksela. –

+0

Jednym z ładnych aspektów rasteryzacji płytek jest to, że zazwyczaj nie ma możliwości warunków wyścigu między pikselami. ale jeśli zamiast tego mówiłeś o 1., to masz rację: gwarancja, że ​​rasteryzacja trójkąta zakończy się serialnie, zostanie naruszona w takim przypadku. – bmcnett

6

Gdy moduł cieniujący odczytuje teksturę podczas jednoczesnego renderowania do tej samej tekstury, wyniki są niezdefiniowane. Właśnie dlatego przydatne jest "tradycyjne" lub łączenie o ustalonej funkcjonalności z glBlendFunc i glBlendEquation.

Aby zmiksować dwa obrazy przy użyciu tradycyjnego mieszania, renderujesz pierwszy obraz, ustawiasz tryb mieszania, funkcję i równanie oraz renderujesz drugi obraz. Gwarantuje to uzyskanie prawidłowych wyników i zwykle jest to najszybszy sposób osiągnięcia efektów, takich jak przezroczystość.

Aby uzyskać ten sam efekt za pomocą modułu cieniującego, należy wyrenderować pierwszy obraz na pomocniczą teksturę, zmienić moduły cieniujące i zrenderować drugi obraz do rzeczywistego bufora ramki, wykonując mieszanie jako ostatni krok w module cieniującym fragment. Zwykle jest to wolniejsze z powodu dodatkowego narzutu odczytów tekstur i z pewnością użyje więcej pamięci GPU dla pomocniczej tekstury.

Na nowoczesnym sprzęcie różnica między tymi dwoma technikami jest zazwyczaj niewielka.

0

Można to w rzeczywistości zrealizować za pomocą gl 3.0 rozszerzenie za pomocą funkcji tekstury bariery:

http://www.opengl.org/registry/specs/NV/texture_barrier.txt

Zasadniczo, po piszesz tła można funkcja TextureBarrierNV(), aby mieć pewność teksele są wypłukiwane, a następnie można wykonać operacji odczytu/zapisu w sposób jeden etap cieniowania (pamiętaj, aby unikać buforów multisamplingowych, ponieważ dozwolona jest tylko jedna operacja zapisu) ..

Powiązane problemy