[Projekt] Mein Stalker-Build

Hier könnt ihr euch selbst, eure Homepage, euren Entwicklerstammtisch, Termine oder eure Projekte vorstellen.
Forumsregeln
Bitte Präfixe benutzen. Das Präfix "[Projekt]" bewirkt die Aufnahme von Bildern aus den Beiträgen des Themenerstellers in den Showroom. Alle Bilder aus dem Thema Showroom erscheinen ebenfalls im Showroom auf der Frontpage. Es werden nur Bilder berücksichtigt, die entweder mit dem attachement- oder dem img-BBCode im Beitrag angezeigt werden.

Die Bildersammelfunktion muss manuell ausgeführt werden, die URL dazu und weitere Details zum Showroom sind hier zu finden.

This forum is primarily intended for German-language video game developers. Please don't post promotional information targeted at end users.
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [Projekt] Mein Stalker-Build

Beitrag von Krishty »

MasterQ32 hat geschrieben:
Mir geht’s vor allem darum, es spielbar zu halten in den nächsten 10, 20 Jahren. Das ist ja erfahrungsgemäß schwer ohne Quelltext.
Löblich! Ich muss die Spiele unbedingt auch mal noch spielen... Und da hat man ja gleich noch nen kleine Modernisierung dabei!

Du hast ja schon die Shadow Map hochgedreht, wie viel Aufwand wäre es, ne Option für SSAA oder MSAA einzubauen? Müsste wesentlich mehr Aufwand sein, oder?
Siehe die unteren beiden Screenshots hier: https://zfx.info/viewtopic.php?f=10&t=4 ... 1df#p55028

Das ist ein Deferred Renderer, also muss ich die Auflösung aller Buffer (Color, Light, Ambience, Material, …) parallel hochdrehen. Ich muss aber außerdem zwischen interner Auflösung und angezeigter Auflösung unterscheiden. Und hier wird’s haarig, denn die Shader haben hunderte Parameter und sobald man einen vergisst, sieht es wie oben aus.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
xq
Establishment
Beiträge: 1581
Registriert: 07.10.2012, 14:56
Alter Benutzername: MasterQ32
Echter Name: Felix Queißner
Wohnort: Stuttgart & Region
Kontaktdaten:

Re: [Projekt] Mein Stalker-Build

Beitrag von xq »

Schade, der Screenshot mit 2x2-SSAA sah schon besser aus
War mal MasterQ32, findet den Namen aber mittlerweile ziemlich albern…

Programmiert viel in ⚡️Zig⚡️ und nervt Leute damit.
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [Projekt] Mein Stalker-Build

Beitrag von Krishty »

