Ejemplo n.º 1
0
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();
}
Ejemplo n.º 2
0
void StereoscopicRenderingApp::resize()
{
	// make sure the camera's aspect ratio remains correct
	mCamera.setAspectRatio( getWindowAspectRatio() );
	mMayaCam.setCurrentCam( mCamera );

	// create/resize the Frame Buffer Object required for some of the render methods
	createFbo();
}
Ejemplo n.º 3
0
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;
	}
}
Ejemplo n.º 4
0
void StereoscopicRenderingApp::setup()
{
	// enable stereoscopic rendering
	mRenderMethod = SIDE_BY_SIDE;

	// enable auto-focussing
	mFocusMethod = AUTO_FOCUS;
	mDrawAutoFocus = false;

	// setup the camera
	mCamera.setEyePoint( Vec3f(0.2f, 1.3f, -11.5f) );
	mCamera.setCenterOfInterestPoint( Vec3f(0.5f, 1.5f, -0.1f) );
	mCamera.setFov( 60.0f );

	mMayaCam.setCurrentCam( mCamera );

	try {
		// load shader(s)
		mShaderPhong = gl::GlslProg( loadAsset("shaders/phong_vert.glsl"), loadAsset("shaders/phong_frag.glsl") );
		mShaderAnaglyph = gl::GlslProg( loadAsset("shaders/anaglyph_vert.glsl"), loadAsset("shaders/anaglyph_frag.glsl") );
		mShaderInterlaced = gl::GlslProg( loadAsset("shaders/interlaced_vert.glsl"), loadAsset("shaders/interlaced_frag.glsl") );

		// load model(s)
		TriMesh		mesh;

		mesh.read( loadAsset("models/trombone.msh") );
		mMeshTrombone = gl::VboMesh( mesh );
		
		mesh.read( loadAsset("models/note.msh") );
		mMeshNote = gl::VboMesh( mesh ); 
	}
	catch( const std::exception &e ) {
		// something went wrong, display error and quit
		console() << e.what() << std::endl;
		quit();
	}

	mColorBackground = Color( 0.8f, 0.8f, 0.8f );

	mFont = Font("Verdana", 24.0f);
	mDrawUI = true;
}
Ejemplo n.º 5
0
void StereoscopicRenderingApp::renderOverUnder( const Vec2i &size )
{
	// store current viewport
	glPushAttrib( GL_VIEWPORT_BIT );

	// draw to top half of window only
	gl::setViewport( Area(0, 0, size.x, size.y / 2) );

	// render left camera
	mCamera.enableStereoLeft();
	render();

	// draw to bottom half of window only
	gl::setViewport( Area(0, size.y / 2, size.x, size.y) );

	// render right camera
	mCamera.enableStereoRight();
	render();

	// restore viewport
	glPopAttrib();
}
Ejemplo n.º 6
0
void StereoscopicRenderingApp::resize( ResizeEvent event )
{
	// make sure the camera's aspect ratio remains correct
	mCamera.setAspectRatio( event.getAspectRatio() );	
	mMayaCam.setCurrentCam( mCamera );

	// create/resize the FBO's required for anaglyph rendering
	gl::Fbo::Format fmt;
	fmt.setMagFilter( GL_LINEAR );
	fmt.setSamples(8);

	mAnaglyphLeft = gl::Fbo( event.getWidth(), event.getHeight(), fmt );
	mAnaglyphRight = gl::Fbo( event.getWidth(), event.getHeight(), fmt );
}
Ejemplo n.º 7
0
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
}
Ejemplo n.º 8
0
void StarsApp::draw()
{		
	int w = getWindowWidth();
	int h = getWindowHeight();

	gl::clear( Color::black() ); 

	if(mIsStereoscopic) {
		glPushAttrib( GL_VIEWPORT_BIT );
		gl::pushMatrices();

		// render left eye
		mCamera.enableStereoLeft();

		gl::setViewport( Area(0, 0, w / 2, h) );
		gl::setMatrices( mCamera.getCamera() );
		render();
	
		// draw user interface
		mUserInterface.draw("Stereoscopic Projection");

		// render right eye
		mCamera.enableStereoRight();

		gl::setViewport( Area(w / 2, 0, w, h) );
		gl::setMatrices( mCamera.getCamera() );
		render();
	
		// draw user interface
		mUserInterface.draw("Stereoscopic Projection");

		gl::popMatrices();		
		glPopAttrib();
	}
	else if(mIsCylindrical) {
		// make sure we have a frame buffer to render to
		createFbo();

		// determine correct aspect ratio and vertical field of view for each of the 3 views
		w = mFbo.getWidth() / 3;
		h = mFbo.getHeight();

		const float aspect = float(w) / float(h);
		const float hFoV = 60.0f;
		const float vFoV = toDegrees( 2.0f * math<float>::atan( math<float>::tan( toRadians(hFoV) * 0.5f ) / aspect ) );

		// for values smaller than 1.0, this will cause each view to overlap the other ones
		const float overlap = 1.0f;	

		// bind the frame buffer object
		mFbo.bindFramebuffer();

		// store viewport, camera and matrices, so we can restore later
		glPushAttrib( GL_VIEWPORT_BIT );
		CameraStereo original = mCamera.getCamera();
		gl::pushMatrices();

		// setup camera	
		CameraStereo cam = mCamera.getCamera();
		cam.disableStereo();
		cam.setAspectRatio(aspect);
		cam.setFov( vFoV );

		Vec3f right, up;	
		cam.getBillboardVectors(&right, &up);
		Vec3f forward = up.cross(right);

		// render left side
		gl::setViewport( Area(0, 0, w, h) );

		cam.setViewDirection( Quatf(up, overlap * toRadians(hFoV)) * forward );
		cam.setWorldUp( up );
		gl::setMatrices( cam );
		render();
		
		// render front side
		gl::setViewport( Area(w, 0, w*2, h) );

		cam.setViewDirection( forward );
		cam.setWorldUp( up );
		gl::setMatrices( cam );
		render();	
	
		// draw user interface
		mUserInterface.draw( (boost::format("Cylindrical Projection (%d degrees)") % int( (1.0f + 2.0f * overlap) * hFoV ) ).str() );

		// render right side
		gl::setViewport( Area(w*2, 0, w*3, h) );

		cam.setViewDirection( Quatf(up, -overlap * toRadians(hFoV)) * forward );
		cam.setWorldUp( up );
		gl::setMatrices( cam );
		render();
		
		// unbind the frame buffer object
		mFbo.unbindFramebuffer();

		// restore states
		gl::popMatrices();		
		mCamera.setCurrentCam(original);
		glPopAttrib();

		// draw frame buffer and perform cylindrical projection using a fragment shader
		if(mShader) {
			float sides = 3;
			float radians = sides * toRadians( hFoV );
			float reciprocal = 0.5f / sides;

			mShader.bind();
			mShader.uniform("texture", 0);
			mShader.uniform("sides", sides);
			mShader.uniform("radians", radians );
			mShader.uniform("reciprocal", reciprocal );
		}

		Rectf centered = Rectf(mFbo.getBounds()).getCenteredFit( getWindowBounds(), false );
		gl::draw( mFbo.getTexture(), centered );

		if(mShader) mShader.unbind();
	}
	else {
		mCamera.disableStereo();

		gl::pushMatrices();
		gl::setMatrices( mCamera.getCamera() );
		render();
		gl::popMatrices();
	
		// draw user interface
		mUserInterface.draw("Perspective Projection");
	}

	// fade in at start of application
	gl::enableAlphaBlending();
	double t = math<double>::clamp( mTimer.getSeconds() / 3.0, 0.0, 1.0 );
	float a = ci::lerp<float>(1.0f, 0.0f, (float) t);

	if( a > 0.0f ) {
		gl::color( ColorA(0,0,0,a) );
		gl::drawSolidRect( getWindowBounds() );
	}
	gl::disableAlphaBlending();
}
Ejemplo n.º 9
0
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();
}