do gamma correction on post if we don't have an sRGB framebuffer
authorJohn Tsiombikas <nuclear@mutantstargoat.com>
Tue, 15 Nov 2016 05:13:25 +0000 (07:13 +0200)
committerJohn Tsiombikas <nuclear@mutantstargoat.com>
Tue, 15 Nov 2016 05:13:25 +0000 (07:13 +0200)
sdr/post_gamma.p.glsl [new file with mode: 0644]
sdr/post_gamma.v.glsl [new file with mode: 0644]
src/app.cc
src/app.h
src/main.cc
src/post.cc [new file with mode: 0644]
src/post.h [new file with mode: 0644]

diff --git a/sdr/post_gamma.p.glsl b/sdr/post_gamma.p.glsl
new file mode 100644 (file)
index 0000000..6b323f8
--- /dev/null
@@ -0,0 +1,10 @@
+uniform sampler2D tex;
+
+void main()
+{
+       const vec3 invgamma3 = vec3(1.0 / 2.2);
+       vec3 texel = texture2D(tex, gl_TexCoord[0].st).xyz;
+
+       gl_FragColor.rgb = pow(texel, invgamma3);
+       gl_FragColor.a = 1.0;
+}
diff --git a/sdr/post_gamma.v.glsl b/sdr/post_gamma.v.glsl
new file mode 100644 (file)
index 0000000..a8fb0cf
--- /dev/null
@@ -0,0 +1,5 @@
+void main()
+{
+       gl_Position = gl_Vertex;
+       gl_TexCoord[0] = gl_MultiTexCoord0;
+}
index d3b5657..096bf4e 100644 (file)
@@ -12,6 +12,7 @@
 #include "datamap.h"
 #include "ui.h"
 #include "opt.h"
+#include "post.h"
 
 #define NEAR_CLIP      5.0
 #define FAR_CLIP       10000.0
@@ -21,6 +22,7 @@ static void draw_scene();
 long time_msec;
 int win_width, win_height;
 float win_aspect;
+bool fb_srgb;
 bool opt_gear_wireframe;
 
 static float cam_dist = 0.0;
@@ -41,7 +43,7 @@ static bool keystate[256];
 static Mat4 view_matrix, mouse_view_matrix, proj_matrix;
 static TextureSet texman;
 static Scene *scn;
-static unsigned int sdr;
+static unsigned int sdr, sdr_post_gamma;
 
 static long prev_msec;
 
@@ -69,7 +71,12 @@ bool app_init(int argc, char **argv)
                goatvr_recenter();
        }
 
+       int srgb_capable;
+       glGetIntegerv(GL_FRAMEBUFFER_SRGB_CAPABLE_EXT, &srgb_capable);
+       printf("Framebuffer %s sRGB-capable\n", srgb_capable ? "is" : "is not");
+       fb_srgb = srgb_capable != 0;
        glEnable(GL_FRAMEBUFFER_SRGB);
+
        glEnable(GL_MULTISAMPLE);
        glEnable(GL_DEPTH_TEST);
        glEnable(GL_CULL_FACE);
@@ -105,6 +112,10 @@ bool app_init(int argc, char **argv)
        set_uniform_int(sdr, "texmap", 0);
        set_uniform_int(sdr, "lightmap", 1);
 
+       if(!fb_srgb) {
+               sdr_post_gamma = create_program_load("sdr/post_gamma.v.glsl", "sdr/post_gamma.p.glsl");
+       }
+
        glUseProgram(0);
 
        if(opt.vr || opt.fullscreen) {
@@ -266,6 +277,10 @@ void app_display()
 
                draw_scene();
 
+               if(!fb_srgb && sdr_post_gamma) {
+                       slow_post(sdr_post_gamma);
+                       glUseProgram(0);
+               }
                app_swap_buffers();
        }
        assert(glGetError() == GL_NO_ERROR);
@@ -344,6 +359,13 @@ void app_keyboard(int key, bool pressed)
                        }
                        break;
 
+               case 'p':
+                       if(mod & MOD_CTRL) {
+                               fb_srgb = !fb_srgb;
+                               show_message("gamma correction for non-sRGB framebuffers: %s\n", fb_srgb ? "off" : "on");
+                       }
+                       break;
+
                case '=':
                        walk_speed *= 1.25;
                        show_message("walk speed: %g", walk_speed);