Ja; es steht noch immer auf meiner To-Do-Liste – dass es mir wichtig ist, sieht man ja daran, dass ich es recht früh ausprobiert habe. Aber es wird halt ein großes Unterfangen :(
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [Projekt] Mein Stalker-Build

Beitrag von Krishty »

Ich versuche immer nebenher, das unübersichtliche Gewirr aus willkürlichen DLLs zu lichten, indem ich Module zusammenfasse. Am Ende soll maximal eine EXE mit drei DLLs übrig bleiben. (S.T.A.L.K.E.R. exportiert tausende(!) Funktionen über DLL-Grenzen, und das behindert den Optimizer gewaltig. Auf exportierte Funktionen lässt sich z. B. weniger Aliasing-Analyse anwenden und kein Inlining. Ganz übel.)

Das lief bisher relativ gut. Es gab oft Konflikte in der Initialisierungsreihenfolge globaler Variablen, aber dann packe ich die Initialisierung halt in eine Funktion und schiebe den Aufruf an eine Stelle, an der er keine Probleme mehr macht.

Ein besonderes Problem ist aber das Lua-Modul (xrLua.dll). Zur Erklärung: Sehr viel KI und Gameplay in S.T.A.L.K.E.R. wurde mit Lua gescriptet. Lua hat einen Just-in-Time-Compiler, der Lua zu x86-Befehlen kompiliert, damit es mit quasi-nativer Geschwindigkeit ausführbar ist. Und das … kracht.

Nicht erst seit der Vereinigung mit der Haupt-EXE – ich habe gemerkt, dass es immer kracht, sobald es mit Optimierung kompiliert wird! Ein Zeiger in einem Callback ist dann verschoben. Der Code, der den Zeiger bereitstellt, ist automatisch erzeugt – und deshalb kaum zu debuggen.

Hm. Ich habe das Problem mit Binärsuche auf eine Quelldateie lfunc.c eingegrenzt, die ohne Optimierung kompiliert werden muss. Nun, kann ich das Problem hoffentlich via #pragma optimize("", off) auf eine einzelne Funktion bestimmen. Ich bin gespannt, ob der Auslöser lückenhafter Code ist (undefiniertes Verhalten?) oder ein weiterer Bug in Visual C++.

Nachtrag: Der Übeltäter ist die selbe Funktion, die auch abstürzte:

Code: Alles auswählen

#pragma optimize("g", off)
UpVal *luaF_findupval (lua_State *L, StkId level) {
  global_State *g = G(L);
  GCObject **pp = &L->openupval;
  UpVal *p;
  UpVal *uv;
  while ((p = ngcotouv(*pp)) != NULL && p->v >= level) {
    lua_assert(p->v != &p->u.value);
    if(p->v == level) {  /* found a corresponding upvalue? */
      if(isdead(g, obj2gco(p)))  /* is it dead? */
        changewhite(obj2gco(p));  /* ressurect it */
      return p;
    }
    pp = &p->next;
  }
  uv = luaM_new(L, UpVal);  /* not found: create a new one */
  uv->tt = LUA_TUPVAL;
  uv->marked = luaC_white(g);
  uv->v = level;  /* current value lives in the stack */
  uv->next = *pp;  /* chain it in the proper position */
  *pp = obj2gco(uv);
  uv->u.l.prev = &g->uvhead;  /* double link it in `uvhead' list */
  uv->u.l.next = g->uvhead.u.l.next;
  uv->u.l.next->u.l.prev = uv;
  g->uvhead.u.l.next = uv;
  lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
  return uv;
}
#pragma optimize("g", on)
Nehme ich die #pragma optimize raus, dann kommt L mit falschem Wert an (120 B verschoben, was exakt der Größe von lua_State entspricht).

Nachtrag 2: Wer das mit den tausenden exportierten Funktionen für eine Übertreibung hielt: Meine xr_3DA.exe exportiert hier gerade 2398 Funktionen; xrCore.dll 606. Ich brenne darauf, den Müll endlich rauszuschmeißen.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [Projekt] Mein Stalker-Build

Beitrag von Krishty »

Ich habe die DLL für den Renderer und die EXE des Spiels verschmolzen. Weil ich sechs(!) verschiedene vorkompilierte Header innerhalb des selben Projekts nicht mehr pflegen wollte, habe ich vorkompilierte Header komplett abgeschaltet.

Das Ergebnis ist, dass der Linker nun mehr als 4 GiB RAM verbraucht, und dann erstmal mangels Adressraum abschmiert.

Wieder was gelernt: Wenn man in der .vcxproj-Datei unter <PropertyGroup Label="Globals"> den zusätzlichen Wert <PreferredToolArchitecture>x64</PreferredToolArchitecture> einträgt, wird auch für 32-Bit-Programme der 64-Bit-Compiler/-Linker eingesetzt. Das ist langsamer und verbraucht mehr Speicher, aber damit kriegt man dann auch 4+ GiB gelinkt … (Es hat sich nun bei 5.7 GiB eingependelt.)
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [Projekt] Mein Stalker-Build

Beitrag von Krishty »

Krishty hat geschrieben: 14.04.2018, 23:24Ich präsentiere hiermit die Abhängigkeiten der S.T.A.L.K.E.R.-Teilprojekte untereinander:
Das ist nun alles zu einer großen EXE verschmolzen. Keine DLL-Hölle mehr; keine zyklischen Abhängigkeiten mehr; nur noch ein riiiiesiges Projekt, das 20 Minuten kompiliert und 6 GiB zum Linken braucht.

Das Verschmelzen hat rund 100 KiB Code rausgeschmissen, weil der Optimizer nun über Funktionsgrenzen optimieren kann und tausende überflüssige Import- und Exporttabelleneinträge entfernen konnte.

Außerdem bin ich auf Visual Studio 2019 umgestiegen, was wiederum an die 100 KiB durch verbesserte Code Generation gebracht hat. Insgesamt fast vier Prozent Größe runter. Geschwindigkeits-Benchmarks muss ich mal nachreichen.

Download: http://krishty.com/stalker_en
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Schrompf
Moderator
Beiträge: 4838
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: [Projekt] Mein Stalker-Build

Beitrag von Schrompf »

Sehr cool. Entspricht auch meinen seit Jahren gepflegten Vorurteilen vom statischen Linken :-)
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [Projekt] Mein Stalker-Build

