OVR: Multisampling Anitaliasing (MSAA) with real mirror view.
authorAndreas Eversberg <jolly@eversberg.eu>
Sun, 15 Apr 2018 15:13:30 +0000 (17:13 +0200)
committerAndreas Eversberg <jolly@eversberg.eu>
Sun, 22 Apr 2018 10:04:04 +0000 (12:04 +0200)
src/libovr/ovr.c
src/libovr/ovr.h
src/libsdl/sdl.c
src/mercenary/main.c

index 0bc8eb9..80c5a85 100755 (executable)
@@ -95,9 +95,13 @@ static ovrHmdDesc hmdDesc;
 static ovrSizei TextureSize[2];
 static ovrTextureSwapChain textureSwapChain[2] = { NULL, NULL };
 static GLuint fboId[2] = { 0, 0 };
+static GLuint mirrorFBO = 0;
+static int mirror_width;
+static int mirror_height;
 static ovrEyeRenderDesc eyeRenderDesc[2];
 static ovrPosef hmdToEyeViewPose[2];
 static ovrLayerEyeFov layer;
+static int multisampling;
 static long long frameIndex = 0;
 static double observer_x = 0.0;
 static double observer_x_normalize = 0.0;
@@ -106,12 +110,13 @@ static double observer_y_normalize = 0.0;
 static double observer_z = 0.0;
 static double observer_z_normalize = 0.0;
 
