OpenGL: SRGB-Rendering

V

VikingGe

Gast
Guten Abend,

folgendes Problem treibt mich gerade in den Wahnsinn: Ich möchte einfach nur gamma-korrekt rendern können.
Wenn ich das richtig verstanden habe, muss man lediglich seine Bild-Texturen in sRGB-Formaten laden (kein Problem) und am Schluss einfach in einen sRGB-Framebuffer rendern. So weit, so gut, nur habe ich keine Ahnung, wie man letzteres sinnvoll anstellt.

- Man kann ja eine sRGB-Textur an ein FBO binden und dann einfach das gerenderte Bild, das im Idealfall ohnehin in 16-Bit RGB vorliegt, dort hinein rendern. An sich ebenfalls kein Problem, aber wien bekommt man die dann auf den Bildschirm, ohne dass a) fälschlicherweise noch einmal Gamma-Korrektur angewendet wird und man b) keine Abstriche bei der Farbgenauigkeit macht?

- Man kann zumindest in der Theorie einen sRGB-Default-Framebuffer erzeugen, der einem das Geraffel eigentlich ersparen sollte. Der Punkt ist nur, das funktioniert nicht:

Code:
  [EXCEPTION] Caught unhandled exception of type SDL2RenderContextCreationError
  [EXCEPTION] In file ve_winsystem_sdl2_context_opengl.cpp, line 80:
  [EXCEPTION] SDL2: Failed to create window:
  [EXCEPTION] Couldn't find matching GLX visual   <<< Problem
  [EXCEPTION] Stack trace, most recent call first:
[...]

Code:
      SDL2->SDL_GL_ResetAttributes();
      
      SDL2->SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, this->_contextProperties->versionMajor);
      SDL2->SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, this->_contextProperties->versionMinor);
      SDL2->SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,  SDL_GL_CONTEXT_PROFILE_CORE);
      
      // TODO Find out why this does not work
      SDL2->SDL_GL_SetAttribute(SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, 1);
      
      if (this->_contextProperties->debugContext)
        SDL2->SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);

      this->_window = SDL2->SDL_CreateWindow(
        "An SDL2 window",
        SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED,
        1024, 600,
        SDL_WINDOW_OPENGL);

Bin unter Linux mit NVidia-Treiber 349.19 unterwegs. GL_ARB_framebuffer_srgb wird selbstredend unterstützt, aber das ganze scheitert in dem Fall ja schon an der Kontext-Erstellung.

Jemand Ideen?
 

Anhänge

  • glxinfo.txt
    65,7 KB · Aufrufe: 449
Zuletzt bearbeitet:
ich kann dir leider nicht sagen, warum die kontexterstellung kaputt geht.

soweit ich weiß, sollten alle default framebuffer, die du dir heutzutage so erzeugen kannst, srgb-capable sein, ohne, dass du das einstellen musst. du musst allerdings GL_FRAMEBUFFER_SRGB enablen, das ist disabled by default. nur wenn das enabled ist UND das framebufferformat sRGB ist, passiert die konvertierung. das gilt auch für FBOs, die du dir erzeugst.

es gibt keine 16-bit-sRGB-fexturformate, sRGB gibts nur für 8-bit texturen, d.h., wenn du von einer sRGB-textur liest und dass in eine 16-bit-textur schreibst, hast du darin lineare, also nicht-gammakorrigierte werte. wenn du das nun auf den bildschirm bringen willst, musst du dafür sorgen, dass eine gammakorrektur wieder angewendet wird, also wie im absatz hierüber auf framebufferformat und GL_FRAMEBUFFER_SRGB achten.

(abschnitte 8.24 und 17.3.9 in der opengl 4.5 spec, die sind ziemlich einfach zu verstehen.)

ich hoffe, das hilft dir weiter :)
 
Hallo,

erstmal danke für die Antwort und für die Hinweise auf die Specs, das ist doch schon etwas aufschlussreicher als die Beschreibung der Extension.

du musst allerdings GL_FRAMEBUFFER_SRGB enablen
Müsste ja eigentlich reichen, das einmal nach der Kontext-Erzeugung zu machen.

es gibt keine 16-bit-sRGB-fexturformate, sRGB gibts nur für 8-bit texturen, d.h., wenn du von einer sRGB-textur liest und dass in eine 16-bit-textur schreibst, hast du darin lineare, also nicht-gammakorrigierte werte.
Das ist klar, aber das sollte generell nicht (bzw. nur beim Texturen samplen, wo das Verhalten ja erwünscht ist) passieren. Folgendes habe ich vor:
- Linear rendern, Post-Processing anwenden, Compositing durchführen, GUI draufmalen etc.
- Das Produkt dann in einen SRGB-Framebuffer malen

Damit eben die linear => sRGB-Konversion als wirklich allerletzte Operation in der Rendering-Pipeline stattfindet. Und dafür hätte ich eben am liebsten einen sRGB-Default-Framebuffer.

soweit ich weiß, sollten alle default framebuffer, die du dir heutzutage so erzeugen kannst, srgb-capable sein,
Weißt du, ob man das irgendwie mit GL-Bordmitteln abfragen kann? Ich weiß wohl, dass GL_EXT_framebuffer_srgb eine Konstante dafür bietet, aber ich möchte ungern mit einer EXT-Extension herumfrickeln, die heute kein Mensch mehr braucht.

Ich habe im Moment auch leider noch nichts zum Rendern, weil ich den Code mal wieder umgeschmissen habe, sonst könnte ich ja mal ausprobieren, was da aktuell so passiert - aber ich hätte eben schon gerne eine Garantie dafür, dass alles so funktioniert, wie ich mir das vorstelle. Sonst muss ich da ggf. die Konversion selbst in einem Shader durchführen - ebenfalls etwas, was ich gerne vermeiden würde.

EDIT: Scheint bislang tatsächlich auch so zu funktionieren. Dann frage ich mich allerdings, warum SDL dann keinen Kontext erzeugen kann, wenn man es explizit aktiviert - zumal in der Dokumentation steht, dass es standardmäßig deaktiviert ist.
 
Zuletzt bearbeitet:
Müsste ja eigentlich reichen, das einmal nach der Kontext-Erzeugung zu machen.
ja, genau.

Das ist klar, aber das sollte generell nicht (bzw. nur beim Texturen samplen, wo das Verhalten ja erwünscht ist) passieren. Folgendes habe ich vor:
- Linear rendern, Post-Processing anwenden, Compositing durchführen, GUI draufmalen etc.
- Das Produkt dann in einen SRGB-Framebuffer malen
solange sämtliche zwischenergebnis-buffer auch 16 bit oder ein sRGB-format haben, klar, kannst du machen. (8bit texturen ergeben dann sinn wenn mehr sich nicht lohnen, da 16 bit natürlich performance kosten können)

Weißt du, ob man das irgendwie mit GL-Bordmitteln abfragen kann?

falls du immer noch das format abfragen willst, schau dir https://www.opengl.org/sdk/docs/man3/xhtml/glGetFramebufferAttachmentParameter.xml an. sowas wie
Code:
glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, &someInt)
sollte für den default framebuffer funktionieren. denk daran, dass openGL treiber bugs haben und manche bei sowas schlicht falsche werte zurückgeben.
 
Zurück
Oben