Jump to content
  • Advertisement
Sign in to follow this  
Will-O

OpenGL Consistent Aspect

This topic is 3415 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm sure this is very easy but I'm going round and round in circles with it! I need the view of the current scene to maintain its aspect ratio, irrespective of the size/aspect of the window. If the scene aspect is not the same as the window aspect then there is padding around the scene, which is fine. Lastly if the scene is smaller than the window in both directions, it should not be resized to fill the window it should be left at its native size. I need to use an ortho projection so z-shifting objects has no effect. Not sure how clear that was so here's some code...
void Camera::SetupOrtho(GLdouble &winW, GLdouble &winH)
{
	GLdouble winAspect = winH / winW;

	GLdouble sceneW, sceneH, sceneD;
	GetSceneDimensions(sceneW, sceneH, sceneD);	// does what it says

	_near = 1.0;
	_far = (10.0 > sceneD) ? 10.0 : sceneD;		// set view depth

	GLdouble sceneAspect = sceneH / sceneW;	

	GLdouble viewW;								// variables filled 
	GLdouble viewH;								// once cases are tested

	if(sceneW >= winW && sceneH >= winH && sceneAspect >= winAspect)
	{
		// eg scene: 500 x 700, win: 450 x 480 => view: 656.25 x 700
		viewW = sceneH / winAspect;   // this is correct!
		viewH = sceneH;
	}

	else if(sceneW >= winW && sceneH >= winH && sceneAspect < winAspect)
	{
		// eg scene: 500 x 650, win: 400 x 600 => ??
	}
	
//	else if(sceneW >= winW && sceneH < winH && sceneAspect >= winAspect)
//	{
//		impossible case
//	}
	
	else if(sceneW >= winW && sceneH < winH && sceneAspect < winAspect)
	{
		//eg scene: 500 x 400, win: 400 x 500 => ??
	}
	else if(sceneW < winW && sceneH >= winH && sceneAspect >= winAspect)
	{
		// eg scene: 300 x 600, win 400 x 500 => ?? 
	}
//	else if(sceneW < winW && sceneH >= winH && sceneAspect < winAspect)
//	{
//		impossible case
//	}
	
	else //if(sceneW < winW && sceneH < winH && sceneAspect >= winAspect)
	{
	//} // grouping these two because aspect is irrelevant
	
	//else// i.e. (sceneW < winW && sceneH < winH && sceneAspect < winAspect)
	//{
		viewW = winW;
		viewH = winH;
	}

	_rhs = 0.5 * _viewMargin * viewW;
	_lhs = -_rhs;
	_top = 0.5 * _viewMargin * viewH;
	_btm = -_top;
	
	//------------------------------------------------------------------
	// do the projection...

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	glOrtho(_lhs, _rhs, _btm, _top, _near, _far);
}

I know the question isn't strictly OpenGL but think it fits here better than anywhere else. The comments are precisely that so some might seem pointless. As the if-else cases show, there are 8 options 2 of which are impossible a further 2 of which can be grouped together so of the five remaining I have solved - the first (when the scene is wider, taller and has a larger aspect than the window) - and the last (when the scene is thinner and shorter than the window thus the aspect doesn't matter). What are the other three cases? As I said at the top, I'm sure this is simple and indeed I may be going about this completely the wrong way, possibly I'm just being a bit dim but if anyone knows the solution I'm all ears. Many thanks in advance for any help received.

Share this post


Link to post
Share on other sites
Advertisement
I would suggest that you render the scene to an FBO rather than direct to the screen. That way you can ensure that Aspect Ratio is always consistent.

All that is changing is how you draw the FBO after rendering. If you monitor the Height of your Window you know whether you need to scale the FBO output down or whether you need to add padding.

Share this post


Link to post
Share on other sites
Thanks Andy. Good tip about the FBO. However, once I've got the scene to a 2D image, I'm still faced with the same problem of how to display the image at the same aspect as the original scene or FBO of scene.

Share this post


Link to post
Share on other sites
Render your scene to an FBO of a fixed resolution (lets say 1024x768 - an aspect ratio of 1.33).

Now lets say that your window is 1280x1024 (1.25)

You draw your FBO at the size 1024x768, which obviously will cause a border to appear around your FBO.

Now lets say you want to render smaller.

If you only monitor one dimension. ie, the Height then it makes life easier. Read the height of your Window and you see that it's 800. so what you do is:

Height_Scale = Window Height / FBO Height.

This gives you scale factor for the Height. Now you need to work out Scale factor for the Width. Since you know the Aspect Ratio you can just do

Width_Scale = Height_Scale * Aspect_Ratio

Then you will have an FBO that is always the same height as the window, but you will have a border appear on the left/right accordingly.

Hope this helps, I've not implemented this myself so I've not tested this so it's just theory.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!