-int init_ovr(void)
+int init_ovr(int _multisampling)
 {
-       int sample_count = 1; // FIXME: make MSAA
        ovrResult result;
        int eye;
 
+       multisampling = _multisampling;
+
        glewExperimental = GL_TRUE;
        if (glewInit() != GLEW_OK) {
                print_error("Failed to init GLEW\n");
@@ -144,12 +149,13 @@ int init_ovr(void)
        layer.Header.Type      = ovrLayerType_EyeFov;
        layer.Header.Flags     = 0;
 
+       /* do we need this??? seems to work without */
+       if (multisampling > 1)
+               glEnable(GL_MULTISAMPLE);
+
        /* create render buffers */
        for (eye = 0; eye < 2; eye++) {
                TextureSize[eye] = ovr_GetFovTextureSize(session, (eye == 0) ? ovrEye_Left : ovrEye_Right, hmdDesc.DefaultEyeFov[eye], 1.0);
-#warning hacking resolution
-//TextureSize[eye].w *= 2;
-//TextureSize[eye].h *= 2;
                ovrTextureSwapChainDesc desc;
                int length, i;
                GLuint chainTexId;
@@ -161,7 +167,7 @@ int init_ovr(void)
                desc.Width = TextureSize[eye].w;
                desc.Height = TextureSize[eye].h;
                desc.MipLevels = 1;
-               desc.SampleCount = sample_count;
+               desc.SampleCount = (multisampling > 1) ? multisampling : 1;
                desc.StaticImage = ovrFalse;
 
                result = ovr_CreateTextureSwapChainGL(session, &desc, &textureSwapChain[eye]);
@@ -173,7 +179,7 @@ int init_ovr(void)
                ovr_GetTextureSwapChainLength(session, textureSwapChain[eye], &length);
                for (i = 0; i < length; i++) {
                        ovr_GetTextureSwapChainBufferGL(session, textureSwapChain[eye], i, &chainTexId);
-                       glBindTexture(GL_TEXTURE_2D, chainTexId);
+                       glBindTexture((multisampling > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D, chainTexId);
                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@@ -193,6 +199,33 @@ int init_ovr(void)
                layer.Viewport[eye].Size.h = TextureSize[eye].h;
        }
 
+       ovrMirrorTexture mirrorTexture = NULL;
+       ovrMirrorTextureDesc desc;
+       memset(&desc, 0, sizeof(desc));
+       desc.Width = mirror_width = TextureSize[0].w;
+       desc.Height = mirror_height = TextureSize[0].h / 2;
+       desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
+       desc.MirrorOptions =
+               ovrMirrorOption_PostDistortion |
+               ovrMirrorOption_IncludeGuardian |
+               ovrMirrorOption_IncludeNotifications |
+               ovrMirrorOption_IncludeSystemGui;
+
+       /* Create mirror texture and an FBO used to copy mirror texture to back buffer */
+       result = ovr_CreateMirrorTextureWithOptionsGL(session, &desc, &mirrorTexture);
+       if (!OVR_SUCCESS(result)) {
+               print_error("ovr_CreateMirrorTextureWithOptionsGL() failed!\n");
+               goto error;
+       }
+
+       /* Configure the mirror read buffer */
+       GLuint texId;
+       ovr_GetMirrorTextureBufferGL(session, mirrorTexture, &texId);
+
+       glGenFramebuffers(1, &mirrorFBO);
+       glBindFramebuffer(GL_READ_FRAMEBUFFER, mirrorFBO);
+       glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texId, 0);
+       glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
 
        return 0;
 
@@ -229,7 +262,7 @@ void begin_render_ovr_eye(int eye)
        ovr_GetTextureSwapChainCurrentIndex(session, textureSwapChain[eye], &curIndex);
        ovr_GetTextureSwapChainBufferGL(session, textureSwapChain[eye], curIndex, &chainTexId);
        glBindFramebuffer(GL_FRAMEBUFFER, fboId[eye]);
-       glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, chainTexId, 0);
+       glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, (multisampling > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D, chainTexId, 0);
 
        glViewport(0, 0, TextureSize[eye].w, TextureSize[eye].h);
        glMatrixMode(GL_PROJECTION);
@@ -271,8 +304,8 @@ void end_render_ovr_eye(int eye)
 {
        // unset render surface
        glBindFramebuffer(GL_FRAMEBUFFER, fboId[eye]);
-       glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
-       glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
+       glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, (multisampling > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D, 0, 0);
+       glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, (multisampling > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D, 0, 0);
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
 
        // Commit the changes to the texture swap chain
@@ -294,21 +327,18 @@ void render_mirror_ovr(int view_width, int view_height)
 {
        int view_x = 0, view_y = 0;
        int new_width, new_height;
-       int eye = 0; /* left eye */
-       int curIndex;
-       GLuint chainTexId;
 
        /* avoid division by zero, if one dimension is too small */
        if (view_width < 1 || view_height < 1)
                return;
 
        /* calculate a viewport that has apect of TextureSize */
-       if (view_height * TextureSize[eye].w > view_width * TextureSize[eye].h) {
-               new_height = view_width * TextureSize[eye].h / TextureSize[eye].w;
+       if (view_height * mirror_width > view_width * mirror_height) {
+               new_height = view_width * mirror_height / mirror_width;
                view_y = view_y + view_height / 2 - new_height / 2;
                view_height = new_height;
-       } else if (view_height * TextureSize[eye].w < view_width * TextureSize[eye].h) {
-               new_width = view_height * TextureSize[eye].w / TextureSize[eye].h;
+       } else if (view_height * mirror_width < view_width * mirror_height) {
+               new_width = view_height * mirror_width / mirror_height;
                view_x = view_x + view_width / 2 - new_width / 2;
                view_width = new_width;
        }
@@ -317,36 +347,18 @@ void render_mirror_ovr(int view_width, int view_height)
        if (view_width < 1 || view_height < 1)
                return;
 
-       /* clear screen */
+       glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
        glClearColor(0.0, 0.0, 0.0, 1.0);
        glClear(GL_COLOR_BUFFER_BIT);
 
-       /* orthogonal viewport */
-       glViewport((GLsizei)view_x, (GLsizei)view_y, (GLsizei)view_width, (GLsizei)view_height);
-       glMatrixMode(GL_PROJECTION);
-       glLoadIdentity();
-       glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
-       glMatrixMode(GL_MODELVIEW);
-
-       /* get texture from OVR */
-       ovr_GetTextureSwapChainCurrentIndex(session, textureSwapChain[eye], &curIndex);
-       ovr_GetTextureSwapChainBufferGL(session, textureSwapChain[eye], curIndex, &chainTexId);
-
-       /* render mirror from texture */
-       glEnable(GL_TEXTURE_2D);
-       glBindTexture(GL_TEXTURE_2D, chainTexId);
-       glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);  /* no modulation with color */
-       glBegin(GL_QUADS);
-       glTexCoord2f(0, 1);
-       glVertex3f(-1.0, -1.0, 0.0);
-       glTexCoord2f(1, 1);
-       glVertex3f(1.0, -1.0, 0.0);
-       glTexCoord2f(1, 0);
-       glVertex3f(1.0, 1.0, 0.0);
-       glTexCoord2f(0, 0);
-       glVertex3f(-1.0, 1.0, 0.0);
-       glEnd();
-       glDisable(GL_TEXTURE_2D);
+       /* Blit mirror texture to back buffer */
+       glBindFramebuffer(GL_READ_FRAMEBUFFER, mirrorFBO);
+       glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+       glBlitFramebuffer(0, mirror_height, mirror_width, 0,
+               view_x, view_y, view_x + view_width, view_y + view_height,
+               GL_COLOR_BUFFER_BIT, GL_NEAREST);
+       glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
 }
 
 void normalize_observer_ovr(void)
@@ -371,6 +383,10 @@ void exit_ovr(void)
                        fboId[eye] = 0;
                }
        }
+       if (mirrorFBO) {
+               glDeleteFramebuffers(1, &mirrorFBO);
+               mirrorFBO = 0;
+       }
 
        if (session) {
                ovr_Destroy(session);
index 4b8b8ee..1400127 100755 (executable)
@@ -1,5 +1,5 @@
 
-int init_ovr(void);
+int init_ovr(int multisampling);
 void exit_ovr(void);
 void begin_render_ovr(void);
 void begin_render_ovr_eye(int eye);
index d0eeb78..3e5d7bd 100644 (file)
@@ -63,7 +63,7 @@ int init_sdl(const char *progname, int width, int height, int sound_samplerate,
        }
        sdl_initialized = 1;
 
-       if (multisampling) {
+       if (multisampling > 1) {
                SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
                SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
                SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
@@ -132,7 +132,7 @@ int init_sdl(const char *progname, int width, int height, int sound_samplerate,
        /* just in case */
        glDisable(GL_DEPTH_TEST);
        glDisable(GL_CULL_FACE);
-       if (multisampling)
+       if (multisampling > 1)
                glEnable(GL_MULTISAMPLE);
 
        if (rift) {
index 526dd06..2b4a8a0 100644 (file)
@@ -56,7 +56,7 @@ static int config_video_filter = 1;
 static int config_audio_filter = 1;
 static int config_render = 1; /* opengl render */
 static int config_skip_intro = 0;
-static int config_multisampling = 16;
+static int config_multisampling = 8;
 static double config_fov = FOV_NOVAGEN;
 static double config_monitor_distance = 31.5; /* inch */
 static double config_benson_size = 1.0;
@@ -94,7 +94,7 @@ static uint8_t *info_osd = NULL;
 static int help_view = 1;
 static int32_t osd_timer = 0;
 #ifdef HAVE_OVR
-#define SCREEN_WIDTH   672
+#define SCREEN_WIDTH   1344
 #define SCREEN_HEIGHT  800
 #else
 #define SCREEN_WIDTH   (320*3)
@@ -1009,19 +1009,21 @@ int main(int argc, char *argv[])
 #ifdef HAVE_OVR
        int vbl_sync = 0;
        int rift = 1;
+       int multisampling = 0;
        window_width = SCREEN_WIDTH;
        window_height = SCREEN_HEIGHT;
 #else
        int vbl_sync = 1;
        int rift = 0;
+       int multisampling = config_multisampling;
        window_width = (config_debug_opengl) ? SCREEN_WIDTH / 3 * 2 : SCREEN_WIDTH;
        window_height = (config_debug_opengl) ? SCREEN_HEIGHT / 3 * 4 : SCREEN_HEIGHT;
 #endif
-       rc = init_sdl(argv[0], window_width, window_height, SOUND_SAMPLERATE, sdl_sound_chunk, keyboard_sdl, audio_sdl, resize_window, config_multisampling, vbl_sync, rift);
+       rc = init_sdl(argv[0], window_width, window_height, SOUND_SAMPLERATE, sdl_sound_chunk, keyboard_sdl, audio_sdl, resize_window, multisampling, vbl_sync, rift);
        if (rc < 0)
                goto done;
 #ifdef HAVE_OVR
-       rc = init_ovr();
+       rc = init_ovr(config_multisampling);
        if (rc < 0)
                goto done;
 #endif