关于OpenGL中正交与透视的问题

Shr*_*ers -2 opengl 3d matrix

我有一个围绕y轴旋转的3个顶点三角形.我发现"怪异"的一件事是GL默认正交投影中的归一化坐标.我使用过像SDL和SFML这样的二维库,几乎总是处理像素.你说你想要一个50x50像素的图像表面,这就是你得到的.所以最初我很难说从[-1,1]中限制我的顶点位置选择.

为什么正交坐标必须标准化?透视投影是否相同?如果是这样,你怎么说你希望你的对象的原点在z = -10?(我快速浏览矩阵m ath说透视是不同的.关于除以'w'创建同质(与标准化相同的东西?)坐标的东西,但我不确定).

gl_Position = View*Model*Project*Vertex;

我已经看到上面的等式,我很惊讶于着色器中使用的变量gl_Position如何既可以表示模型/对象的当前顶点的位置,又可以表示视图/投影的位置,或者相机.这是如何运作的?我通过乘法理解所有信息都存储在一个矩阵中,但OpenGL如何使用一个矩阵,其信息现在被组合起来说,"好吧,gl_Position的这部分/分数用于摄像机,而另一部分是信息该模型将要去哪里."?(顺便说一句,我不太确定Vertex vec4代表什么.我认为模型的所有顶点都在模型内部.任何想法?

还有一个问题,如果你只是想移动相机,例如在FPS游戏中你移动鼠标向上移动,但是除了相机之外没有任何物体被旋转或翻译(我认为),上面的等式会看起来像什么像这样?

gl_Position =查看*项目;

dat*_*olf 5

为什么正交坐标必须标准化?

他们没有.您可以根据需要设置正交投影体积的限制.glOrtho调用的left,right,bottom,top,near和far参数定义视口量的限制.如果您选择它们​​left = 0,right = win_pixel_width,bottom = 0,top = win_pixel_height,您最终会得到像往常一样的像素单位投影体积.但是为什么还要用像素呢?您只需要稍后补偿实际的窗口大小.只需选择邻域投影体积范围以匹配您要绘制的场景.

也许你把这与标准化的设备坐标混淆了.对于那些,它只是被定义为映射到视口范围的值范围[-1,1].

更新

顺便说一句,我不太清楚Vertex vec4代表什么.我认为模型的所有顶点都在模型中.有任何想法吗?

我现在变得非常疲惫,因为在过去的几天里我已经多次回答过这么多问题.所以,在这里又一次:

在OpenGL中没有相机.

在OpenGL中没有场景.

在OpenGL中没有模型.

"等等,什么?!" 你现在可能想知道.但这是真的.

所有OpenGL关心的是,有一些目标帧缓冲区,即它可以绘制的画布,以及制作几何图元的顶点属性流.基元是点,线和三角形.不知何故,三角形的顶点属性必须映射到帧缓冲画布上的位置.对于这个顶点属性,我们称之为位置经历了许多仿射变换.

第一种是从局部模型空间到世界空间的模型变换.

从世界空间到眼睛空间,视图变换.正是这种视图变换,就像将相机放在场景中一样.

之后,它通过相机的镜头,这是一个投影变换.

在投影变换之后,位置处于剪辑空间中,在该空间中它经历一些操作,这对于暂时理解不是必需的.在剪切之后,通过将剪辑空间位置矢量除以其自身的w分量,应用所谓的均匀划分以达到标准化设备坐标空间.

v_position_ndc = v_position_clip / v_position_clip.w
Run Code Online (Sandbox Code Playgroud)

这一步是什么使透视投影真正起作用.顶点'位置的z距离被加工到剪辑空间w-component中.并且通过具有较大位置的均匀分割顶点w在XY平面中与1/w成比例地缩放,这产生透视效果.

你把这个操作误认为是规范化,但事实并非如此!

在将均匀分割顶点位置从剪辑映射到NDC空间之后.并且OpenGL定义了NDC空间的可见体积是框[-1,1] ^ 3; 剪裁此框外的顶点.

理解View变换和Projection是不同的,这一点至关重要.对于一个位置它不是那么明显,但是另一个称为法线的顶点属性,它是照明计算的一个重要组成部分,必须以稍微不同的方式Projection · View · Model进行转换(而不是它必须被转换inverse(transpose(View · Model)),即投影不参与其中)但观点确实如此).

矩阵本身是4×4网格的实值标量(暂时忽略计算机中的数字总是有理数).所以矩阵的秩是4,因此它必须乘以维数4的向量(因此类型为vec4)

OpenGL将顶点属性视为列向量,因此矩阵乘法是左关联的,即向量在右侧进入表达式并在左侧出现.矩阵乘法的顺序很重要.你不能自由地重新订购东西!

该声明

gl_Position = Projection * View * Model * vertex_position; // note the order
Run Code Online (Sandbox Code Playgroud)

使顶点着色器执行我刚才描述的这个转换过程.