Beitrag von Krishty »

Bloom und sRGB

S.T.A.L.K.E.R. ist aus den frühen 00ern, und deshalb kommt es mit einer dicken Portion Bloom.

Bloom wird gern als Gaußfilter implementiert – horizontal blurren, vertikal blurren, zum Bild addieren. Wenn man das auch so umsetzt, erhält man diesen Matsch:

Bild

Um das zu vermeiden, und wirklich nur die stark leuchtenden Bildteile strahlen zu lassen, führt man üblicherweise einen Grenzwert ein. Alles, was dunkler als dieser Grenzwert ist, wird im Bloom ignoriert. (Steuerbar hier via r2_ls_bloom_threshold.)

Das führt dann zum perfekten 00er-Look, bei dem alle hellen Bildteile total bloomen und alle mittelhellen und dunklen Bildteile absolut gar keinen Bloom haben (hier bewusst übertrieben):

Bild

Ich bin großer Feind des Thresholds und nutze es grundsätzlich nicht.

Die grundsätzliche Idee – Gauß zum Bild addieren – ist nicht verkehrt. Sie ist sogar relativ nah an dem, was im Auge passiert. Ich bin sogar ein kleines Bisschen Bloom-Freund.

Aber warum sieht das erste Bild oben dann derart vermatscht und verkehrt aus?

Das Problem ist, dass hier HDR versucht wird, ohne die Gammakurve zu beachten. Die Pixel des Back Buffers sind im sRGB-Farbraum mit Gamma ~2.2. Wenn man zwei Pixel addiert, die 10% Helligkeit haben, kommen naiv 20% Helligkeit heraus. Tatsächlich sollten es aber (0.1 ^ 2.2 + 0.1 ^ 2.2) ^ 1/2.2 sein; also eher 14% Helligkeit.

Da der Bloom sehr viele Pixel aufaddiert, ist der Fehler entsprechend groß – und der Bloom viel zu grell.

Also lasst uns S.T.A.L.K.E.R. so umbauen, dass es sRGB-korrekt rendert!

Das klingt schwieriger, als es ist. Das Spiel baut auf Direct3D 9. Dessen Mittel für sRGB sind relativ beschränkt, und lassen sich wie folgt zusammenfassen:
  1. Für jede Textur muss SetSamplerState(D3DSAMP_SRGBTEXTURE, TRUE) aufgerufen werden, so dass die Texel im linearen Farbraum geladen werden.
  2. Vor dem Rendern muss SetRenderState(D3DRS_SRGBWRITEENABLE, TRUE) aufgerufen werden. So werden die gerenderten Pixel beim Schreiben in den Back Buffer in den sRGB-Farbraum konvertiert.
Naja, ganz so einfach ist es nicht. Wer blind die beiden Aufrufe einbaut, wird merken, dass das Menü grün wird und das Spiel nur noch einen weißen Bildschirm anzeigt. S.T.A.L.K.E.R. nutzt auch Normal Maps und Displacement Maps (bspw. für Hitzeflimmern im Deferred Rendering), und wenn die fälschlicherweise als sRGB interpretiert werden, kracht es gewaltig.

