image ©Maxim Nikolaev
Port na OSG już grywalny 2015-06-13 - Vedyimyn

(Niniejszy tekst jest luźnym tłumaczeniem wypowiedzi scrawla. Z uwagi na trudności w przekładzie technicznego języka, niektóre fragmenty zostawiam po angielsku, a niektóre, drobne, pomijam. Proszę wybaczyć niektóre neologizmy, jeśli takowe powstały, starałem się jak mogłem ;) )

Przez ostatnie trzy miesiące zespół OpenMW ciężko pracował, by przeportować kod z silnika Ogre3D na OpenScenGraph (w skrócie OSG). Można o tym poczytać w jednym z poprzednich postów (tutaj).

Mamy zaszczyt ogłosić, że nasze wysiłki wreszcie wydały owoce. Wszystkie funkcje istotne dla gameplayu zostały przeportowane, tak więc użytkownicy mogą cieszyć się pełnoprawnym Morrowindem z gałęzi rozwojowej OpenMW-osg.

Niektóre zaawansowane funkcje – shadery, odległy teren, cienie i refleksy na wodzie – nie zostały jeszcze przeniesione. Można już jednak powiedzieć, że przejście na nowy silnik było wielkim sukcesem, nawet większym, niż się spodziewaliśmy. Odnowiony OpenMW ładuje się szybciej, wyświetla więcej klatek na sekundę, wygląda bardziej jak oryginalna gra oraz naprawia wiele długowiecznych bugów, którymi trudno się było zająć, korzystając z poprzednich narzędzi.

Zaraz, zaraz… Więcej klatek? Przetestujmy…

Pierwszy benchmark

Sprzęt, na którym testowano:
GeForce GTX 560 Ti/PCIe/SSE2, procesor AMD Phenom(tm) II X4 955 × 4, Linux 3.13.0-24-generic x86_64
1680×1050, pełny ekran, bez AA, 16x AF, bez refleksów na wodzie, cieni i shaderów
Maksymalny zasięg widzenia, ustawiony za pomocą suwaka w ustawieniach.

osg_bench
Scena testowa: stara, dobra (zacinająca się) Balmora.

Wielkości średnie OpenMW OpenMW-osg
Klatek na sekundę 49 75
Czas ładowania 7s 3.4s
Zajęta pamięć 344.6mb 277.1mb

OSG wygrywa we wszystkich kategoriach, co nie jest zaskoczeniem. Poprawa liczby klatek na sekundę zadowala, ale nie jest to trzy-, czterokrotna poprawa, jaką widzieliśmy w poprzednich testach, na pojedynczym modelu. Nie jest to powód do zmartwienia, ale jednak trzeba patrzeć na te wyniki z przymrużeniem oka:

  1. To porównanie nie jest fair. Do gałęzi OSG dodano nowe funkcje, które przybliżają nas do kompatybilności z oryginalnym Morrowindem, ale też wpływają na wydajność. Na przykład bryły brzegowe są dynamicznie rozszerzane, zależnie od animacji, co naprawia niesławny Bug 455 objawiający się znikaniem skrzekaczy pod pewnymi kątami. Ta zmiana odbija się na liczbie klatek. Wyrzucono static geometry batching (statyczne przetwarzanie geometrii?), które poprawiało wydajność, ale niosło ze sobą wiele problemów, na przykład niepoprawne oświetlenie albo brak ruchu pewnych obiektów. Pomimo tych dodatkowych obciążeń, OSG jest wciąż szybszy!
  2. Po dodaniu brakujących funkcji, zysk wydajności będzie większy. Powyższe porównanie uczyniono przy minimalnych ustawieniach graficznych, z uwagi na obecny brak implementacji zaawansowanych funkcji (shaderów, refleksów wodnych, itd.) w OSG. Spodziewamy się, że gdy tylko te funkcje się pojawią, spowodują mniejszy spadek wydajności, niż na starym silniku. Wynika to z lepszego dopasowywania się OSG do obciążenia GPU. Rysowanie działa w innym wątku niż reszta programu, toteż wyświetlanie złożonej sceny nie koliduje z realizacją fizyki, skryptów i animacji.
  3. Prawdziwa optymalizacja jeszcze się nie zaczęła. Na razie nacisk położono na to, by gra wróciła do stanu grywalnego, co stało się zaledwie parę dni temu. Teraz pojawiło się wiele nowych możliwości optymalizacji. Nowy silnik daje nam większą kontrolę nad procesem rysowania sceny, oraz nad jej zmianami. Dopiero zaczynamy z tego korzystać. Planowane optymalizacji obejmują:
    1. Przeniesienie aktualizacji skinów (skinning updates) do wątku roboczego.
    2. Przeniesienie aktualizacji cząsteczek do wątku roboczego.
    3. Współdzielenie stanu między różnymi NIF-ami.
    4. Dodanie cullingu dla emiterów cząsteczek. (Enable culling for particle emitters/programs.) [culling – usuwanie obiektów zasłoniętych przez inne obiekty, przyp. tłum.].
    5. Integrate a model optimizer. Morrowind’s models unfortunately contain plenty of redundant nodes, redundant transforms, and redundant state, which impacts rendering performance. The original engine runs an “optimizer” pass over the models upon loading them into the engine. We should implement a similar optimizer pass. OpenSceneGraph dostarcza przydatne narzędzie: osgUtil::Optimizer that might prove useful for this very purpose.
    6. Create a more balanced scene graph, e.g. a quad tree, to reduce the performance impact of culling and scene queries.
  4. Rendering to nie jedyne wąskie gardło. Założenie, że N razy szybszy silnik da nam N razy szybsze działanie programu jest błędne. Wiele innych czynników przyczynia się do czasu generowania pojedynczej klatki. Teraz, kiedy mamy szybszy silnik, inne wąskie gardła stały się bardziej widoczne. Obecnie największymi łobuzami są systemy odpowiadające za fizykę i animację. Wprowadzono parę wstępnych poprawek, ale bez wątpienia można zrobić więcej.