@@ -370,8 +392,9 @@ void app_mouse_button(int bn, bool pressed, int x, int y)
 
 static inline void mouse_look(int dx, int dy)
 {
-       cam_theta += dx * 0.5;
-       cam_phi += dy * 0.5;
+       float scrsz = (float)win_height;
+       cam_theta += dx * 512.0 / scrsz;
+       cam_phi += dy * 512.0 / scrsz;
 
        if(cam_phi < -90) cam_phi = -90;
        if(cam_phi > 90) cam_phi = 90;
index 02db8db..5e65394 100644 (file)
--- a/src/app.h
+++ b/src/app.h
@@ -5,6 +5,7 @@ extern long time_msec;
 extern int win_width, win_height;
 extern float win_aspect;
 extern bool opt_gear_wireframe;
+extern bool fb_srgb;
 
 enum {
        MOD_SHIFT       = 1,
index 01c9d12..fb8a2e2 100644 (file)
@@ -41,7 +41,11 @@ int main(int argc, char **argv)
                        SDL_Quit();
                        return 1;
                }
+               fprintf(stderr, "failed to get an sRGB framebuffer.\n");
        }
+       int val;
+       SDL_GL_GetAttribute(SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, &val);
+       printf("SDL says we %s an sRGB framebuffer\n", val ? "got" : "didn't get");
 
        if(!(ctx = SDL_GL_CreateContext(win))) {
                fprintf(stderr, "failed to create OpenGL context\n");
@@ -113,8 +117,11 @@ bool app_is_fullscreen()
 
 void app_grab_mouse(bool grab)
 {
-       SDL_SetWindowGrab(win, grab ? SDL_TRUE : SDL_FALSE);
-       SDL_ShowCursor(grab ? 1 : 0);
+       if(grab) {
+               SDL_WarpMouseInWindow(win, win_width / 2, win_height / 2);
+       }
+       //SDL_SetWindowGrab(win, grab ? SDL_TRUE : SDL_FALSE);
+       //SDL_ShowCursor(grab ? 1 : 0);
        SDL_SetRelativeMouseMode(grab ? SDL_TRUE : SDL_FALSE);
        mouse_grabbed = grab;
 }
@@ -164,7 +171,8 @@ static void process_event(SDL_Event *ev)
 
        case SDL_MOUSEMOTION:
                if(mouse_grabbed) {
-                       app_mouse_delta(ev->motion.xrel, ev->motion.yrel);
+                       // XXX xrel/yrel seems faster by default
+                       app_mouse_delta(ev->motion.xrel * 0.5, ev->motion.yrel * 0.5);
                } else {
                        app_mouse_motion(ev->motion.x * scale_factor, ev->motion.y * scale_factor);
                }
diff --git a/src/post.cc b/src/post.cc
new file mode 100644 (file)
index 0000000..b675f5b
--- /dev/null
@@ -0,0 +1,67 @@
+#include "opengl.h"
+#include "app.h"
+
+static void update_fbtex();
+
+static unsigned int fb_tex;
+static int fb_tex_width, fb_tex_height;
+
+void slow_post(unsigned int sdr)
+{
+       update_fbtex();
+
+       glBindTexture(GL_TEXTURE_2D, fb_tex);
+       glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, win_width, win_height);
+
+       glPushAttrib(GL_ENABLE_BIT);
+       glDisable(GL_DEPTH_TEST);
+       glDisable(GL_LIGHTING);
+
+       glUseProgram(sdr);
+
+       float umax = (float)win_width / (float)fb_tex_width;
+       float vmax = (float)win_height / (float)fb_tex_height;
+
+       glBegin(GL_QUADS);
+       glTexCoord2f(0, 0);
+       glVertex2f(-1, -1);
+       glTexCoord2f(umax, 0);
+       glVertex2f(1, -1);
+       glTexCoord2f(umax, vmax);
+       glVertex2f(1, 1);
+       glTexCoord2f(0, vmax);
+       glVertex2f(-1, 1);
+       glEnd();
+
+       glPopAttrib();
+}
+
+static int next_pow2(int x)
+{
+       x--;
+       x = (x >> 1) | x;
+       x = (x >> 2) | x;
+       x = (x >> 4) | x;
+       x = (x >> 8) | x;
+       x = (x >> 16) | x;
+       return x + 1;
+}
+
+static void update_fbtex()
+{
+       if(win_width <= fb_tex_width && win_height <= fb_tex_height) {
+               return;         // nothing to do
+       }
+       if(!fb_tex) {
+               glGenTextures(1, &fb_tex);
+               glBindTexture(GL_TEXTURE_2D, fb_tex);
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+       } else {
+               glBindTexture(GL_TEXTURE_2D, fb_tex);
+       }
+
+       fb_tex_width = next_pow2(win_width);
+       fb_tex_height = next_pow2(win_height);
+       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, fb_tex_width, fb_tex_height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
+}
diff --git a/src/post.h b/src/post.h
new file mode 100644 (file)
index 0000000..737cb02
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef POST_H_
+#define POST_H_
+
+void slow_post(unsigned int sdr);
+
+#endif // POST_H_