From 03beb162b0463bdc492c67b300c3fe826ce8a332 Mon Sep 17 00:00:00 2001 From: skyjake Date: Tue, 29 Oct 2013 18:49:14 +0200 Subject: [PATCH] Cleanup|ClientWindow: Moved wip Oculus Rift drawing to a private method Also, fixed some issues with the use of GLState: - This test code is using immediate GL drawing, which means every change to GLState has to be manually applied before drawing. Managed drawing with libgui's Drawable will do this for us. - Applied a purple hue to identify that the graphics are coming from the offscreen target. - Clearing the targets appropriately before drawing. - For the final draw, disable blending and depth test. Todo: Next problem is to find out why the game-side menu drawer messes up GL state in such a way that the screen is drawn as purple. --- doomsday/client/src/ui/clientwindow.cpp | 148 +++++++++++++----------- 1 file changed, 82 insertions(+), 66 deletions(-) diff --git a/doomsday/client/src/ui/clientwindow.cpp b/doomsday/client/src/ui/clientwindow.cpp index caf239acd3..f449febcac 100644 --- a/doomsday/client/src/ui/clientwindow.cpp +++ b/doomsday/client/src/ui/clientwindow.cpp @@ -442,6 +442,85 @@ DENG2_OBSERVES(App, GameChange) sidebar->deleteLater(); sidebar = 0; } + + /* + * Special Viewing Modes: + */ + + QScopedPointer unwarpedTarget; + GLTexture unwarpedTexture; + + /** + * Draws the entire UI in two halves, one for the left eye and one for the + * right. The Oculus Rift optical distortion effect is applied using a + * shader. + * + * @todo unwarpedTarget and unwarpedTexture should be cleared/deleted when + * Oculus Rift mode is disabled (or whenever they are not needed). + */ + void vrDrawOculusRift() + { + // Allocate offscreen buffers + Size size = self.canvas().size(); + if(unwarpedTexture.size() != size) + { + unwarpedTexture.setUndefinedImage(size, Image::RGBA_8888); + unwarpedTexture.setWrap(gl::ClampToEdge, gl::ClampToEdge); + unwarpedTarget.reset(new GLTarget(GLTarget::ColorDepthStencil, unwarpedTexture)); + } + + // Set render target to offscreen temporarily. + GLState::push().setTarget(*unwarpedTarget).apply(); // Debug on right side + unwarpedTarget->clear(GLTarget::ColorDepth); + + // Left eye view on left side of screen. + VR::eyeShift = VR::getEyeShift(-1); + GLState::setActiveRect(Rectangleui(0, 0, size.x/2, size.y), true); + self.root().draw(); + + // Right eye view on right side of screen. + VR::eyeShift = VR::getEyeShift(+1); + GLState::setActiveRect(Rectangleui(size.x/2, 0, size.x/2, size.y), true); + self.root().draw(); + + GLState::pop().apply(); + + // Return the drawing to the full target. + GLState::setActiveRect(Rectangleui(), true); + + self.canvas().renderTarget().clear(GLTarget::Color); + GLState::push() + .setBlend(false) + .setDepthTest(false) + .apply(); + + // Copy contents of offscreen buffer to normal screen + unwarpedTexture.glBindToUnit(0); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + // if (useShader) + // glUseProgram(shader); + glColor3f(1, .5f, 1); + glBegin(GL_TRIANGLE_STRIP); + glTexCoord2d(0, 1); glVertex3f(-1, 1, 0.5); + glTexCoord2d(1, 1); glVertex3f( 1, 1, 0.5); + glTexCoord2d(0, 0); glVertex3f(-1, -1, 0.5); + glTexCoord2d(1, 0); glVertex3f( 1, -1, 0.5); + glEnd(); + // if (useShader) + // glUseProgram(0); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + glBindTexture(GL_TEXTURE_2D, 0); + + GLState::pop().apply(); + } }; ClientWindow::ClientWindow(String const &id) @@ -610,74 +689,11 @@ void ClientWindow::canvasGLDraw(Canvas &canvas) GLState::setActiveRect(Rectangleui(width()/2, 0, width()/2, height()), true); root().draw(); break; - case VR::MODE_OCULUS_RIFT: /// @todo head tracking, image warping, shrunken hud, field of view - { - // My failed attempt to render to offscreen buffer, then blit back to screen CMB Oct 29, 2013 -// #define TRY_OCULUS_OFFSCREEN 1 -#ifdef TRY_OCULUS_OFFSCREEN - // Allocate offscreen buffers - static QScopedPointer unwarpedTarget; - static GLTexture unwarpedTexture; - Size screenSize(width(), height()); - if (unwarpedTexture.size() != screenSize) - { - unwarpedTexture.setUndefinedImage(screenSize, Image::RGBA_8888); - unwarpedTexture.setWrap(gl::ClampToEdge, gl::ClampToEdge); - unwarpedTarget.reset(new GLTarget(GLTarget::ColorDepthStencil, unwarpedTexture)); - } - - // Set render target to offscreen - GLState::push().setTarget(*unwarpedTarget); // Debug on right side - unwarpedTarget->glBind(); -#endif - - // Left eye view on left side of screen. - VR::eyeShift = VR::getEyeShift(-1); - GLState::setActiveRect(Rectangleui(0, 0, width()/2, height()), true); - root().draw(); - - // Right eye view on right side of screen. - VR::eyeShift = VR::getEyeShift(+1); - GLState::setActiveRect(Rectangleui(width()/2, 0, width()/2, height()), true); - root().draw(); - -#ifdef TRY_OCULUS_OFFSCREEN - // Restore render target to regular on screen - unwarpedTarget->glRelease(); - GLState::pop(); - - GLState::push().setViewport(Rectangleui(0, 0, width(), height())); - GLState::setActiveRect(Rectangleui(0, 0, width(), height()), true); - - // Copy contents of offscreen buffer to normal screen - unwarpedTexture.glBindToUnit(0); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - // if (useShader) - // glUseProgram(shader); - glBegin(GL_TRIANGLE_STRIP); - glTexCoord2d(0, 1); glVertex3f(-1, 1, 0.5); - glTexCoord2d(1, 1); glVertex3f( 1, 1, 0.5); - glTexCoord2d(0, 0); glVertex3f(-1, -1, 0.5); - glTexCoord2d(1, 0); glVertex3f( 1, -1, 0.5); - glEnd(); - // if (useShader) - // glUseProgram(0); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - glBindTexture(GL_TEXTURE_2D, 0); - - GLState::pop(); -#endif + case VR::MODE_OCULUS_RIFT: /// @todo head tracking, image warping, shrunken hud, field of view + d->vrDrawOculusRift(); break; - } + // Overlaid type stereo 3D modes below: case VR::MODE_GREEN_MAGENTA: // Left eye view