Podsumowując, większa wydajność to nie wszystko, czego użytkownicy mogą się spodziewać.

Wstępna lista zmian:

Poprawki w renderingu:

  1. Wieloosiowe skalowanie NPC-ów (Bug 814):
    Niektórzy NPC-e są teraz skalowani wzdłuż osi X i Y, co nadaje im grubawy wygląd, jak w oryginalnym Morrowindzie. Poprzednie wersje OpenMW nie mogły tego osiągnąć z powodu ograniczeń Ogre3D.
  2. Zwiększenie precyzji renderingu: gdy gracz znajdował się daleko od początku świata (co dawało duże współrzędne jego położenia) działy się dziwne rzeczy. Filmik.
  3. Usunięto statyczne przetwarzanie grafiki (static geometry batching): naprawa Bugu 385 (niepoprawne oświetlenie), naprawa ruchu obiektów pod wpływem skryptów (Bug 602), poprawa czasu ładowania sceny.
  4. Przezroczystość wygląda teraz tak, jak w oryginale: poprzednie wersje OpenMW radziły sobie z przezroczystością inaczej, niż oryginalny Morrowind, co miało ułatwić implementację statycznego przetwarzanie grafiki (static geometry batching). Poprawiono to. Widać, że przezroczyste obiekty mają gładsze krawędzie.
  5. Dodanie cullingu małych rzeczy (small feature culling option): oprócz usuwania obiektów spoza ekranu, można także wykonać culling obiektów mniejszych od piksela po wyrenderowaniu. Wizualnie nie widać zmiany, więc ta opcja jest domyślnie włączona.
osg_scaling osg_transparency
Porównanie skalowania NPC Porównanie przezroczystości

Zmieniono loader NIF-ów:

  1. Wsparcie dla skalowania wieloosiowego w plikach NIF  (Bug 2052).
  2. Poprawiono ograniczenie liczby węzłów w plikach NIF (Bug 2187).
  3. Poprawiono „zamarzanie animacji” przy cullingu obiektu (Bug 2151).
  4. Poprawiono algorytm skinningu, dla zwiększenia wydajności renderingu.
  5. Dynamiczne rozszerzanie brył brzegowych zależnie od animacji. Załatwia to Bug 455 (znikanie niektórych istot pod pewnymi kątami).
  6. Współdzielenie stanu NIF-ów (scene graphs are now a shared resource); drastyczne skrócenie czasu ładowania.
  7. Klucze animacji są teraz zasobem współdzielonym.

