2013-07-02 10 views
5

Mam animację, którą koduję w javascript i HTML5 (bez bibliotek, bez wtyczek, bez niczego i chciałbym, żeby tak pozostało). Animacja wykorzystuje fizykę (w zasadzie kilka niezwykłych sprężyn połączonych z masami), aby symulować prostą ciecz. Dane wyjściowe z tej części programu to siatka (tablica 2d) obiektów, z których każda ma wartość z. Działa to całkiem nieźle. Mój problem powstaje podczas rysowania danych na płótnie HTML5.HTML5 Creative Creative Alpha-Mieszanie

That's what it looks like. Trust me, it's better when animated.

Tak to wygląda. Zaufaj mi, to lepiej, gdy jesteś animowany.

Dla każdego punktu danych program rysuje jedno kółko o kolorze określonym przez wartość z. Właśnie rysując te punkty, wzór siatki jest boleśnie oczywisty i trudno jest zobaczyć płyn, który on reprezentuje. Aby rozwiązać ten problem, zrobiłem kółka większe i bardziej przezroczyste, tak aby zachodziły na siebie i kolory się mieszały, tworząc proste rozmycie splotu. Wynik był zarówno szybki, jak i piękny, ale dla jednej małej wady:

Gdy kręgi są rysowane w kolejności, ich wartości kolorów nie układają się równo, a więc pofałdowane kółka zaciemniają te wcześniej rysowane. Matematyczne renderowanie przyjmuje powtarzające się średnie ważone wartości kolorów kół. Działa to dobrze dla dwóch kółek, dając każdemu wartość 0,5 * alpha_n, ale dla trzech okręgów renderer pobiera średnią z najnowszego koła ze średnią dwóch pozostałych, nadając najnowszemu kręgowi wartość 0,5 * alpha_n, ale wcześniejsze kręgi mają wartość 0,25 * alpha_n. W miarę nakładania się kolejnych okręgów proces ten trwa, tworząc tendencję do nowych kręgów i starszych. Zamiast tego, dla każdego z trzech lub więcej kręgów otrzymam wartość 0,33 * alfa_n, aby wcześniejsze kręgi nie były zasłonięte.

Oto obraz mieszania alfa w akcji. Zauważ, że później niebieski okrąg zasłania wcześniej wyciągnąć czerwone i zielone: ​​

Later blue circle obscures earlier drawn ones.

Here's what the problem looks like in action. Notice the different appearance of the left side of the lump.

Oto na czym polega problem wygląda w akcji. Zwróć uwagę na inny wygląd lewej strony guzka.

Aby rozwiązać ten problem, próbowałem różnych metod:

  • Używanie innego płótna "blend-tryby". "Pomnożyć" (jak widać na powyższym obrazku) zrobiło lewę, ale stworzyło niefortunne zniekształcenia kolorów.
  • Łączenie razem wywoływanie połączeń. Zamiast robić z każdego kręgu oddzielną ścieżkę płótna, próbowałem zrzucić je wszystkie w jeden. Niestety, jest to nie do pogodzenia z oddzielnymi kolorami wypełnienia, a co więcej, ścieżka nie łączy się z samym sobą, tworząc matową, monotonną sylwetkę.
  • Przeplatanie kolejności rysowania. Zamiast rysować koła w kolejności od 0 do n, próbowałem najpierw narysować wyrównanie, a następnie szanse. To tylko częściowo rozwiązało problem i stworzyło nieestetyczny wzór warstwowy, w którym szanse wydawały się unosić nad wieczorami.
  • Tworzenie własnego trybu mieszania przy użyciu metody putImageData. Próbowałem utworzyć ręczny program do cieniowania pikseli, który odpowiadałby moim potrzebom przy użyciu javascript, ale zgodnie z oczekiwaniami był o wiele za wolny.

W tym momencie trochę utknąłem. Szukam twórczych sposobów rozwiązania lub obejścia tego problemu i cieszę się z twoich pomysłów. Nie jestem zbytnio zainteresowany powiedzeniem mi, że to niemożliwe, ponieważ mogę to sobie wyobrazić.Jak możesz elegancko czerpać płyn z takich punktów danych?

+0

