2013-01-04 9 views
6

Pracuję nad aplikacją pisma ręcznego na iOS. Znalazłem przykładowy projekt "GLPaint" z dokumentacji iOS, który jest implementowany przez OpenGL ES, i zrobiłem coś na nim modyfikacji.Jak uniknąć nakładania się przezroczystości za pomocą OpenGL?

Śledzę punkty dotykowe i obliczam krzywe między punktami i rysuję same obrazy cząsteczek na krzywej, aby wyglądała na miejsce przejścia palca.

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, brushData); // burshData is from CGImage, it is 

// vertexBuffer is generated based on the calculated points, it's just a sequence of point where need to draw image. 
glVertexPointer(2, GL_FLOAT, 0, vertexBuffer); 
glDrawArrays(GL_POINTS, 0, vertexCount); 

glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer); 
[context presentRenderbuffer:GL_RENDERBUFFER_OES]; 

Co mam, to solidna linia, która wygląda całkiem nieźle. Ale teraz chcę narysować półprzezroczyste podświetlenie zamiast linii ciągłej. Dlatego zamieniam obraz cząstki na 50% przezroczystości bez zmiany kodu.

Result of 50% transparency particle image

Result of 50% transparency particle image

Jest coś złego w mieszance.

What I need

What I need

narysować trzech punktów przy użyciu cząstek obraz pół przejrzystości, a obszar przecięcia należy utrzymać 50% przezroczystość.

Jakie jest rozwiązanie?

+1

Problem polega na tym, że trzeba wyeliminować overdraw, które _ na ogólny przypadek_ nie jest możliwe przy "just blending". Możesz użyć bufora głębi (z testem alfa), ale to nie będzie prawidłowo antialias. Jeśli chcesz, aby to było właściwie antyaliasingowane, to nie jest banalne, aby uzyskać prawo, a przynajmniej nie w ogólnym przypadku. Będziesz musiał najpierw renderować do dodatkowego bufora ramki, a composite w drugim przebiegu. – Damon

+0

Dziękuję za odpowiedź. Jestem początkującym do OpenGL, nadal nie jestem jasne o najbardziej koncepcji w OpenGL. Myślę, że antialias nie jest problemem. Czy mógłbyś podać kod z większą ilością szczegółów? –

Odpowiedz

6

Im może dwa lata później odpowiadając na to pytanie, ale mam nadzieję, że to pomaga kogoś, kto przychodzi tu w poszukiwaniu rozwiązania tego problemu, jak to się stało.

Będziesz musiał przypisać do każdego kręgu inną wartość z. Nie ma znaczenia, jak duża lub mała jest ta różnica, potrzebujemy tylko, aby nie były dokładnie równe.

Najpierw należy wyłączyć zapisywanie w buforze kolorów glColorMask(false,false,false,false), a następnie normalnie narysować kółka. Bufor Z zostanie zaktualizowany zgodnie z oczekiwaniami, ale żadne kręgi nie zostaną jeszcze narysowane.

Następnie można włączyć zapisywanie w buforze kolorów (glColorMask(true,true,true,true)) i ustawić depthFunc na LEQUAL (glDepthFunc(GL_LEQUAL)). Tylko piksele najbliższego okręgu przejdą test głębokości (ustawienie go na LEQUAL zamiast EQUAL zajmuje się kilkoma rzadkimi, ale możliwymi błędami aproksymacji zmiennoprzecinkowej). Włączenie mieszania i ponowne ich narysowanie spowoduje wytworzenie pożądanego obrazu bez nakładania przezroczystości.

+0

Naprawdę dziękuję za odpowiedź. Jeszcze jedno pytanie. Co masz na myśli przez "przypisanie innej wartości z". Czy to trzeci wymiar wartości współrzędnych lub bufora z? Przepraszam, jeśli to pytanie ma niewielkie znaczenie, jestem nowicjuszem w OpenGL. –

+0

Obie w tym samym czasie! Wewnątrz shaderów współrzędne X i Y kontrolują pozycję na ekranie każdego wierzchołka (-1 do 1), a współrzędna Z kontroluje głębokość (0 do 1, czyli o 0 bliżej). Ta głębokość jest porównywana z buforem Z. - jeśli bufor Z w tym pikselu ma mniejszą wartość, oznacza to, że piksel jest już przybliżony do kamery, więc fragment jest odrzucany. Jeśli więc każde koło ma inną współrzędną Z, tylko jeden fragment na piksel nie zostanie odrzucony (najbliższy aparatowi), więc mieszanie się powiedzie. – Ivelate

+0

Możesz być zdezorientowany, ponieważ w większości przypadków stosujemy transformację współrzędnych wewnątrz modułu cieniującego wierzchołków przy użyciu macierzy transformacji. Tak więc masz początkowe X, Y, Z dla wierzchołka i zostanie on przekształcony w inną pozycję, aby wyrównać go z kamerą lub czymkolwiek, więc rzeczywiste Z używane przez moduł cieniujący może nie być oryginalnym Z twojego wierzchołka. Wyjaśnienie, czy jesteś nowicjuszem w OpenGL, jest nieco skomplikowane, więc zdecydowanie polecam przeczytanie tego samouczka (do momentu uzyskania części "Depth and stencil"), https://open.gl/, bardzo mi to pomogło, gdy zaczynałem. Nie wahaj się zapytać mnie więcej, jeśli potrzebujesz! – Ivelate

Powiązane problemy