void StereoscopicRenderingApp::update() { float d, f; Area area; switch( mFocusMethod ) { case SET_CONVERGENCE: // auto-focus by calculating distance to center of interest d = (mCamera.getCenterOfInterestPoint() - mCamera.getEyePoint()).length(); f = math<float>::min( 5.0f, d * 0.5f ); // The setConvergence() method will not change the eye separation distance, // which may cause the parallax effect to become uncomfortably big. mCamera.setConvergence( f ); mCamera.setEyeSeparation( 0.05f ); break; case SET_FOCUS: // auto-focus by calculating distance to center of interest d = (mCamera.getCenterOfInterestPoint() - mCamera.getEyePoint()).length(); f = math<float>::min( 5.0f, d * 0.5f ); // The setConvergence( value, true ) method will automatically calculate a fitting value for the eye separation distance. // There is still no guarantee that the parallax effect stays within comfortable levels, // because there may be objects very near to the camera compared to the point we are looking at. mCamera.setConvergence( f, true ); break; case AUTO_FOCUS: // Here, we use the gl::StereoAutoFocuser class to determine the best focal length, // based on the contents of the current depth buffer. This is by far the best method of // the three, because it guarantees the parallax effect will never be out of bounds. // Depending on the rendering method, we can sample different area's of the screen // to optimally detect details. This is not required, however. // Use the UP and DOWN keys to adjust the intensity of the parallax effect. switch( mRenderMethod ) { case MONO: break; case SIDE_BY_SIDE: // sample half the left eye, half the right eye area = gl::getViewport(); area.expand( -area.getWidth()/4, 0 ); mAF.autoFocus( &mCamera, area ); break; case OVER_UNDER: // sample half the left eye, half the right eye area = gl::getViewport(); area.expand( 0, -area.getHeight()/4 ); mAF.autoFocus( &mCamera, area ); break; case ANAGLYPH_RED_CYAN: // sample the depth buffer of one of the FBO's mAF.autoFocus( &mCamera, mFbo ); break; } break; } }
void StereoscopicRenderingApp::draw() { // clear color and depth buffers gl::clear( mColorBackground ); // stereoscopic rendering switch( mRenderMethod ) { case MONO: // render mono camera mCamera.disableStereo(); render(); break; case ANAGLYPH_RED_CYAN: renderAnaglyph( getWindowSize(), Color(1, 0, 0), Color(0, 1, 1) ); break; case SIDE_BY_SIDE: renderSideBySide( getWindowSize() ); break; case OVER_UNDER: renderOverUnder( getWindowSize() ); break; case INTERLACED_HORIZONTAL: renderInterlacedHorizontal( getWindowSize() ); break; } // draw auto focus visualizer if( mDrawAutoFocus ) mAF.draw(); }
void StereoscopicRenderingApp::renderUI() { float w = (float) getWindowWidth() * 0.5f; float h = (float) getWindowHeight(); std::string renderMode, focusMode; switch(mRenderMethod) { case MONO: renderMode = "Mono"; break; case SIDE_BY_SIDE: renderMode = "Side By Side"; break; case OVER_UNDER: renderMode = "Over Under"; break; case ANAGLYPH_RED_CYAN: renderMode = "Anaglyph Red Cyan"; break; case INTERLACED_HORIZONTAL: renderMode = "Interlaced Horizontal"; break; } switch(mFocusMethod) { case SET_CONVERGENCE: focusMode = "setConvergence(d, false)"; break; case SET_FOCUS: focusMode = "setConvergence(d, true)"; break; case AUTO_FOCUS: focusMode = "autoFocus(cam)"; break; } std::string labels( "Render mode (F1-F5):\nFocus mode (1-3):\nFocal Length:\nEye Distance:\nAuto Focus Depth (Up/Down):\nAuto Focus Speed (Left/Right):" ); boost::format values = boost::format( "%s\n%s\n%.2f\n%.2f\n%.2f\n%.2f" ) % renderMode % focusMode % mCamera.getConvergence() % mCamera.getEyeSeparation() % mAF.getDepth() % mAF.getSpeed(); #if(defined CINDER_MSW) gl::enableAlphaBlending(); gl::drawString( labels, Vec2f( w - 350.0f, h - 150.0f ), Color::black(), mFont ); gl::drawStringRight( values.str(), Vec2f( w + 350.0f, h - 150.0f ), Color::black(), mFont ); gl::disableAlphaBlending(); #else // \n is not supported on the mac, so we draw separate strings std::vector< std::string > left, right; left = ci::split( labels, "\n", false ); right = ci::split( values.str(), "\n", false ); gl::enableAlphaBlending(); for(size_t i=0;i<4;++i) { gl::drawString( left[i], Vec2f( w - 350.0f, h - 150.0f + i * mFont.getSize() * 0.9f ), Color::black(), mFont ); gl::drawStringRight( right[i], Vec2f( w + 350.0f, h - 150.0f + i * mFont.getSize() * 0.9f ), Color::black(), mFont ); } gl::disableAlphaBlending(); #endif }
void StereoscopicRenderingApp::keyDown( KeyEvent event ) { switch( event.getCode() ) { case KeyEvent::KEY_ESCAPE: quit(); break; case KeyEvent::KEY_f: // toggle full screen setFullScreen( ! isFullScreen() ); break; case KeyEvent::KEY_v: // toggle vertical sync gl::enableVerticalSync( !gl::isVerticalSyncEnabled() ); break; case KeyEvent::KEY_d: // toggle visualizer mDrawAutoFocus = !mDrawAutoFocus; break; case KeyEvent::KEY_u: // toggle interface mDrawUI = !mDrawUI; break; case KeyEvent::KEY_UP: // increase the parallax effect (towards negative parallax) if(mFocusMethod == AUTO_FOCUS) mAF.setDepth( mAF.getDepth() + 0.01f ); break; case KeyEvent::KEY_DOWN: // decrease the parallax effect (towards positive parallax) if(mFocusMethod == AUTO_FOCUS) mAF.setDepth( mAF.getDepth() - 0.01f ); break; case KeyEvent::KEY_SPACE: // reset the parallax effect to 'no parallax for the nearest object' mAF.setDepth( 1.0f ); break; case KeyEvent::KEY_LEFT: // reduce the auto focus speed mAF.setSpeed( mAF.getSpeed() - 0.01f ); break; case KeyEvent::KEY_RIGHT: // increase the auto focus speed mAF.setSpeed( mAF.getSpeed() + 0.01f ); break; case KeyEvent::KEY_1: mFocusMethod = SET_CONVERGENCE; break; case KeyEvent::KEY_2: mFocusMethod = SET_FOCUS; break; case KeyEvent::KEY_3: mFocusMethod = AUTO_FOCUS; break; case KeyEvent::KEY_F1: mRenderMethod = MONO; createFbo(); break; case KeyEvent::KEY_F2: mRenderMethod = ANAGLYPH_RED_CYAN; createFbo(); break; case KeyEvent::KEY_F3: mRenderMethod = SIDE_BY_SIDE; createFbo(); break; case KeyEvent::KEY_F4: mRenderMethod = OVER_UNDER; createFbo(); break; case KeyEvent::KEY_F5: mRenderMethod = INTERLACED_HORIZONTAL; createFbo(); break; } }
void StereoscopicRenderingApp::draw() { // find dimensions of each viewport int w = getWindowWidth(); int h = getWindowHeight(); // clear color and depth buffers gl::clear( mBackgroundColor ); // stereoscopic rendering switch( mRenderMethod ) { case MONO: // render mono camera mCamera.disableStereo(); render(); break; case SIDE_BY_SIDE: // store current viewport glPushAttrib( GL_VIEWPORT_BIT ); // draw to left half of window only gl::setViewport( Area(0, 0, w / 2, h) ); // render left camera mCamera.enableStereoLeft(); render(); // draw to right half of window only gl::setViewport( Area(w / 2, 0, w, h) ); // render right camera mCamera.enableStereoRight(); render(); // restore viewport glPopAttrib(); break; case OVER_UNDER: // store current viewport glPushAttrib( GL_VIEWPORT_BIT ); // draw to top half of window only gl::setViewport( Area(0, 0, w, h / 2) ); // render left camera mCamera.enableStereoLeft(); render(); // draw to bottom half of window only gl::setViewport( Area(0, h / 2, w, h) ); // render right camera mCamera.enableStereoRight(); render(); // restore viewport glPopAttrib(); break; case ANAGLYPH_RED_CYAN: // store current viewport glPushAttrib( GL_VIEWPORT_BIT ); // bind the left FBO and adjust the viewport to its bounds mAnaglyphLeft.bindFramebuffer(); gl::setViewport( mAnaglyphLeft.getBounds() ); // because glClear() does not respect the color mask, // clear the color (and depth) buffers using a red filtered background color gl::clear( mBackgroundColor * Color( 1, 0, 0 ) ); // set up color mask to only draw red and render left camera glColorMask( true, false, false, true ); mCamera.enableStereoLeft(); render(); glColorMask( true, true, true, true ); mAnaglyphLeft.unbindFramebuffer(); // bind the right FBO and adjust the viewport to its bounds mAnaglyphRight.bindFramebuffer(); gl::setViewport( mAnaglyphRight.getBounds() ); // because glClear() does not respect the color mask, // clear the color (and depth) buffers using a cyan filtered background color gl::clear( mBackgroundColor * Color( 0, 1, 1 ) ); // set up color mask to only draw cyan and render right camera glColorMask( false, true, true, true ); mCamera.enableStereoRight(); render(); glColorMask( true, true, true, true ); mAnaglyphRight.unbindFramebuffer(); // restore viewport glPopAttrib(); // draw the FBO's on top of each other using a special additive blending operation gl::color( Color::white() ); gl::draw( mAnaglyphLeft.getTexture(), Rectf( 0, (float) h, (float) w, 0 ) ); glEnable( GL_BLEND ); glBlendFunc( GL_ONE, GL_ONE ); gl::draw( mAnaglyphRight.getTexture(), Rectf( 0, (float) h, (float) w, 0) ); glDisable( GL_BLEND ); break; } // draw auto focus visualizer if( mDrawAutoFocus ) mAF.draw(); }