PS: Jestem dość biegły w javascript i HTML5, więc nie musisz mnie uczyć niczego. Ponadto, jeśli wydaje ci się to banalnym problemem, pamiętaj, że nie zmuszam cię do odpowiedzi. Po prostu przeszkadza mi to i chcę pracować nad jego rozwiązaniem. – mindoftea

+4

Cholerne złudzenia optyczne, twoje obrazy wyglądają na ożywione, nawet jeśli nie są. – Philipp

+0

Czy ktoś może mi powiedzieć, dlaczego głosowanie w dół? – mindoftea

Odpowiedz

2

Jeśli można rozkładać swoje kręgi na dwie grupy (wyrównuje i kursów), takie, które nie pokrywają kręgach w grupie, następująca sekwencja powinna dać pożądanego efektu:

  1. Jasne tło
  2. Draw celu wyrównania z alfa 1,0 (matowa)
  3. Draw sprzeczności z alfa 1,0 (matowa)
  4. Draw celu wyrównania z alfa 0,5

miejscach objętych ani wyrównania poziomu ani kursów pokazuje tła. Te, które są pokrywane tylko przez evens, pokażą wszystko na 100% nieprzezroczystości. Osoby zaklasyfikowane jako szanse pokażą szanse ze 100% nieprzezroczystością. Objęte przez oba będą zawierać mieszankę 50%.

Istnieją inne podejścia, których można użyć, aby spróbować połączyć trzy lub więcej zestawów obiektów, ale wykonanie "dokładnie" jest skomplikowane. Alternatywne podejście, jeśli mamy trzy lub więcej obrazów, które powinny być mieszane równomiernie w zależności od ich kanału alfa, polega na wielokrotnym losowaniu wszystkich obrazów, podczas gdy globalna alfa rozpada się od 1 do 0 (zauważ, że wyżej wymieniona procedura faktycznie to robi, ale jest to numerycznie precyzyjne, gdy są tylko dwa obrazy). Zagadnienia związane z zaokrąglaniem numerycznym ograniczają precyzję tej techniki, ale nawet wykonanie dwóch lub trzech przebiegów może znacząco zmniejszyć ciężkość artefaktów wizualnych spowodowanych zamówieniem, a jednocześnie użyć mniejszej liczby kroków, niż byłoby to wymagane do precyzyjnego mieszania. Nawiasem mówiąc, jeśli wzór mieszania jest ustalony, możliwe jest znaczne przyspieszenie renderowania poprzez rysowanie równości i szans na oddzielnych płótnach nie jako okręgach, ale jako nieprzezroczyste prostokąty i odejmowanie od kanału alfa jednego z nich. na płótnach zawartość ustalonego płótna lub wzoru wypełnienia "cookie cutter". Jeśli prawidłowo obliczy się zawartość płótna do obcinania foremek, to podejście to można zastosować dla więcej niż dwóch zestawów płócien. Określanie zawartości płótna typu "cookie cutter" może być nieco powolne, ale należy je wykonać tylko raz.

+0

Nice! Nie pomyślałbym o iteracyjnym przerysowaniu kręgów, ale to otwiera zupełnie nowy świat możliwości łączenia! – mindoftea

3

Cóż, dziękuję za pomoc, chłopaki. :) Ale rozumiem, to było dziwne pytanie i trudno odpowiedzieć.

Umieszczam to tutaj w części, aby zapewnić zasób dla przyszłych widzów. Wciąż jestem zainteresowany innymi możliwymi rozwiązaniami, więc mam nadzieję, że inni opublikują odpowiedzi, jeśli mają jakieś pomysły.

W każdym razie, samodzielnie wymyśliłem rozwiązanie: Zanim narysowałem koła, zrobiłem na nich comb sort, aby uporządkować je według wartości z, a następnie narysowałem w odwrotnej kolejności. W rezultacie obiekty o najwyższej wartości (które powinny być bliżej widza) zostały wyciągnięte na końcu, a więc nie zostały zasłonięte przez inne okręgi. Powoduje to, że efekt zaciemnienia nadal istnieje, ale teraz dzieje się to w sposób, który ma sens w geometrii. Oto co symulacja wygląda z tej korekty, zauważ, że jest teraz symetryczne:

Normal use Lump test