Это всего лишь предположение, но ...
Рисование 15 полноэкранных изображений будет медленным во многих системах. Это просто слишком много пикселей. Это не размер изображений, это размер, который они нарисованы. Как и на моем MacBook Air разрешение экрана составляет 2560х1600
Вы рисуете 15 изображений. Эти изображения нарисованы на холсте. Этот холст затем рисуется в окне браузера, а окно браузера затем рисуется на рабочем столе. Так что это как минимум 17 розыгрышей или
2560 * 1600 * 17 = 70meg pixels
Чтобы получить плавную частоту кадров, мы обычно хотим работать со скоростью 60 кадров в секунду. 60 кадров в секунду означает
60 frames a second * 70 meg pixels = 4.2gig pixels a second.
Мой графический процессор рассчитан на 8 гигабайт пикселей в секунду, поэтому похоже, что здесь мы можем получить 60 кадров в секунду
Давайте сравним с Macbook Air 2015 года с Intel HD Graphics 6000. Его разрешение экрана составляет 1440x900, которое, если вычислить, достигает 1,3 гигабайта пикселей при 60 кадрах в секунду. Его графический процессор рассчитан на 1,2 гигабайта пикселей в секунду, поэтому мы не получим 60 кадров в секунду на Macbook Air 2015 года
Обратите внимание, что, как и все, указанная максимальная скорость заполнения для графического процессора является одной из тех теоретических максимальных вещей, вы, вероятно, никогда не увидите, что она достигнет максимальной скорости из-за других накладных расходов. Другими словами, если вы посмотрите на скорость заполнения GPU, умножьте ее на 85% или еще что-то (просто предположение), чтобы получить скорость заполнения, которую вы, скорее всего, увидите в реальности.
Вы можете легко это проверить, просто сделайте окно браузера меньше. Если вы сделаете окно браузера на 1/4 размера экрана, и оно будет работать плавно, тогда ваша проблема была заполнена (при условии, что вы изменяете размер буфера рисования холста, чтобы он соответствовал размеру экрана). Это связано с тем, что после того, как вы сделаете, рисуется меньше пикселей (на 75% меньше), но все остальные работы остаются прежними (все javascript, webgl и т. Д.)
Если предположить, что ваша проблема заполнена, то что вы можете сделать
Не рисуйте все 15 слоев.
Если некоторые слои исчезают до 100% прозрачности, не рисуйте эти слои. Если вы можете спроектировать сайт таким образом, чтобы одновременно отображались только 4-7 слоев, вы значительно продвинетесь ниже предела заполнения
Не рисовать прозрачные области
Вы сказали 15 слоев, но некоторые из этих слоев в основном прозрачные. Вы можете разбить их на части, скажем, на 9+ (например, на рамку), а не нарисовать средний кусок. Будь то 9 штук или 50 штук, это, вероятно, лучше, чем 80% пикселей, которые на 100% прозрачны.
Многие игровые движки, если вы дадите им изображение, будут автоматически генерировать меш, который использует только части текстуры, которые> 0% непрозрачны. Например я сделал этот кадр в фотошопе
Затем, загрузив его в единое целое, вы увидите, что Unity создал сетку, которая покрывает только не 100% прозрачные части
Это то, что вы бы делали в автономном режиме, либо написав инструмент, либо вручную, либо используя какой-либо 3D-редактор сетки, например, Blender, для создания сеток, которые соответствуют вашим изображениям, так что вы не тратите время на рендеринг пикселей с 100 % прозрачный.
Попробуйте отбросить прозрачные пиксели
Это вам нужно проверить. В ваш фрагментный шейдер вы можете поместить что-то вроде
if (color.a <= alphaThreshold) {
discard; // don't draw this pixel
}
Где alphaThreashold
равно 0,0 или больше. Экономит ли это время, может зависеть от графического процессора, поскольку использование отбрасывания выполняется медленнее, чем нет. Причина в том, что если вы не используете discard
, тогда графический процессор может выполнить определенные проверки заранее. В вашем случае, хотя я думаю, что это может быть победой. Обратите внимание, что опция № 2 выше, использование сетки для каждой плоскости, которая покрывает только непрозрачные части, намного лучше, чем эта опция.
Передача большего количества текстур в один шейдер
Это слишком сложно, но вы могли бы сделать функцию drawMultiImages
, которая принимает несколько текстур и несколько матриц текстур и рисует N текстур одновременно. У них всех будет один и тот же прямоугольник назначения, но, отрегулировав исходный прямоугольник для каждой текстуры, вы получите тот же эффект.
N, вероятно, будет 8 или меньше, поскольку существует ограничение на количество текстур, которое вы можете сделать за один вызов отрисовки, в зависимости от графического процессора. 8 - это минимальное ограничение IIRC, означающее, что некоторые графические процессоры будут поддерживать более 8, но если вы хотите, чтобы все работало везде, вам нужно справиться с минимальным случаем.
Графические процессоры, как и большинство процессоров, могут читать быстрее, чем могут писать, поэтому чтение нескольких текстур и их смешивание в шейдере будет быстрее, чем выполнение каждой текстуры по отдельности.
Наконец, неясно, почему вы используете WebGL для этого примера.
Вариант 4 будет самым быстрым, но я бы не рекомендовал его. Мне кажется, слишком много работы для такого простого эффекта. Тем не менее, я просто хочу отметить, что, по крайней мере, на первый взгляд вы можете просто использовать N <div>
s и установить их css transform
и opacity
и получить тот же эффект. У вас остались бы те же проблемы, 15 полноэкранных слоев - это слишком много, и вы должны скрыть <div>
s, у которых непрозрачность равна 0% (браузер может сделать это для вас, но лучше не принимать в расчет). Вы также можете использовать 2D Canvas API, и вы должны увидеть аналогичные перфокарты. Конечно, если вы делаете какой-то особый эффект (не смотрел на код), тогда не стесняйтесь использовать WebGL, на первый взгляд, это было неясно.