Поднимите свои приложения PixiJS на новый уровень с помощью передовых стратегий и методов
В этом посте рассматриваются различные способы оптимизации рендеринга нескольких элементов в pixiJS с точки зрения как процессора, так и памяти. Например, рассмотрим разницу между повторным рендерингом каждого кадра без какого-либо кэширования (который хорошо работает с точки зрения использования ЦП) или кэшированием визуализированной графики в памяти. Это увеличит использование памяти пропорционально количеству графики в сцене.
Существует ряд стратегий для решения такой оптимизации. Особо следует отметить Data-Oriented Design, который представляет собой радикально альтернативный набор подходов по сравнению с более традиционно распространенным объектно-ориентированным способом программирования.
Другие основные способы включают в себя: отбор и использование гораздо более структурированных форматов - например, NativeArrays в C# и TypedArrays в TypeScript. Это позволит гораздо лучше управлять буферами памяти, что может ограничить количество промахов в кэше, но также требует значительного инженерного опыта и/или настройки.
В этом посте я сосредоточусь на одном рабочем методе оптимизации среды WebGL с помощью PixiJS: объектно-ориентированном подходе, включая лучшие практики. Это предоставит вам хорошо организованные средства для повышения скорости и эффективности ваших приложений PixiJS.
В моей следующей статье я расскажу об еще одном сильном подходе к оптимизации: подходе «сущность-компонент-система». Подход ECS поразительно ориентирован на данные и предлагает свежий взгляд на оптимизацию PixiJS в высокопроизводительных средах. Продолжите читать эту статью на Medium, где я подробно расскажу о мельчайших подробностях подхода ECS.
Всегда помните, что всегда есть что-то, что можно сделать лучше, пытаясь оптимизировать и еще больше повысить производительность вашего приложения Pixi. Под «лучше» не подразумевается «самый оптимизированный» или «самый быстрый». Лучшее решение — это вопрос компромисса между количеством времени, которое вы вкладываете в оптимизацию, и окупаемостью этих инвестиций, чтобы гарантировать, что вы сможете уложиться в сроки проекта, но с достаточной оптимизацией, чтобы, как мы надеемся, удовлетворить любых потенциальных пользователей без чрезмерного расширения ваших ресурсов.
В этом разделе я расскажу вам о лучших способах оптимизации приложений PixiJS.
Этот раздел основан на официальных советах, которые стоит проверить!
Остальная часть нашего обсуждения будет вращаться вокруг графики Pixi, спрайтов, сеток и того, когда использовать контейнер частиц вместо контейнера Pixi по умолчанию. Эта глава должна дать вам четкое представление о том, как все это можно оптимально использовать в объектно-ориентированном контексте, чтобы ваши проекты PixiJS были функциональными и отображались с максимальной эффективностью.
Чтобы эффективно использовать графику Pixi, нам необходимо понимать, как она работает внутри. Итак, давайте начнем с демонстрации простого примера создания графического объекта в Pixi:
const graphics = new PIXI.Graphics(); graphics.beginFill(0xff0000); graphics.drawRect(0, 0, 200, 100); graphics.endFill();
Однако в этой простой реализации важно то, что происходит «под капотом». Создавая такого рода графику, Pixi создает нечто, называемое объектом GraphicsGeometry. Этот объект принимает форму и размер в зависимости от размеров и свойств, которые вы указываете для рисуемой фигуры. Окончательный объект Geometry затем сохраняется внутри GeometryList внутри объекта Graphics.
Обратите внимание, что каждый раз, когда вы что-то рисуете с помощью PIXI.Graphics, GeometryList обновляется. Иногда вам нужно просто очистить этот список, но в то же время сохранить работоспособность объекта Graphics — именно здесь в игру вступает метод .clear(). Знание того, как работает этот процесс, очень поможет вам при использовании Pixi, поскольку оно напрямую влияет на то, как Pixi будет обрабатывать и отображать графику в вашем приложении.
Давайте рассмотрим стратегии оптимизации на примере создания 100 графических объектов в PixiJS.
function createGraphics(x, y) { const graphic = new PIXI.Graphics(); graphic.beginFill(0xDE3249); graphic.drawCircle(x, y, 10); graphic.endFill(); return graphic; } for (let i = 0; iВ этом сценарии, если все 100 графических объектов имеют одинаковую ширину и высоту, мы можем оптимизировать, повторно используя геометрию.
Передача GraphicsGeometry в качестве ссылки
Создайте единую геометрию для круга и используйте ее повторно:
// Create a single geometry for a circle const circleGeometry = new PIXI.Graphics(); circleGeometry.beginFill(0xDE3249); circleGeometry.drawCircle(0, 0, 10); // Draw a circle at the origin circleGeometry.endFill(); // Function to create a graphic using the circle geometry function createCircle(x, y) { const circle = new PIXI.Graphics(circleGeometry.geometry); circle.x = x; circle.y = y; return circle; } // Create 100 circles using the same geometry for (let i = 0; iЭтот метод значительно снижает использование памяти за счет ссылки на одну и ту же геометрию вместо ее дублирования для каждого объекта.
Нарисуйте все в одном графическом объекте
Для статической графики или сложных структур рисование всех элементов в одном объекте Graphics является еще одним методом оптимизации:
const graphics = new PIXI.Graphics(); // Draw 100 circles using the same PIXI.Graphics instance for (let i = 0; iВ этом подходе вместо создания новых объектов Graphics мы добавляем новые геометрии в GeometryList одного экземпляра Graphics. Этот метод особенно эффективен для более сложных графических структур.
Использование возможностей CacheAsBitmap в PixiJS
Одна из самых мощных функций PixiJS — это CacheAsBitmap. По сути, это позволяет движку обрабатывать графику как спрайты. В некоторых случаях это может существенно повысить производительность.
Используйте CacheAsBitmap, только если объект обновляется не слишком часто.
Большой пакет графики можно кэшировать как растровое изображение в контейнере. Вместо повторного рендеринга 100 изображений pixi сделает снимок и предварительно отрендерит его как растровое изображение.
Всегда учитывайте использование памяти: кэшированные растровые изображения используют много памяти.
Использовать кэшAsBitmap следует разумно. Он будет наиболее эффективен при применении к объектам, которые необходимо обновлять редко. Например, если у вас есть тысячи томов графики, которые являются статичными или имеют лишь редкие изменения, их кэширование в виде растрового изображения радикально снижает накладные расходы на рендеринг.
Вместо повторного рендеринга 100 отдельных графических изображений PixiJS может сделать их «снимок» и отобразить их как одно растровое изображение. Вот как вы можете реализовать:
const graphicsContainer = new PIXI.Container(); // Add your graphics to the container // ... // Cache the entire container as a bitmap graphicsContainer.cacheAsBitmap = true;
Однако важно помнить об использовании памяти. Кэшированные растровые изображения могут занимать значительный объем памяти. Таким образом, хотя кэшAsBitmap может значительно снизить нагрузку на рендеринг, он компенсируется использованием большего количества памяти. Этот компромисс следует тщательно обдумать с учетом конкретных потребностей и ограничений вашего приложения.
Подводя итог, можно сказать, что cacheAsBitmap — это эффективный инструмент для оптимизации производительности PixiJS, особенно для статической или редко обновляемой графики. Он упрощает рендеринг, рассматривая сложную графику как отдельные растровые изображения, но важно сбалансировать это с последствиями, связанными с объемом памяти.
Когда дело доходит до эффективности использования памяти в PixiJS, спрайты обычно имеют преимущество перед графикой. Это особенно очевидно при работе с несколькими объектами, имеющими одну и ту же форму или текстуру. Давайте вернемся к примеру создания 100 кругов, но на этот раз с использованием спрайтов.
Сначала мы создаем текстуру на основе геометрии одного круга:
const circleGraphic = new PIXI.Graphics(); circleGraphic.beginFill(0xDE3249); circleGraphic.drawCircle(0, 0, 10); circleGraphic.endFill(); // Generate a texture from the graphic const circleTexture = app.renderer.generateTexture(circleGraphic); Next, we use this texture to create sprites: // Function to create a sprite using the circle texture function createCircleSprite(x, y) { const sprite = new PIXI.Sprite(circleTexture); sprite.x = x; sprite.y = y; return sprite; } // Create and add 100 circle sprites to the stage for (let i = 0; iВ этом подходе вместо повторного рендеринга графики и управления растущим списком геометрии для каждого объекта мы создаем одну текстуру и повторно используем ее в нескольких спрайтах. Это значительно снижает нагрузку на рендеринг и использование памяти.
Ограничения и креативные решения
Одним из ограничений этого метода является то, что вы ограничены созданными вами текстурами. Однако именно здесь творчество становится ключевым моментом. Вы можете создавать текстуры различной формы с помощью PIXI.Graphics и применять их к спрайтам. Особенно эффективный подход — создать базовую текстуру, например растровое изображение размером 1x1 пиксель, и повторно использовать ее для всех прямоугольных спрайтов. Изменяя размер спрайта до разных размеров, вы можете использовать одну и ту же базовую текстуру в нескольких спрайтах без избыточности.
Например:// This creates a 16x16 white texture const baseTexture = PIXI.Texture.WHITE; // Use this baseTexture for all rectangular shapes const sprite= new PIXI.Sprite(baseTexture); sprite.tint = 0xDE3249; // Set the sprite color sprite.position.set(x, y); sprite.width = width; sprite.height = height;С помощью этого метода .tint() позволяет раскрасить спрайт без запуска полной повторной визуализации, поскольку оттенок применяется как дополнительный шейдерный эффект непосредственно на графическом процессоре.
Использование 100 тысяч спрайтов в контейнере частиц
Чтобы проиллюстрировать возможности этого метода, представьте, что вы запускаете 100 000 отдельных спрайтов со случайными оттенками, каждый из которых трансформируется в каждом кадре, и все это при сохранении плавной скорости 60 кадров в секунду.
Для дальнейшего чтения по оптимизации PixiJS я настоятельно рекомендую проницательную статью одного из первых создателей PixiJS, в которой глубоко рассматривается техника renderTexture.
Вы можете найти это здесь
Ух ты! Если вы зашли так далеко, я хочу искренне поблагодарить вас за то, что вы оставались со мной в этом глубоком погружении в оптимизацию PixiJS. Надеюсь, вы нашли идеи и методы, изложенные здесь, полезными для ваших проектов. Следите за обновлениями для моей следующей статьи, в которой я еще более подробно рассмотрю подход Entity-Component-System (ECS) и возможности NativeArrays. Эти методы поднимут ваши приложения PixiJS на новую высоту производительности и эффективности. Спасибо за прочтение и увидимся в следующем выпуске!
Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.
Copyright© 2022 湘ICP备2022001581号-3