Количество видимых на объекте деталей существенно снижается при значительном отдалении от камеры. Однако, при отрисовке объекта всё ещё будет использоваться то же количество треугольников, даже не смотря на то, что часть из них визуально будет незаметно. Существует техника оптимизации, которая позволяет снижать количество отрисовываемых треугольников по мере удаления объекта от камеры: уровни детализации (Levels Of Detail, LOD). Если весь ваш объект не находится близко к камере, LOD снизит нагрузку на оборудование и повысит производительность отрисовки.
Для настройки LOD отрисовки объекта в Unity, вы можете добавить на него компонент LOD Group . Более подробно с этим компонентом вы можете ознакомиться на странице со справкой по нему, однако, на изображениях, представленных ниже, вы можете ознакомиться с тем, как меняется уровень LOD (LOD Level) объекта при удалении от камеры. На первом изображении показан объект с уровнем LOD 0 (наиболее детализированный):-
Топ Настройки в Майнкрафт
… и на втором изображении показан объект со меньшим уровнем LOD при удалении от камеры:-
Хоть расположение уровней LOD и зависит от целевой платформы и доступных GPU ресурсов, Unity позволяет установить максимальный уровень LOD (Maximum LOD Level) и смещение LOD (LOD Bias, т.е. какому из соседних уровней отдавать предпочтение при расположении между ними) в Quality Settings.
Соглашение об именовании LOD в импортируемых объектах
Если вы создаете набор мешей, имена которых оканчиваются на _LOD0, _LOD1, _LOD2, и т.д., в соответствии с количеством необходимых вам уровней LOD, то при импорте вашего объекта, будет автоматически создана группа LOD (компонент LOD Group) с нужными настройками. Например, если базовое название ваших мешей — Player, то вы можете создать файлы с именами Player_LOD0, Player_LOD1 и Player_LOD2 для генерации объекта с тремя уровнями LOD. Соглашение о нумерации подразумевает, что модель с LOD 0 является наиболее детализированной, и детализация снижается по мере увеличения индекса.
Источник: docs.unity3d.com
Форум МИРа NVIDIA
«Слишком высокий уровень детализации. Память видеокарты меньше 64 мб, что позволяет выбрать минимальный уровень детализации, равный [ +]. В будущем это может вызвать проблемы. Рекомендуем выбрать более низкий уровень детализации и перезапустить игру. Хотите установить рекомендуемый уровень детализации?
Да. Нет.»
Нажимаем либо да, либо нет, экзэшник прекращает работу и закрывается.
Играю на ноутбуке, стоит 7-ка, 2 видеокарты, интеловская и geforse gt 630m(2гб), видимо при запуске игры выбирается по умолчанию встройка. Пробовал изменять графический редактор по умолчанию, пробовал запуск с ручным выбором видеокарты, менял программные настройки в управлении видеокарты nvideo. Ничего не помогает.
ВСЕ СПОСОБЫ КАК УВЕЛИЧИТЬ ФПС В МАЙНКРАФТ НЕ ЛАГАЛ И НАСТРОИТЬ ГРАФИКУ НОУТБУКЕ И СЛАБОМ КОМПЬЮТЕРЕ
Может быть кто-нибудь сталкивался с такой проблемой и решил её, отпишитесь здесь.
Re: Слишком высокий уровень детализации
Сообщение togrul » 14.01.2013 13:30
negative123
драйвера на видяху не переставляли часом? Чтоб адекватно работало переключение между дискретной и встроенной картами надо, чтоб драйвера были родными, ноут был подключен к сети и в параметрах энергосбережения должно быть выставлено «максимальная производительность.»
Re: Слишком высокий уровень детализации
Сообщение negative123 » 15.01.2013 16:57
togrul писал(а): negative123
драйвера на видяху не переставляли часом? Чтоб адекватно работало переключение между дискретной и встроенной картами надо, чтоб драйвера были родными, ноут был подключен к сети и в параметрах энергосбережения должно быть выставлено «максимальная производительность.»
Скачал и установил драйвер с сайта NVIDIA, на видяху, версию 9.18.13.1090(дата разработки 29.12.2012), к сети подключен, в параметрах выставлена «максимальная производительность» — ошибка точно такая же(
Источник: forum.nvworld.ru
Введение
Одной из интереснейших задач, решаемых посредством трехмерной графики является создание «больших миров» — протяженных сцен, содержащих большое число объектов с возможностью неограниченного перемещения по сцене. Решение этой задачи упирается в понятные ограничения, присущие аппаратному обеспечению компьютера.
Типичный пример: «большой мир» при визуализации железной дороги на движке OSG. Не хватает только лангольеров, пожирающих мир за поездом.
В этой связи возникает необходимость управления ресурсами приложения, сводящаяся к очевидному решению: загрузке только тех ресурсов (моделей, текстур и так далее), которые необходимы для формирования сцены в текущий момент времени при текущем положении наблюдателя; уменьшении уровней детализации удаленных объектов; выгрузке не нужных более объектов из памяти системы. В большинстве своем графические и игровые движки предоставляют некоторый набор инструментов для решения подобных задач. Сегодня мы рассмотрим, какие из них имеются в OpenSceneGraph.
1. Использование уровней детализации (LOD)
Техника использования уровней детализации позволяет отображать один и тот же объект более или менее детально, в зависимости от расстояния от него до наблюдателя. Использование этой техники основано на том простом соображении, что мелкие детали трехмерной модели неразличимы на большом расстоянии, значит нет необходимости в их прорисовке. С одной стороны этот прием позволяет уменьшить общее количество геометрических примитивов, выводимых в буфер кадра, а с другой — не терять в дальности отображения объектов сцены, что очень полезно при создании больших открытых миров.
OSG предоставляет инструменты для реализации этого приема через класс osg::LOD, наследуемый от всё того же osg::Group. Этот класс позволяет представить один и тот же объект в нескольких уровнях детализации. Каждый уровень детализации характеризуется минимальной и максимальной дистанцией до наблюдателя, при соблюдении которой происходит переключение отображения объекта в этом уровне детализации.
osg::LOD позволяет задавать данный диапазон сразу при задании дочерней ноды, или позже, применением методы setRange()
osg::ref_ptr lodNode = new osg::LOD; lodNode->addChild(node2, 500.0f, FLT_MAX); lodNode->addChild(node1); . . . lodNode->setRange(1, 0.0f, 500.0f);
Продолжаем мучать цессну и проиллюстрируем описанную технику примером
Пример lod
main.h
#ifndef MAIN_H #define MAIN_H #include #include #include #include #endif
main.h
#include «main.h» int main(int argc, char *argv[]) < (void) argc; (void) argv; osg::ref_ptrmodelL3 = osgDB::readNodeFile(«../data/cessna.osg»); osg::ref_ptr modelL2 = dynamic_cast(modelL3->clone(osg::CopyOp::DEEP_COPY_ALL)); osg::ref_ptr modelL1 = dynamic_cast(modelL3->clone(osg::CopyOp::DEEP_COPY_ALL)); osgUtil::Simplifier simplifer; simplifer.setSampleRatio(0.5f); modelL2->accept(simplifer); simplifer.setSampleRatio(0.1f); modelL1->accept(simplifer); osg::ref_ptr root = new osg::LOD; root->addChild(modelL1.get(), 200.0f, FLT_MAX); root->addChild(modelL2.get(), 50.0f, 200.0f); root->addChild(modelL3.get(), 0.0f, 50.0f); osgViewer::Viewer viewer; viewer.setSceneData(root.get()); return viewer.run(); >
Для начала загружаем модель
osg::ref_ptr modelL3 = osgDB::readNodeFile(«../data/cessna.osg»);
Теперь необходимо генерировать несколько (ограничимся для примера двумя) моделек, с более низким уровнем детализации. Для этого скопируем загруженную ноду дважды, применяя методику так называемого «глубокого» копирования класса, для ноды реализуемого методом clone()
osg::ref_ptr modelL2 = dynamic_cast(modelL3->clone(osg::CopyOp::DEEP_COPY_ALL)); osg::ref_ptr modelL1 = dynamic_cast(modelL3->clone(osg::CopyOp::DEEP_COPY_ALL));
Теперь редуцируем геометрию этих моделей, используя класс osgUtil::Simplifer. Степень упрощение модели задается методом setSampleRatio() данного класса — чем меньше передаваемый параметр, тем менее детальной будет модель после применения процедуры редукции
osgUtil::Simplifier simplifer; simplifer.setSampleRatio(0.5f); modelL2->accept(simplifer); simplifer.setSampleRatio(0.1f); modelL1->accept(simplifer);
Когда у нас есть модельки разного уровня детализации мы можем зарядить их в корневую ноду, созданную как умный указатель на osg::LOD. Для каждого уровня детализации задаем дистанцию отображения этого уровня
osg::ref_ptr root = new osg::LOD; root->addChild(modelL1.get(), 200.0f, FLT_MAX); root->addChild(modelL2.get(), 50.0f, 200.0f); root->addChild(modelL3.get(), 0.0f, 50.0f);
Под FLT_MAX понимается в некотором роде «бесконечно» большое расстояние до наблюдателя. После запуска вьювера получаем следующую картину
Уровень детализации 3
Уровень детализации 2
Уровень детализации 1
Видно, как при отдалении камеры от объекта снижается детальность отображаемой геометрии. Применяя этот прием можно добиться высокой реалистичности сцены при малом расходе ресурсов.
2. Техника фоновой загрузки узлов сцены
В движке OSG представлены классы osg::ProxyNode и osg::PagedLOD, предназначенный для баллансировки нагрузки при рендеринге сцены. Оба класса наследуются от osg::Group.
Узел типа osg::ProxyNode уменьшает время запуска приложения до начала рендеринга, если в сцене огромное количество загружаемых с диска и отображаемых моделей. Он работает как интерфейс к внешним файлам, позволяя выполнять отложенную загрузку моделей. Для добавления дочерних узлов используется метод setFileName() (вместо addChild) чтобы установить имя файла модели на диске и загрузить его динамически.
Узел osg::PagedNode наследует методы osg::LOD и загружает и выгружает уровни детализации таким образом, чтобы избежать перегрузки конвейера OpenGL и обеспечить плавную отрисовку сцены.
3. Динамическая (runtime) загрузка модели
Посмотрим, как происходит процесс загрузки модели с применением osg::ProxyNode.
Пример proxynode
main.h
#ifndef MAIN_H #define MAIN_H #include #include #endif
main.cpp
#include «main.h» int main(int argc, char *argv[]) < (void) argc; (void) argv; osg::ref_ptrroot = new osg::ProxyNode; root->setFileName(0, «../data/cow.osg»); osgViewer::Viewer viewer; viewer.setSceneData(root.get()); return viewer.run(); >
Процесс загрузки здесь немного отличается
osg::ref_ptr root = new osg::ProxyNode; root->setFileName(0, «../data/cow.osg»);
Вместо явной загрузки модели коровы мы указываем корневой ноде имя файла, где содержится модель и индекс дочерней ноды, куда следует поместить эту модель после её загрузки. При выполнении программы мы получи такой результат
Видно, что точка обзора выбрана не лучшим образом — камера упирается прямо в зеркальный бок коровы. Это произошло потому, что модель загрузилась уже после запуска рендера и инициализации камеры, когда нода 0 ещё не была видна. Вьювер просто не смог просчитать необходимые параметры камеры. Однако, модель загрузилась и мы может настроить режим её отображения путем манипуляций мышью
Что происходит в рассмотренном примере? osg::ProxyNode и osg::PagedLOD работают в данном случае как контейнеры. Внутренний менеджер данных OSG будет посылать запросы и загружать данные в граф сцены по мере того, как возникнет необходимость в файлах моделей и уровнях детализации.
Данный механизм работает в нескольких фоновых потоках и управляет загрузкой статических данных, расположенных в файлах на диске и динамических данных, генерируемых и добавляемых в процессе выполнения программы.
Движок автоматически обрабатывает узлы, не отображаемые в текущем вьюпорту и удаляет их из графа сцены когда рендер перегружен. Однако, такое поведение не затрагивает узлы osg::ProxyNode.
Как и прокси-узел, класса osg::PagedLOD также имеет метод setFileName() для задания пути к загружаемой модели, однако для его необходимо установить диапазон дистанции видимости, как для узла osg::LOD. При условии, что у нас имеется файл cessna.osg и низкополигональная модель уровня L1 мы можем организовать выгружаемую ноду следующим образом
osg::ref_ptr pagedLOD = new osg::PagedLOD; pagedLOD->addChild(modelL1, 200.0f, FLT_MAX ); pagedLOD->setFileName( 1, «cessna.osg» ); pagedLOD->setRange( 1, 0.0f, 200.0f );
Нужно понимать, что узел modelL1 не может быть выгружен из памяти, так как это обычный дочерний не прокси-узел.
При рендеринге внешне не видна разница между osg::LOD и osg::PagedLOD, если использовать только один уровень детализации модели. Интересной идеей будет организовать громадный кластер моделей Cessna, используя класс osg::MatrixTransform. Для этого можно использовать например такую функцию
osg::Node* createLODNode( const osg::Vec3 osg::ref_ptrpagedLOD = new osg::PagedLOD; … osg::ref_ptr mt = new osg::MatrixTransform; mt->setMatrix( osg::Matrix::translate(pos) ); mt->addChild( pagedLOD.get() ); return mt.release(); >
Пример программы реализующей фоновую загрузку 10000 самолетов
main.h
#ifndef MAIN_H #define MAIN_H #include #include #include #endif
main.cpp
#include «main.h» //—————————————————————————— // //—————————————————————————— osg::Node *createLODNode(const std::string pos) < osg::ref_ptrpagedLOD = new osg::PagedLOD; pagedLOD->setFileName(0, filepath); pagedLOD->setRange(0, 0.0f, FLT_MAX); osg::ref_ptr mt = new osg::MatrixTransform; mt->setMatrix(osg::Matrix::translate(pos)); mt->addChild(pagedLOD.get()); return mt.release(); > //—————————————————————————— // //—————————————————————————— int main(int argc, char *argv[]) < (void) argc; (void) argv; osg::ref_ptrroot = new osg::Group; float dist = 50.0f; int N = 100; for (int i = 0; i < N; ++i) < float x = i * dist; for (int j = 0; j < N; ++j) < float y = j * dist; osg::Vec3 pos(x, y, 0.0f); osg::ref_ptrnode = createLODNode(«../data/cessna.osg», pos); root->addChild(node.get()); > > osgViewer::Viewer viewer; viewer.setSceneData(root.get()); return viewer.run(); >
Предполагается, что самолеты будут располагаться на плоскости с интервалом в 50 единиц координат. При загрузке мы увидим, что загружаются только те цессны, что попадаю в кадр. Те самолеты, что исчезают из кадра пропадают из дерева сцены.
Заключение
Этот урок в цикле об OpenSceneGraph будет последним, выполненным в формате «How To». В рамках двенадцати статей удалось уместить базовые принципы работы и использования OpenSceneGraph на практике. Очень надеюсь, что данный движок стал более понятен русскоязычному разработчику.
Это не означает, что я закрываю тему OpenSceneGraph на ресурсе, напротив, будущие статьи планируется посвятить более продвинутым техникам и приемам применения OSG в разработке графических приложений. Но для этого следует накопить хороший материал и переработать массу англоязычных источников, а на это требуется время.
Но я не прощаюсь, благодарю за внимание и до новых встреч!
- 3d-графика
- графический движок
- openscenegraph
- c++
- Программирование
- Работа с 3D-графикой
- Разработка под Linux
- CGI (графика)
- Разработка под Windows
Источник: habr.com