Przepisanie fizyki:

  1. Przy kompilacji z użyciem Bullet 2.83 lub nowszym, można skorzystać z funkcji btScaledBvhTriangleMeshShape, co poprawia wydajność instancingu kształtu (shape instancing).
  2. Usunięcie „szczegółowego” ray castingu, na rzecz bezpośredniego ray castingu, co znacznie zmniejsza zużycie pamięci.
  3. Użycie btCollisionWorld w miejsce btDynamicsWorld, żeby uniknąć zbędnych aktualizacji funkcjonalności, której nie używamy.
  4. Mapowanie obiektów kolizji przez wskaźnik zamiast nazwy.

Nowy ray casting:

  1. Użycie osgUtil::IntersectionVisitor dla bezpośredniego raycastingu.
  2. Wsparcie dla ray castingu zamiast  animowanych siatek (meshy). Tak naprawiono Bug 827.
  3. Przepisano algorytm wyświetlania postaci w oknie ekwipunku (podgląd obecnego ubioru) tak, aby używał ray castingu zamiast bufora selekcji, co poprawia responsywność.

Poprawiono ekran ładowania:

  1. Ekran ładowania jest renderowany w osobnym wątku, nie blokując w ten sposób procedury ładowania.
  2. Zwiększono liczbę klatek na sekundę w oknie łądowania, co upłynnia ruch paska ładowania.
  3. Wczytywanie obiektów OpenGL w osobnym wątku, w tle, w czasie ładowania obszaru, używając osgUtil::IncrementalCompileOperation.

Poprawa wsparcia dla SDL2

SDL2, wieloplatformowa biblioteka używana do obsługi wejścia i do tworzenia okien, została bardziej zintegrowana z systemem renderingu. Praktyczne korzyści obejmują:

  1. Opcja antyaliasingu wreszcie działa na Linuksie (Bug 2014).
  2. SDL2 odpowiada teraz za kontekst graficzny, co oznacza, że nowe API wyświetlania, takie jak Wayland i Mir na Linuksie, będą automatycznie wspierane bez przeróbek kodu.

osg_antialiasing
Antyaliasing 8x w akcji

Dynamiczna analiza programu

Miłym efektem ubocznym używania OSG jest możliwość korzystania z wysokiej klasy narzędzi do dynamicznej analizy programu. Klawisz F3 uruchamia nam podgląd, dający świetne informacje na temat programu.

osg_profiling
Dynamiczna analiza programu (Profiling overlay) – kolorowe paski obazują wątki wewnęrzne OSG, biały logikę OpenMW

Poprawki pasywne

OpenMW używa ujednoliconego silnika OpenGL na wszystkich platformach. Direct3D nie jest już wspierany, co ułatwia utrzymanie kodu i odciąża zespół.

Mówiąc praktycznie, w ten sposób naprawiono Bug 2186 (piksele-śmieci na minimapie na Windowsie) i Bug 1647 (wysypywanie się przy przełączeniu na pracę w oknie, na Windowsie).

Różne zmiany

Jest parę zmian nie związanych z przejściem na OSG, ale powstały w tej gałęzi kodu, dla redukcji liczby problemów przy łączeniu z resztą kodu:

  1. Zmieniono zasięg aktywacji dla świateł (Bug 1813).
  2. Poprawiono siłę NiGravity (Bug 2147).
  3. Dodano tryby ekstrapolacji kontrolera (Bug 1871).
  4. Dodano procesor cząsteczek NiPlanarCollider (Bug 2149).
  5. Dodano skalowanie interfejsu użytkownika:
osg_ui_scale_1 osg_ui_scale_2
Normalna skala Skala 2x, ta sama rozdzielczość

Utrzymanie kodu/restrukturyzacja/oczyszczanie

Baza kodu znacząco straciła na wadzie, co jest interesujące dla developerów, niekoniecznie dla użytkowników.

  1. Kod fizyki przeniesiono do nowego subsystemu: “mwphysics”.
  2. Usunięte nazwy węzłów scen, np. identyfikator RefData::getHandle.
  3. Usunięto OpenEngine.
  4. Usunięto „platform wrapper”.
  5. Usunięto „shiny”.

W sumie usunięto około 23 000 linijek kodu:

git diff upstream/master --shortstat
689 files changed, 24051 insertions(+), 47695 deletions(-)

Co dalej?

Lista poprawek jest spora, więc naszym priorytetem będzie wcielenie portu to głównej gałęzi, doprowadzenie nocnych buildów z powrotem do stanu używalności, wypuszczenie nowej wersji.

