Я работаю над игрой на основе HTML5, в которой я хочу смешать полукруглые области разного цвета, нарисованные на сотнях квадратных ячеек в сетке. Эффект похож на тепловую карту. После некоторых исследований я обнаружил технику «теней», описанную выше Саймоном Саррисом.
Внедрение этой техники дало вид, который я хотел. И мне понравилось, что это было легко понять. Однако на практике я обнаружил, что рендеринг даже нескольких (~150) теней был намного медленнее по сравнению с моей предыдущей техникой (хотя и непривлекательной) рисования тысяч заполненных прямоугольников.
Поэтому я решил провести небольшой анализ. Я написал базовый JavaScript (модифицированную версию можно увидеть по адресу https://jsfiddle.net/Flatfingers/4vd22rgg/ ) для рисования 2000 копий каждого из пяти различных типов фигур на неперекрывающихся участках холста размером 1250 x 600 с записью прошедшего времени для каждой из этих пяти операций в последних версиях пяти основных настольных браузеров и мобильного Safari. (Извините, настольный Safari. У меня также нет под рукой Android, чтобы проверить.) Затем я попробовал разные комбинации эффектов и записал прошедшее время.
Вот упрощенный пример того, как я рисую два градиента, похожих на затененные закрашенные дуги:
var gradient1 = context.createRadialGradient(75,100,2,75,100,80);
gradient1.addColorStop(0,"yellow");
gradient1.addColorStop(1,"black");
var gradient2 = context.createRadialGradient(125,100,2,125,100,80);
gradient2.addColorStop(0,"blue");
gradient2.addColorStop(1,"black");
context.beginPath();
context.globalCompositeOperation = "lighter";
context.globalAlpha = 0.5;
context.fillStyle = gradient1;
context.fillRect(0,0,200,200);
context.fillStyle = gradient2;
context.fillRect(0,0,200,200);
context.globalAlpha = 1.0;
context.closePath();
ВРЕМЯ
(2000 непересекающихся фигур, наборы globalAlpha, drawImage() используется для градиентов, но не для теней)
IE 11 (64-bit Windows 10)
Rects = 4 ms
Arcs = 35 ms
Gradients = 57 ms
Images = 8 ms
Shadows = 160 ms
Edge (64-bit Windows 10)
Rects = 3 ms
Arcs = 47 ms
Gradients = 52 ms
Images = 7 ms
Shadows = 171 ms
Chrome 48 (64-bit Windows 10)
Rects = 4 ms
Arcs = 10 ms
Gradients = 8 ms
Images = 8 ms
Shadows = 203 ms
Firefox 44 (64-bit Windows 10)
Rects = 4 ms
Arcs = 21 ms
Gradients = 7 ms
Images = 8 ms
Shadows = 468 ms
Opera 34 (64-bit Windows 10)
Rects = 4 ms
Arcs = 9 ms
Gradients = 8 ms
Images = 8 ms
Shadows = 202 ms
Mobile Safari (iPhone5, iOS 9)
Rects = 12 ms
Arcs = 31 ms
Gradients = 67 ms
Images = 82 ms
Shadows = 32 ms
НАБЛЮДЕНИЯ
- Среди заполненных фигур заполненные прямоугольники неизменно являются самой быстрой операцией во всех протестированных браузерах и средах.
- Заполненные полные дуги (круги) примерно в 10 раз медленнее в IE 11 и Edge, чем заполненные прямоугольники, по сравнению с примерно в 3,5 раза медленнее в других основных браузерах.
- Градиенты примерно в 3 раза медленнее прямоугольников в IE 11, Chrome 48 и Opera 34, но в 100 раз медленнее в Firefox 44 (см. отчет об ошибке 728453).
- Изображения с помощью drawImage() примерно в 1,5 раза быстрее, чем заполненные прямоугольники во всех настольных браузерах.
- Затененные дуги с заливкой работают медленнее всех: примерно в 50 раз медленнее, чем заполненные прямоугольники в IE, Edge, Chrome и Opera, до 100 раз медленнее в Firefox.
- Chrome 48 и Opera 34 удивительно быстры во всех категориях форм, кроме затененных заполненных дуг, но они не хуже, чем другие браузеры.
- Chrome и Opera аварийно завершают работу, когда функция drawImage() отрисовывает 1000 фигур, где значение shadowOffsetX или shadowOffsetY выходит за пределы физического разрешения экрана.
- IE 11 и Edge рисуют дуги и градиенты медленнее, чем другие настольные браузеры.
- drawImage() работает медленно в мобильном Safari. На самом деле быстрее рисовать несколько градиентов и затененных дуг, чем много раз рисовать одну копию с помощью drawImage().
- Рисование в Firefox чувствительно к предыдущим операциям: рисование теней и градиентов замедляет рисование дуг. Показаны самые быстрые результаты.
- Рисование в Mobile Safari чувствительно к предыдущим операциям: тени замедляют градиенты; градиенты и дуги делают функцию drawImage() еще медленнее, чем обычно. Показаны самые быстрые результаты.
АНАЛИЗ
Хотя функция shadowOffset является простым и визуально эффективным способом смешивания фигур, она значительно медленнее, чем все другие методы. Это ограничивает его полезность для приложений, которым нужно рисовать только несколько теней и которым не нужно быстро и многократно рисовать много теней. Кроме того, при ускорении с помощью drawImage() задание для shadowOffsetX или shadowOffsetY значения, превышающего примерно 3000, приводит к зависанию Chrome 48 и Opera 34 почти на минуту, потребляя циклы ЦП, а затем приводит к сбою моего драйвера дисплея nVidia, даже после его обновления. до последней версии. (Поиск Google не нашел отчетов об ошибках для Chromium, описывающих эту ошибку, когда большие shadowOffset и drawImage() используются вместе.)
Для приложений, которые должны смешивать нечеткие формы, наиболее визуально похожий подход к теням — установить для globalCompositeOperation значение «lighter» и использовать drawImage() со значением globalAlpha для повторного рисования предварительно окрашенного радиального градиента или для рисования отдельных градиентов, если они нужны. быть разного цвета. Это не идеальное совпадение для перекрывающихся теней, но оно близко и позволяет избежать попиксельных вычислений. (Однако обратите внимание, что в мобильном Safari прямое рисование затененных дуг на самом деле быстрее, чем градиенты и drawImage().) При установке globalCompositeOperation на «lighter» IE 11 и Edge примерно в 10 раз медленнее рисуют дуги с использованием радиального градиента. по-прежнему быстрее, чем использование затененных дуг во всех основных настольных браузерах, и только в два раза медленнее, чем затененные дуги в мобильном Safari.
ЗАКЛЮЧЕНИЕ
Если вашей единственной целевой платформой является iPad/iPhone, самый быстрый способ получить красиво выглядящие смешанные формы — это затененные закрашенные дуги. В противном случае, самый быстрый метод с сопоставимым внешним видом, который я нашел до сих пор, который работает во всех основных настольных браузерах, — это рисование радиальных градиентов с параметром globalCompositeOperation, установленным на «светлее», и управлением непрозрачностью с помощью globalAlpha.
Примечание. Есть несколько очевидных способов улучшить производительность в тестах рисования, которые я выполнял. В частности, рисование каждого экземпляра каждой фигуры в буфере за пределами экрана, а затем однократное рисование всего этого буфера на видимом холсте приведет к значительному повышению производительности. Но это свело бы на нет цель этого тестирования, которое состояло в том, чтобы сравнить относительные скорости рисования различных форм на видимом холсте.
person
Bart Stewart
schedule
22.02.2016