Я играю и бросаю играть в Обливион уже лет десять, и всё то время, когда он стоит на моем ПК, у игры всегда наблюдаются проблемы, занимающие мой ум. Например, почему Западные Врата Чейдинхола так лагают? Я уверен, что и у вас не наблюдалось строгих 60 FPS в этой игре. Я ожидаю просадок, но даже в оригинальной игре я получаю только 30 FPS при i5 4690K при 4.4GHz и RX 570.
Ладно, я тут пока писал стратью погонял с DXVK HUD и сравнил с Gallium HUD и, снова переключившись на DXVK, я заметил, что оптимизация улучшилась в разы. Переключился на Gallium HUD и снова получил хороший результат. Причина этого поста, по ходу, улетучилась, но может быть, имеет смысл для вашего игрового сетапа. Фреймрейт, который вы увидите, не стоит воспринимать как данность. Не знаю, что я сделал, починив этот косяк разработчиков. Но это все еще интересная проблема.
Это старая игра, а наше железо уже в тыыыыщу раз круче того, что было в те годы. AnandTech использовал Athlon 64 dual core и SLI/Crossfire GPUs (который скалировался очень хорошо, Oblivion хорошо с ним ладит), и было верхом успеха получить 30 FPS при средних настройках в виде 1024x768. Сейчас у нас GPU и CPU за $200, разгоняющие современные игры до 100FPS при 1080p, но в Oblivion мы все также пытаемся вытянуть из фреймрейта 60FPS. Что за ерунда? Это большая тема, в которыю я сейчас не хочу погружаться. Поэтому обьясню проблему вкратце простыми словами, опираясь на свои наблюдения.
Использование системы обливионом
Обливион - плоть от плоти эпохи гейминга на DirectX 9. Он использует движок GameBryo, дополненный после Морровинда пачкой нововведений. Для нас в данном случае важны следующие: физика от Havok, уровень детализации на расстоянии (LOD) и динамическое освещение. Radiant AI тоже был таким нововведением, хотя по факту это улучшение того, что мы уже видели в Морровинде.
Использование GPU
Оригинальная игра, даже с модами, едва ли использует GPU. Единственные эффекты, которые действительно нагружают GPU, это вещи по типу шейдеров из ENB или Oblivion Reloaded. Большая часть рендерящихся эффектов, как рефракция или отражения в воде, привязаны к GPU. Современные GPU даже не заметят этой нагрузки, поэтому наши GPU всегда используются не на 100%.
Использование CPU
Будучи игрой из 2006 года, она не любит многопоточность. Большая часть вещей (вызовы отрисовки и ИИ – самые нагружающие) находятся в главном потоке CPU, когда как 1 и, возможно, дополнительный поток делают что-то еще (OSR, кажется, что-то делает с третьим потоком, но этого я еще не тестировал). Пусть ИИ действительно тяжел для загрузки, но в той зоне Чейдинхола лишь 2 стражника у Западных Ворот, так что их ИИ – просто погрешность. Вокруг нет ничего, что затрагивало бы физику. Динамическое освещение, отрисовываемое CPU, отсутствует. Едва ли есть ЛОДы в этой ячейке Чейдинхола, да и оригинальная игра не то чтобы много их в себе содержит. И если ЛОДы не проблема, то тогда откуда такая нагрузка?
draw calls
Вы скорее всего уже слышали такой термин и возможно в курсе, что «чем их больше, тем ниже оптимизация», но что по сути из себя представляет вызов отрисовки (draw call)? GPU, особенно старые, довольно тупые. Они просто берут информацию и рендерят её на экране. Сейчас GPU стали очень комплексными и способными делать множество вещей, которые выпадали на долю CPU в играх, но в 2006 это была мечта! Сама концепция шейдеров тогда еще была меньше десяти лет от роду. Так как вообще рендерят обьект? Откуда инфа о нем приходит?
CPU говорит GPU что, где и как отрендерить. Самый важный аспект из представленных это ЧТО мы будем рендерить, так как он самый ограничивающий. В нашем контексте, я опишу весь меш обьекта как модель, а весь маппинг текстуры (texture mapping) как текстурную карту (texture map). Отдельные компоненты – это меши и текстуры. Сингулярный обьект, ну скажем, модель персонажа, это не единый меш с единой текстурой, привязанной к нему. Это комплексная модель, разделенная на части, позволяющая тем самым легко текстурировать и модифицировать эту модель. То есть вы разделяете модель персонажа на три меша с двумя текстурами на каждый (цвет и карта нормалей (normal map)).
Затык в том, что CPU не знает, что это один обьект. Для него это 3 меша с 2 текстурами на каждом, и он говорит GPU: «здесь 9 штук надо отрендерить». Так что вместо того чтобы модель персонажа была единым мешем с двумя текстурами, у неё три меша с шестью текстурами в совокупности. На наших глазах у нас утроилось количество вызовов отрисовки на одну модель. И это самая медленная часть рендеринга 3D графики, её узкое горлышко. Настолько медленная, что соверменные движки выгружают как можно больше в GPU, чтобы CPU не тратило время на вызовы отрисовки.
Современные CPU, кажется, ограничены около 10 тысячами вызовов отрисовки перед тем как FPS упадет ниже 60. Однако больше вызовов отрисовки не означает падение FPS в ноль. Чейдинхол вызывает около 46 тысяч вызовов отрисовки, но 30 FPS вполне способен удержать, в то время как 20 тысяч вызовов отрисовки из RAEVWD не могут стабильно выдавать даже 25 ФПС. Это раазница, которую нужно держать в уме. Смотрите на вызовы отрисовки в конкретной области, а не в игре в целом.
тестирование
Сперва я создал HUD чтобы отражать информацию, которую я хочу видеть. Используя Линукс и AMD GPU, я перешел на Gallium, используя Gallium New драйвер в виде аддона для игр на Wine. Это дало мне информацию по каждому ядру CPU, FPS, загрузке GPU, и количеству вызовов отрисовки.
Первые мысли
Изначально я был убежден, что собака зарыта в освещении (lights). Я тестил стартовую ячейку в тюрьме и думал, что источники света вызывают около 1500 отрисовок. Это, мягко говоря, многовато для света. Поэтому я пошел в Чейдинхол и повозился с освещением у Западных Ворот, быстро выяснив, что дело не в источниках света.
Их отключение ни к чему не привело! Ясно, что я иду в неправильном направлении.
Следующая мысль
Тогда я решил, что проблема в домах. Я уже знал, что они сделаны неэффективно. Поэтому я протестил дома и отключил их.
И увидел, что количество вызовов отрисовки падает в разы! 5000 вызовов отрисовки тут же пропали.
Тогда я решил сделать нечто еще более радикальное и удалил пачку домов рядом с собором и снова потестил область.
Почти 20 тысяч вызовов отрисовки тут же испарились. Проблема была ни в источниках света, ни в ЛОДах. Виноваты дома Чейдинхола!
обливион и вызовы отрисовки
Обливион разработан для ПК и Xbox360 соответственно. По правде кое в чем он разрабатывался в первую очередь под Xbox360. У консоли было только 512 МБ памяти для работы на всю систему, когда как самый скромный ПК скорее всего имел 1 ГБ системной памяти и 256 МБ видеопамяти в то время. К тому же игра была создана под один двухслойный диск DVD (содержит около 8 ГБ). Бесезда должна была минимизировать размеры текстур, при этом не делая из игры заблюренную кашу. Чтобы добиться этого они создали текстуры по единому образцу (generic textures) для общих мешей по единому образцу (generic meshes), чтобы состыковать кусочки мешей вместе и сделать тем самым модель. Эти меши так же соединялись по единому образцу при создании новых строений. Они не могли добиться того чтобы в игре были один меш с одной-двумя текстурами на модель, это бы съело слишком много места на диске и в памяти. Типичный дом в Чейдинхоле имеет следующую модель:
Каждый NiTriStrips имеет соответствующую текстуру, и эта текстура должна иметь соответствующую карту нормалей. Это около 50 вызовов отрисовки на дом. А у нас десятки домов перед глазами единовременно. И Обливион не имеет Occlusion Culling, так что все эти дома рендерятся всегда, когда находятся перед глазами. Так что неудивительно, что Чейдинхол не шибко оптимизирован.
математическая проблема
Если сложить в уме, то окажется, что 50 вызовов отрисовки на дом не могут привести к 46 тысячам вызовам отрисовки в Западных Воротах. Честно? Я тоже не знаю, как это работает. Очень сложно определить, что именно требует вызова отрисовки, особенно, когда у нас нету SDK движка. Если у кого есть более продвинутые познания, я бы мечтал узнать об этом от вас.
решение
Пока что есть только одна вещь, фиксящая проблемы вызовов отрисовки в Обливионе, и она не самая простая в реализации. Все статичные модели игры (камни, здания, и тд) нужно переделать в единый меш с использованием атласной текстуры. Морровинд имеет восхитительный проект Атласного Текстурирования, который включает все модели игры и комбинирует компоненты мешей в единую модель. Если сделать нечто подобное для домов в Чейдинхоле, то вместо 50 вызовов отрисовки на один дом у нас будет около 3,6% вызовов отрисовки от этого числа. Я бы потестил это сам, но не умею моделировать, да и времени учиться этому нет.
VWD opitimized meshes qwertyasdfgh’а это отличная точка отчета, но это только для ЛОДов. Как по мне нам нужен проект, который включит в себя все оригинальные меши. В таком случае даже оригинальные VWD меши будут хорошо оптимизированы. Как мне кажется, это единственный способ сделать Обливион оптимизированным в ближайшем будущем, особенно с учетом порта на OpenMW, который появится лет через 5 минимум, и тем, что Борис не вернется в Обливион чтобы дать нам Occlusion Culling. Тогда проблема Чейдинхола наконец-то будет решена.
Комментарии