A mówiąc o dalszej przyszłości: daleko nam do uwolnienia pełnego potencjału naszego nowego silnika. Następne kroki zostaną skierowane ku poprawie wydajności, potem przywróceniu shaderów, odległego terenu, refleksów na wodzie i cieni. Nowy loader NIF-ów pozwala na implementację wczytywania komórek w tle, co początkowo planowano jako poprawkę po wydaniu wersji 1.0. Obecnie jest to trywialne, więc pewnie zobaczymy tę funkcję jeszcze przed wydaniem 1.0.

W międzyczasie jednak, pod względem graficznym, nic nas nie powstrzymuje przed wydaniem długo oczekiwanego OpenMW 1.0, więc pewnie najpierw skupimy się na usunięciu ostatnich blokad, wydaniu wersji 1.0, dodaniu dodatkowych funkcji graficznych w wersji 1.1. Jaka będzie kolejność – wyjdzie w praniu. W szczególności, odbicia na wodzie powinny być łatwiejsze do dodania niż cienie, które i tak nie działały zbyt dobrze na Ogre.

Jeśli chcesz się podzielić swoją opinią, nie krępuj się. Niezależnie od przyjętych priorytetów, czekają nas ekscytujące chwile!

Miejsce na komentarze.
Port na OSG już działa! 2015-06-07 - Vedyimyn

