Skip to content

Commit

Permalink
Cleanup|ClientWindow: Moved wip Oculus Rift drawing to a private method
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
skyjake committed Oct 29, 2013
1 parent 0157e61 commit 03beb16
Showing 1 changed file with 82 additions and 66 deletions.
148 changes: 82 additions & 66 deletions doomsday/client/src/ui/clientwindow.cpp
Expand Up @@ -442,6 +442,85 @@ DENG2_OBSERVES(App, GameChange)
sidebar->deleteLater();
sidebar = 0;
}

/*
* Special Viewing Modes:
*/

QScopedPointer<GLTarget> 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)
Expand Down Expand Up @@ -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<GLTarget> 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
Expand Down

0 comments on commit 03beb16

Please sign in to comment.