OpenGL 拉伸形状 - 纵横比 [英] OpenGL stretched shapes - aspect ratio

查看:24
本文介绍了OpenGL 拉伸形状 - 纵横比的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的 openGL 视图的大小为(可以说..)800(宽度)x600(高度).然后我得到了一个二维坐标对象:

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

正如你所理解的,这应该是一个正方形(基于类比).但是在我的 openGL 视图上打印出这个拉伸.现在,我明白为什么会这样了.它基本上是因为我正在研究 -1,1 的默认矩阵.由于我的 800x600 分辨率没有 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.

现在我对如何解决这个问题更感兴趣.我读过像 glFrustum、glOrtho、glViewPort 之类的函数,它们在投影矩阵上发生并且可以解决这些问题.事情是,我不确定使用它们.我基本上想要的是在制作正方形时保持上述坐标,并在我的视图中实际显示为正方形.

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?

推荐答案

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{x,y,z,w}/↑v_w

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# 被定义在 [-1 … 1] 范围内,该范围被映射以填充选定的视口矩形.视口不影响变换矩阵!它只是从NDC到它定义的窗口坐标的转换.

↑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.

在上面的代码中,我将模型视图矩阵设置为标识,即顶点按原样进行投影.投影本身是一个正交投影,映射 x 值范围 [-aspect ... aspect] → [-1 ... 1] 和 y 值范围 [-1 ... 1] → [-1 ... 1](即 y 没有变化).因此,窗口方面会转换顶点以适应 NDC 到视口值范围.

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.

我为什么要告诉你 OpenGL 是一个状态机?因为这意味着您可以随时切换投影和变换.因此,如果您需要渲染小地图,请不要费力将其放置在 3D 场景中.只需为它切换视口和投影即可.通常,您应该在绘图函数中设置所有渲染状态(即所有矩阵).窗口事件处理程序(重绘处理程序除外)不应执行任何 OpenGL 操作.

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.

这篇关于OpenGL 拉伸形状 - 纵横比的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