Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
746 views
in Technique[技术] by (71.8m points)

2d - OpenGL stretched shapes - aspect ratio

I got my openGL view at a size of (lets say..) 800(width)x600(height). Then i got a 2D object of coords:

0.0 , 0.0
0.1 , 0.0
0.1 , 0.1
0.0 , 0.1

this, as you understand is supposed to be a square (based on analogy). But on my openGL view prints this stretched. Now, i understand why this is happening. Its basically because im working on the default matrix of -1,1. And since my resolution of 800x600 doesnt have an aspect ratio of 1, my shape is getting stretched.

Now im more interested on how to fix this. Ive read about functions like glFrustum, glOrtho, glViewPort which are happening on the projection matrix and can address such issues. Thing is, im not sure on using them. What i basically want is keep the above coords when making a square and actually apear as a square on my View.

Whats the correct way of addressing this issue?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
float aspect = (float)width / (float)height;
glOrtho(-aspect, aspect, -1, 1, -1, 1);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

Update: Explanation what happens

OpenGL is a state machine and in the case of OpenGL-2.1 and below maintains a set of transformation matrices. A vertex ↑v first gets multiplied with the modelview matrix to yield a eye coordinate vertex ↑v', which is used for lighting calculations. Then ↑v' is multiplied by the projection matrix to reach the so called clip space ↑v'', where (the name suggests it) the clipping operations are performed (or at least their outcome is defined). From clip space the so called Normalized Device Coordinates (NDC) are reached by calculating ↑v#{x,y,z,w} = ↑v{x,y,z,w}/↑v_w

↑v# is defined to be in the range [-1 … 1] which is mapped to fill the selected viewport rect. The viewport does not influence the transformation matrices! It's only the transformation from NDC to window coordinates it defines.

In the code above I set the modelview matrix to identity, i.e. the vertices go into projection as they are. The projection itself is a ortho projection, that maps the x value range [-aspect … aspect] → [-1 … 1] and y value range [-1 … 1] → [-1 … 1] (i.e. no change for y). So vertices get transformed by the window aspect to fit into the NDC to viewport value range.

And why did I tell you that OpenGL is a state machine? Because it means that you can switch projections and transformations anytime. So if you need to render a minimap, don't struggle with getting it placed in the 3D scene. Just switch the viewport and projection for it. In general you should set all rendering state (that means all the matrices) in the drawing function. Window event handlers (except the redraw handler) should perform no OpenGL operations at all.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...