[JavaScript, WebGL, Работа с 3D-графикой] Продолжаем чистить память с three.js
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
ВведениеНедавно писал о своем опыте очистки памяти в приложении, с использованием three.js. Напомню, что целью была перерисовка нескольких сцен с подгрузкой gltf моделей.
С тех пор я провел ряд экспериментов и считаю необходимым дополнить сказанное ранее этой небольшой статьей. Вот некоторые моменты, которые помогли мне улучшить производительность приложения.
Основная частьИзучая различные примеры сборки мусора на three.js заинтересовал подход, предложенный на threejsfundamentals.org. Однако, реализовав предложенную конфигурацию и завернув в this.track() все материалы и геометрию, выяснилось, что при загрузке новых сцен нагрузка на GPU продолжает расти. Более того, предложенный пример некорректно работает с EffectComposer и другими классами для постобработки, поскольку в этих классах track() использовать нельзя.
Решение с добавлением ResourceTracker во все используемые классы не привлекает, по очевидным причинам, поэтому решил дополнить метод очистки упомянутого класса. Вот некоторые приемы, которые были использованы:
Прием 1. Грубый.Добавляем renderer.info после метода очистки. Поочередно убираем ресурсы из приложения, чтобы понять, какие из них составляют нагрузку и прячутся в текстурах или материалах. Это не способ решение проблем, а просто способ отладки о котором кто-то мог не знать.
Прием 2. Долгий.Открыв код используемого класса (например AfterimagePass, который можно найти на гитхабе three.js) смотрим, где создаются ресурсы, которые нам нужно очищать, чтобы поддерживать число геометрий и материалов в требуемых рамках.
this.textureComp = new WebGLRenderTarget( window.innerWidth, window.innerHeight, { ... }
То что надо. Согласно документации, WebGLRenderTarget имеет функцию dispose, на которой завязана очистка памяти. Получаем что-то вроде
class Scene {
//...
postprocessing_init(){ // В нашем классе
this.afterimagePass = new AfterimagePass(0);
this.composer.addPass(this.afterimagePass);
}
//...
}
//...
class ResourceTracker {
//...
dispose() {
//...
sceneObject.afterimagePass.WebGLRenderTarget.dispose();
//...
}
}
Прием 3.Работает, но код для очистки в таком случае раздувается. Попробуем использовать знакомый нам из предыдущей статьи подход. Напомню, в ней мы реализовали метод disposeNode(node), в котором ресурс перебирался на поиск того, что можно очистить. disposeNode() может выглядеть как-то так:
disposeNode(node) {
node.parent = undefined;
if (node.geometry) {
node.geometry.dispose();
}
let material = node.material;
if (material) {
if (material.map) {
material.map.dispose();
}
if (material.lightMap) {
material.lightMap.dispose();
}
if (material.bumpMap) {
material.bumpMap.dispose();
}
if (material.normalMap) {
material.normalMap.dispose();
}
if (material.specularMap) {
material.specularMap.dispose();
}
if (material.envMap) {
material.envMap.dispose();
}
material.dispose();
}
} else if (node.constructor.name === "Object3D") {
node.parent.remove(node);
node.parent = undefined;
}
}
Отлично, теперь возьмем все дополнительные классы, которые мы применяли, и дополним наш ResourceTracker:
dispose() {
for (let key in sceneObject.afterimagePass) {
this.disposeNode(sceneObject.afterimagePass[key]);
}
for (let key in sceneObject.bloomPass) {
this.disposeNode(sceneObject.bloomPass[key]);
}
for (let key in sceneObject.composer) {
this.disposeNode(sceneObject.composer[key]);
}
}
ИтогиВ результате всех этих действий я значительно повысил ФПС и уменьшил нагрузку GPU в своем приложении. Возможно, я некорректно применял ResourceTracker, однако он в любом случае не помог бы в работе с дополнительными классами. Про то, что перебор EffectComposer через наш disposeNode(node) влияет на число текстур, оказывающихся в памяти я нигде не видел (однако так оно и есть). Этот вопрос следует рассмотреть отдельно.
Для сравнения предыдущая версия останется по старому адресу, а новую можно будет посмотреть отдельно. Проект в некотором виде есть на гитхабе.
Буду рад услышать ваш опыт по работе с аналогичными проектами и обсудить детали!
===========
Источник:
habr.com
===========
Похожие новости:
- [JavaScript, Программирование, Разработка веб-сайтов] Drag'n'Drop API: пример использования
- [JavaScript, Angular, ReactJS, TypeScript] Простые TypeScript-хитрости, которые позволят масштабировать ваши приложения бесконечно
- [Разработка веб-сайтов, JavaScript, Программирование, VueJS] Vue 3.0 — первый взгляд
- [Работа с 3D-графикой, Разработка игр, WebGL] Рендеринг каустики воды в реальном времени (перевод)
- [C, JavaScript, Интернет вещей, Программирование микроконтроллеров, Разработка для интернета вещей] Термостат на ThingJS (beta)
- [JavaScript, Алгоритмы, Программирование] Нестабильная сортировка в JavaScript
- [Конференции] Новая неделя стримов: от SvelteJS до Rider
- [JavaScript] «Никогда не писали автотесты? Попробуйте Cypress»
- [MongoDB, Node.JS, Python] Top 10 Full Stack Development Companies to Check Out in 2020
- [Работа с 3D-графикой, Разработка игр, Игры и игровые приставки] Портирование Detroit: Become Human с Playstation 4 на PC (перевод)
Теги для поиска: #_javascript, #_webgl, #_rabota_s_3dgrafikoj (Работа с 3D-графикой), #_three.js, #_js, #_webgl, #_javascript, #_webgl, #_rabota_s_3dgrafikoj (
Работа с 3D-графикой
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 22:37
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
ВведениеНедавно писал о своем опыте очистки памяти в приложении, с использованием three.js. Напомню, что целью была перерисовка нескольких сцен с подгрузкой gltf моделей. С тех пор я провел ряд экспериментов и считаю необходимым дополнить сказанное ранее этой небольшой статьей. Вот некоторые моменты, которые помогли мне улучшить производительность приложения. Основная частьИзучая различные примеры сборки мусора на three.js заинтересовал подход, предложенный на threejsfundamentals.org. Однако, реализовав предложенную конфигурацию и завернув в this.track() все материалы и геометрию, выяснилось, что при загрузке новых сцен нагрузка на GPU продолжает расти. Более того, предложенный пример некорректно работает с EffectComposer и другими классами для постобработки, поскольку в этих классах track() использовать нельзя. Решение с добавлением ResourceTracker во все используемые классы не привлекает, по очевидным причинам, поэтому решил дополнить метод очистки упомянутого класса. Вот некоторые приемы, которые были использованы: Прием 1. Грубый.Добавляем renderer.info после метода очистки. Поочередно убираем ресурсы из приложения, чтобы понять, какие из них составляют нагрузку и прячутся в текстурах или материалах. Это не способ решение проблем, а просто способ отладки о котором кто-то мог не знать. Прием 2. Долгий.Открыв код используемого класса (например AfterimagePass, который можно найти на гитхабе three.js) смотрим, где создаются ресурсы, которые нам нужно очищать, чтобы поддерживать число геометрий и материалов в требуемых рамках. this.textureComp = new WebGLRenderTarget( window.innerWidth, window.innerHeight, { ... } То что надо. Согласно документации, WebGLRenderTarget имеет функцию dispose, на которой завязана очистка памяти. Получаем что-то вроде class Scene {
//... postprocessing_init(){ // В нашем классе this.afterimagePass = new AfterimagePass(0); this.composer.addPass(this.afterimagePass); } //... } //... class ResourceTracker { //... dispose() { //... sceneObject.afterimagePass.WebGLRenderTarget.dispose(); //... } } Прием 3.Работает, но код для очистки в таком случае раздувается. Попробуем использовать знакомый нам из предыдущей статьи подход. Напомню, в ней мы реализовали метод disposeNode(node), в котором ресурс перебирался на поиск того, что можно очистить. disposeNode() может выглядеть как-то так: disposeNode(node) {
node.parent = undefined; if (node.geometry) { node.geometry.dispose(); } let material = node.material; if (material) { if (material.map) { material.map.dispose(); } if (material.lightMap) { material.lightMap.dispose(); } if (material.bumpMap) { material.bumpMap.dispose(); } if (material.normalMap) { material.normalMap.dispose(); } if (material.specularMap) { material.specularMap.dispose(); } if (material.envMap) { material.envMap.dispose(); } material.dispose(); } } else if (node.constructor.name === "Object3D") { node.parent.remove(node); node.parent = undefined; } } Отлично, теперь возьмем все дополнительные классы, которые мы применяли, и дополним наш ResourceTracker: dispose() {
for (let key in sceneObject.afterimagePass) { this.disposeNode(sceneObject.afterimagePass[key]); } for (let key in sceneObject.bloomPass) { this.disposeNode(sceneObject.bloomPass[key]); } for (let key in sceneObject.composer) { this.disposeNode(sceneObject.composer[key]); } } ИтогиВ результате всех этих действий я значительно повысил ФПС и уменьшил нагрузку GPU в своем приложении. Возможно, я некорректно применял ResourceTracker, однако он в любом случае не помог бы в работе с дополнительными классами. Про то, что перебор EffectComposer через наш disposeNode(node) влияет на число текстур, оказывающихся в памяти я нигде не видел (однако так оно и есть). Этот вопрос следует рассмотреть отдельно. Для сравнения предыдущая версия останется по старому адресу, а новую можно будет посмотреть отдельно. Проект в некотором виде есть на гитхабе. Буду рад услышать ваш опыт по работе с аналогичными проектами и обсудить детали! =========== Источник: habr.com =========== Похожие новости:
Работа с 3D-графикой ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 22:37
Часовой пояс: UTC + 5