我的openGL视图的大小为(比如说).. 800(宽度)x600(高度)。 然后我得到了一个二维协调对象:
0.0 , 0.0
0.1 , 0.0
0.1 , 0.1
0.0 , 0.1
这个,正如你所理解的那样应该是一个正方形(基于类比)。 但是在我的openGL视图中打印出这个拉伸。现在,我理解为什么会这样。它基本上是因为我正在使用-1,1的默认矩阵。 而且由于800x600的分辨率不是1的宽高比,我的形状会变得很紧张。
现在我对如何解决这个问题更感兴趣。我已经阅读过像glFrustum,glOrtho,glViewPort这样的函数,它们正在投影矩阵上发生,可以解决这些问题。事实是,我不确定使用它们。我基本上想要的是在制作一个正方形时保持上面的坐标,并且在我的视图上实际上是一个正方形。
解决这个问题的正确方法是什么?
答案 0 :(得分:21)
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();
OpenGL是一个状态机,在OpenGL-2.1及以下的情况下维护一组转换矩阵。顶点↑v 首先与 modelview 矩阵相乘,以产生眼睛坐标顶点↑v',用于照明计算。然后↑v'乘以投影矩阵,以达到所谓的剪辑空间 ↑v'',其中(顾名思义)执行剪切操作(或者至少定义它们的结果)。从剪辑空间,通过计算↑v# {x,y,z,w} = ↑v >来达到所谓的规范化设备坐标(NDC)强> {X,Y,Z,W} /的↑v 强> _w
↑v#定义在[-1 ... 1]范围内,该范围被映射以填充选定的视口rect。视口不会影响转换矩阵!它只是从NDC到它定义的窗口坐标的转换。
在上面的代码中,我将模型视图矩阵设置为identity,即顶点按原样进入投影。投影本身是一个正投影,它映射x值范围[-aspect ... aspect]→[-1 ... 1]和y值范围[-1 ... 1]→[-1 ... 1](即y没有变化) )。因此,顶点会被窗口方面转换为适合NDC到视口值范围。
为什么我告诉你OpenGL是状态机?因为这意味着您可以随时切换投影和变换。因此,如果您需要渲染小地图,请不要将其置于3D场景中。只需切换视口和投影即可。通常,您应该在绘图函数中设置所有渲染状态(即所有矩阵)。窗口事件处理程序(重绘处理程序除外)根本不应执行任何OpenGL操作。