Wir machen’s vorsichtiger. Wir setzen in der Funktion, die den Bloom-Filter implementiert, sRGB und setzen es danach wieder zurück:

    // r2_rendertarget_phase_bloom.cpp

    void CRenderTarget::phase_bloom()
    {
        for(int i = 0; i < 256; ++i)
            RCache.dbg_SetSS(i, D3DSAMP_SRGBTEXTURE, TRUE);
        RCache.dbg_SetRS(D3DRS_SRGBWRITEENABLE, TRUE);


        …

        for(int i = 0; i < 256; ++i)
            RCache.dbg_SetSS(i, D3DSAMP_SRGBTEXTURE, FALSE);
        RCache.dbg_SetRS(D3DRS_SRGBWRITEENABLE, FALSE);

    }


Das selbe für das Rendering der Geometrie:

    // r2_R_render.cpp

    void CRender::Render()
    {
        …
        LP_normal.sort();
        LP_pending.sort();

        for(int i = 0; i < 256; ++i)
            RCache.dbg_SetSS(i, D3DSAMP_SRGBTEXTURE, TRUE);
        RCache.dbg_SetRS(D3DRS_SRGBWRITEENABLE, TRUE);


        …

        // Lighting, dependant on OCCQ
        render_lights(LP_pending);

        for(int i = 0; i < 256; ++i)
            RCache.dbg_SetSS(i, D3DSAMP_SRGBTEXTURE, FALSE);
        RCache.dbg_SetRS(D3DRS_SRGBWRITEENABLE, FALSE);


        // Postprocess
        Target->phase_combine();
    }


TADAAAA

Bild

Ich musste natürlich ein paar Faktoren anpassen, da sich durch sRGB die Gesamthelligkeit des Bildes geändert hat.

Aber der Bloom ist nun an hellen Stellen genau so stark wie vorher, und an mittleren und dunklen Stellen viiiiel schwächer. Außerdem ist die Beleuchtung nun halbwegs sRGB-korrekt. Und das wirkt sich insbesondere auf die indirekte Beleuchtung aus:

Bild

Ich zementiere diese Einstellungen noch als Voreinstellung beim ersten Start der Engine, so dass sie jeder User meiner EXE automatisch bekommt. Und dann ist mal wieder ein Update fällig.

Jedenfalls kriegt man einen Hauch von sRGB recht einfach sogar in eine bestehende D3D9-Engine gezimmert. In diesem Fall waren vier Code-Ergänzungen ausreichend, wenngleich mit der Holzhammer-Methode. Wenn man es richtig machen wollte, würde man nun den Code der Lichter, Vertex-Farben, Materialien, usw. an sRGB anpassen.

Nun, wo der Bloom nicht mehr so stark weichzeichnet, fällt das fehlende Antialiasing stärker auf. Das könnte ich als nächstes angehen.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Thoran
Establishment
Beiträge: 224
Registriert: 15.05.2009, 12:51
Wohnort: Stuttgart
Kontaktdaten:

Re: [Projekt] Mein Stalker-Build

Beitrag von Thoran »

Krishty hat geschrieben: 28.05.2020, 20:36 Nun, wo der Bloom nicht mehr so stark weichzeichnet, fällt das fehlende Antialiasing stärker auf. Das könnte ich als nächstes angehen.
Vielleicht gabs ja einen Grund für das übertriebene Weichzeichnen? ;-)
Wer Rechtschreibfehler findet, darf diese gerne behalten.
Mein Entwicklertagebuch
Aktuelle Projekte: Universum: Domination (ehemalig AlphaOmega),Universum: Sternenjäger, PixelWars: Highscore-based Top-Down-Spaceshooter
Spieleengine Unreal 5
scheichs
Establishment
Beiträge: 845
Registriert: 28.07.2010, 20:18

Re: [Projekt] Mein Stalker-Build

Beitrag von scheichs »

Also... Ich muss wieder mal sagen: Mega! Danke für die geilen, verständlichen Erklärungen (gamma-korrigiertes Aufaddieren der Helligkeit).
Und das Ergebnis kann sich auch sehen lassen!
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [Projekt] Mein Stalker-Build

Beitrag von Krishty »

Gern!
Thoran hat geschrieben: 04.06.2020, 12:40Vielleicht gabs ja einen Grund für das übertriebene Weichzeichnen? ;-)
Ja – nämlich, dass die in den 00er aufgewachsenen die Generation der Bloomers sind.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Antworten