Scrawl powiadomił, że nowy port już działa. Wykonał także kilka testów. Można o tym poczytać tutaj. Postaram się przetłumaczyć tego posta w sobotę. Niestety nawał obowiązków nie pozwoli wcześniej :(

During the past three months, the OpenMW team has been hard at work porting their codebase away from the Ogre3D engine and towards the OpenSceneGraph rendering toolkit. The previous post talks about our motivations.

We are pleased to announce the porting efforts are finally bearing fruit – as in, all gameplay-essential features have been ported across, so users can enjoy a legitimate game of Morrowind in the OpenMW-osg development branch.

Some advanced features – shaders, distant terrain, shadows, and water reflections – have not been ported yet. However, even this early, it is safe to say the transition has been a massive success, in more ways than we initially imagined. Players will find the new OpenMW loads faster, improves framerate, looks more like the original game, and fixes a host of long-standing bugs that proved difficult to address within our old framework.

Hold on… improved framerate? Let’s put that to the test…

The first benchmark

Our test environment shall be:
GeForce GTX 560 Ti/PCIe/SSE2, AMD Phenom(tm) II X4 955 Processor × 4, Linux 3.13.0-24-generic x86_64
1680×1050, full screen, no AA, 16x AF, no water reflections, no shadows, no shaders
Maximum view distance as per the in-game slider

osg_bench
The testing scene: good old (laggy) Balmora

OpenMW OpenMW-osg
Framerate avg. 49 75
Loading time avg. 7s 3.4s
System memory avg. 344.6mb 277.1mb

Unsurprisingly, the OSG port wins on all three counts. The framerate improvement is decent, though still far short of the 3-4x improvement we saw in earlier tests with a single model. There is no reason to be concerned, however – you should take these numbers with a grain of salt:

  1. The comparison is unfair. New rendering features are included in the OSG branch, that bring us closer to vanilla Morrowind compatibility, but affect performance as well. For example, we now dynamically expand bounding boxes based on running animations, which fixes the infamous bug of cliff racers disappearing under certain angles (Bug 455), but is taxing on frame rate as well. Likewise, we have ditched static geometry batching, a performance optimization that was causing a multitude of issues, mainly incorrect lighting and scripted movement of objects not working. Even under all this new workload, the OSG port is still faster!
  2. Expect higher performance gains for advanced graphical features. The comparison was made with the minimum graphics settings, for the simple reason that the advanced settings (shadows, reflections, etc.) do not exist in the OSG branch yet. We expect that once those advanced features are ported, their impact on framerate will be much lower than before, simply due to the new renderer scaling a lot better with regards to GPU workload. Draw submissions are now offloaded to a worker thread, so the graphical complexity of the scene does not block the main thread from performing work in the meantime such as culling, physics, scripting, and animation.
  3. The real optimization phase hasn’t even begun yet. The main focus for now has been to get the game back to a playable state, and that only happened a few days ago. Now, there are plenty of optimization opportunities on the horizon. Our new rendering framework gives us more control over how the scene graph is structured, and how updates are dispatched, something we are only just starting to take advantage of. Planned optimizations in the near future include:
    • Move skinning updates to a worker thread.
    • Move particle updates to a worker thread.
    • Share state across different NIF files.
    • Enable culling for particle emitters/programs.
    • Integrate a model optimizer. Morrowind’s models unfortunately contain plenty of redundant nodes, redundant transforms, and redundant state, which impacts rendering performance. The original engine runs an “optimizer” pass over the models upon loading them into the engine. We should implement a similar optimizer pass. OpenSceneGraph provides the osgUtil::Optimizer that might prove useful for this very purpose.
    • Create a more balanced scene graph, e.g. a quad tree, to reduce the performance impact of culling and scene queries.
  4. Rendering is not the only bottleneck. Assuming an N times faster renderer would lead to an N times faster OpenMW is wrong. We have other systems contending for frame time, and now that our renderer is faster, these other bottlenecks are becoming ever more apparent. In particular, the physics and animation systems are currently the worst two offenders. Some preliminary optimizations for these systems have made it into the OSG port, but we have no doubts there is more room for improvement.

With that said, better performance is certainly not the only change users can look forward to:

Preliminary changelog

Rendering improvements

osg_scaling osg_transparency
NPC scaling comparison Transparency comparison

Re-designed NIF loader

Physics rewrite

New raycasting

Improved loading screen

Improved SDL2 support

SDL2, the library we are using for cross-platform input and window creation, has been more closely integrated with the rendering system. Practical benefits for the user include:

osg_antialiasing
8x antialiasing in action

Profiling overlay

A nice side effect of using OpenSceneGraph is access to their top-notch profiling tools. With the ‘F3’ key, an on-screen overlay appears that shows more information with every key press.

osg_profiling
Profiling overlay – the colored bars represent OpenSceneGraph’s internal threads, the white bars OpenMW logic

Passive fixes

The new OpenMW sports a unified OpenGL renderer on all our platforms. Rendering via Direct3D is no longer supported, easing the maintenance and support overhead for the OpenMW team.

Practically speaking, we have thus “fixed” Bug 2186 (garbage pixels on the minimap on Windows) and Bug 1647 (crash when switching to windowed mode on Windows).

Miscellaneous changes

Finally, we do have some bonus changes that are not strictly related to the OpenSceneGraph transition, but were committed to the OSG branch anyway in an effort to reduce merge conflicts:

osg_ui_scale_1 osg_ui_scale_2
Normal UI scale 2x UI scale, same resolution

Code maintenance / restructuring / cleanup

The codebase has considerably lost weight, which is likely interesting to developers, though not so interesting to end-users.

In total, ~23.000 lines of code were removed:

git diff upstream/master --shortstat
689 files changed, 24051 insertions(+), 47695 deletions(-)

What’s next?

Phew, that was a lot to take in – even at this stage, the list of improvements is massive, so our first priority should be to merge the port into the main branch, get our various nightly builds up and running again, then get a new release out.

Speaking for the longer term, we are not even close to unleashing the full potential of our new rendering engine. The next steps would be to further improve performance, then work on restoring shaders, distant terrain, water reflections and shadows. Our new NIF loader facilitates the implementation of background cell loading, which was originally planned as a post-1.0 improvement – now, it would be trivial to do, so we might see this feature pre-1.0 after all.

In the meantime though, on the graphics front, there is now nothing stopping us from releasing the long awaited OpenMW 1.0, so perhaps efforts should be diverted to fix the remaining OpenMW 1.0 blockers first, get version 1.0 out the door, then port the advanced graphical features for version 1.1. We might decide this on a case-by-case basis. In particular, the water reflections should be a lot easier to port than shadows, which weren’t working particularly well in the Ogre branch anyway.

If you have an opinion on the matter, feel free to comment. Though regardless of the priorities we decide on, these are certainly exciting times ahead!

Want to leave a comment?

Zespół OpenMW ogłasza wydanie wersji konserwacyjnej 0.36.1. Dodatkowe skrypty startowe nie uruchamiały się – zostało to naprawione. Nową wersję można pobrać tutaj, dla wszystkich systemów operacyjnych.

Znane problemy:

Lista zmian:

Naprawiono:

Zapraszamy do komentowania tutaj!

The OpenMW team announces the release of maintenance version 0.36.1. This version addresses a regression that caused additional startup scripts to fail to launch. Grab it from our Downloads Page for all operating systems.

Known Issues:

Changelog:

Want to leave a comment?