2013-07-02 4 views
5

Итак, у меня есть анимация, которую я кодирую в javascript и HTML5 (нет библиотек, нет плагинов, нет ничего, и я бы хотел, чтобы это было так). Анимация использует физику (в основном кучу необычных пружин, прикрепленных к массам), чтобы имитировать простую жидкость. Результатом этой части программы является сетка (2d-массив) объектов, каждая из которых имеет значение z. Это работает очень хорошо. Моя проблема возникает при рисовании данных на холсте HTML5.HTML5 Canvas Creative Alpha-Blending

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

Вот как это выглядит. Поверьте мне, это лучше, когда анимировать.

Для каждой точки данных программа рисует один круг с цветом, определяемым значением z. Однако, только рисуя эти моменты, схема сетки болезненно очевидна, и трудно увидеть жидкость, которую она представляет. Чтобы решить эту проблему, я сделал круги более крупными и прозрачными, чтобы они накладывались друг на друга, а цвета смешивались, создавая простое размытие свертки. Результат был как быстрым, так и красивым, но для одного небольшого недостатка:

По мере того, как круги нарисованы по порядку, их значения цвета не складываются одинаково, и поэтому более вытянутые круги затушевывают ранее нарисованные. Математически рендеринг принимает повторяющиеся средневзвешенные значения цветов кругов. Это отлично работает для двух кругов, каждый из которых имеет значение 0,5 * alpha_n, но для трех кругов рендеринг принимает среднее значение самого нового круга со средним значением двух других, давая самому новому кругу значение 0,5 * alpha_n, но более ранние круги имеют значение 0,25 * alpha_n. По мере того как больше кругов перекрывается, процесс продолжается, создавая предвзятость к более новым кругам и к более старым. Вместо этого я хочу, чтобы каждый из трех или более кругов получал значение 0,33 * alpha_n, так что предыдущие круги не были закрыты.

Вот изображение альфа-смешивания в действии. Обратите внимание на то, что позже синий круг затемняет раньше обращается красные и зеленые:

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.

Вот что проблема выглядит в действии. Обратите внимание на разный вид левой части куска.

Чтобы решить эту проблему, я пробовал различные методы:

  • Использование различного холста "Blend-режимы". «Умножить» (как видно на рисунке выше) сделал трюк, но создал неудачные цветовые искажения.
  • Схватывая вместе призывы рисования. Вместо того чтобы сделать каждый круг отдельным холстом, я попытался объединить их все вместе в один. К сожалению, это несовместимо с наличием отдельных цветов заливки и, более того, путь не сливался с самим собой, создавая матовый монотонный силуэт.
  • Чересстрочный чертежный заказ. Вместо того, чтобы рисовать круги в порядке от 0 до n, я попробовал сначала рисовать эвены, а затем коэффициенты. Это лишь частично разрешило проблему и создало неприглядный образец расслоения, в котором шансы, казалось, плавали над эвенками.
  • Построение собственного режима смешивания с использованием putImageData. Я попытался создать ручной пиксельный шейдер в соответствии с моими потребностями с помощью javascript, но, как и ожидалось, он был слишком медленным.

На данный момент, я немного застрял. Я ищу творческие способы решения или кругосветки этой проблемы, и я приветствую ваши идеи. Меня не очень интересует, что мне говорят, что это невозможно, потому что я могу понять это для себя.Как вы изящно рисуете жидкость из таких точек данных?

+0

PS: Я достаточно разбираюсь в javascript и HTML5, поэтому вам не нужно ничего научить. Кроме того, если это кажется тривиальной проблемой для вас, имейте в виду, что я не заставляю вас отвечать. Меня это только беспокоит, и я хочу работать над его решением. – mindoftea

+4

Проклятые оптические иллюзии, ваши изображения выглядят анимированными, даже если они не являются. – Philipp

+0

Может кто-нибудь сказать мне, почему голос? – mindoftea

ответ

2

Если вы можете разложить свои круги на две группы (эвены и шансы), так что нет никакого перекрытия среди кругов в пределах группы, следующая последовательность должна дать желаемый эффект:

  1. Ясно фон
  2. Draw эвенов с альфа 1,0 (непрозрачных)
  3. Draw шансы с альфа 1,0 (непрозрачный)
  4. Draw эвенами с альфа 0,5

Места, которые покрыты ни эвенов, ни шансов покажет фон. Те, которые покрыты только эвеном, будут отображаться на 100% непрозрачности. Те, которые покрыты шансами, будут показывать шансы со 100% непрозрачностью. Те, которые покрыты обоими, показывают 50% -ную смесь.

Есть и другие подходы, которые можно использовать, чтобы попытаться объединить три или более множества объектов, но делать это «точно» сложно. Альтернативный подход, если у одного есть три или более изображений, которые должны быть равномерно смешаны в соответствии с их альфа-каналом, состоит в том, чтобы многократно рисовать все изображения, в то время как глобальная альфа-распадается от 1 до 0 (обратите внимание, что вышеупомянутая процедура на самом деле это делает, но она численно точный, если есть только два изображения). Числовые проблемы округления ограничивают точность этой методики, но даже выполнение двух или трех проходов может существенно снизить серьезность визуальных артефактов, вызванных порядком, при использовании меньших шагов, чем это необходимо для точного смешивания.

Кстати, если шаблон смешивания фиксирован, можно будет значительно ускорить рендеринг путем рисования эвенов и коэффициентов на отдельных холстах не как круги, а как непрозрачные прямоугольники и вычитания из альфа-канала одной из на холстах содержимое aa фиксированного холста или шаблона заливки «cookie-cutter». Если вы правильно вычисляете содержимое холстов для печенья, этот подход может использоваться для более чем двух наборов полотна. Определение содержания холстов для печенья может быть несколько медленным, но это нужно сделать только один раз.

+0

Ницца! Я бы не подумал об итеративном перерисовке кругов, но это открывает целый новый мир возможностей смешивания! – mindoftea

3

Ну, спасибо за помощь, ребята. :) Но, я понимаю, это был странный вопрос и трудно ответить.

Я помещаю это здесь частично, чтобы он предоставил ресурс будущим зрителям. Меня все еще интересуют другие возможные решения, поэтому я надеюсь, что другие будут публиковать ответы, если у них есть какие-то идеи.

В любом случае, я решил самостоятельно решить проблему: перед рисованием кругов я сделал на них comb sort, чтобы привести их в порядок по значению z, а затем нарисовал их в обратном порядке. В результате получилось, что наивысшие объекты (которые должны быть ближе к зрителю) были вычерчены последними и поэтому не были закрыты другими кругами. В результате, темный эффект все еще существует, но теперь это происходит так, что имеет смысл с геометрией. Вот что моделирование выглядит с этой коррекцией, обратите внимание, что теперь симметрично:

Normal use Lump test

 Смежные вопросы

  • Нет связанных вопросов^_^