OpenGL 坐标系统 投影

为了将坐标从一个坐标系变换到另一个坐标系,我们需要用到几个变换矩阵,最重要的几个分别是模型(Model)、观察(View)、投影(Projection)三个矩阵。比如一个空间中物体的移动,旋转,缩放或叠加在一起的复合变换都可以用一个4×4的矩阵乘以找个物体的所有顶点来实现,这就是模型矩阵;当我们想在某个特定的位置和角度去观察三维空间中的物体的时候,我们就可以用一个矩阵去乘以找个物体的所有顶点来实现,这样的矩阵就是观察矩阵;投影矩阵又有什么用呢?在三维空间里面我们尽力去描绘一种跟我们现实世界看到的一样的视觉效果,投影在这里便起了最显著的效果。

投影分为正射投影和透视投影,他们都是将三维坐标映射到2D平面,但是由于正射投影没有将透视考虑进去,所以会产生不真实的效果,即没有现实中的“近大远小“的效果,所以在三维效果显示上一般都会选择透视投影。
这里写图片描述
不管是前面讲到的模型矩阵,观察矩阵还是现在的投影矩阵,他们都只是一个矩阵,本质上都是坐标变换,下面的公式对顶点坐标的变换将可以得到一个三维视角。对于投影具体的变换原理,这里不做细述,如果有疑问可以参照这里

V=MprojectionMviewMmodelVlocal

除此之外,投影还有一个非常有用的功能。因为将所有可见的坐标都指定在-1.0到1.0的范围内不是很直观,所以我们会指定自己的坐标集(Coordinate Set)并将它变换回标准化设备坐标系,就像OpenGL期望的那样。而通过投影矩阵,就可以不局限于(-1, 1)这个范围去定义顶点坐标,这样我们就可以按照自己的方式去定义坐标,比如可以使用屏幕像素的方式定义坐标。投影矩阵可以帮我们把坐标由我们自己定义的坐标系统转换成OpenGL内部标准化设备坐标(-1, 1),这个在实际开发过程中还是很有用的。
这里有两个函数需要注意:

glViewport (GLint x, GLint y, GLsizei width, GLsizei height);

该函数的前两个参数表示窗口的左下角坐标,后两个参数设置窗口尺寸。

mat4x4 ortho(float left, float right,   float bottom, float top, float zNear, float zFar);

这个是创建正射投影的函数,通过这个函数可以生成一个投影矩阵,前两个参数指定了平截头体的左右坐标,第三和第四参数指定了平截头体的底部和顶部。通过这四个参数我们定义了近平面和远平面的大小,然后第五和第六个参数则定义了近平面和远平面的距离。这个投影矩阵会将处于这些x,y,z值范围内的坐标变换为标准化设备坐标。

所以要通过像素坐标或其他非标准化设备坐标去指定顶点的时候就需要设置投影矩阵,下面举个例子:

glViewport(0, 0, 800, 600); 

该函数设置窗口左下角为(0,0)点,宽800, 高600,这样就确定了视口的坐标和大小(这个视口可以小于窗口),该函数只是指定了最终要显示在窗口的画面的位置和大小。

mat4 projection = ortho(0.0f, 800.0f, 0.0f, 600.0f, 0.1f, 100.0f);  

ortho是GLM的内置函数,通过设置函数的参数可以对应到屏幕上的像素点坐标位置,使得输入顶点的坐标和最终显示在窗口的像素坐标对应。
这里写图片描述

如上图所示我们可以给顶点着色器传递和窗口坐标相同的坐标:


GLfloat vertices[] = {  
        600.0f, 150.0f, 0.0f,
        600.0f, 450.0f, 0.0f,
        200.0f, 150.0f, 0.0f,
};

我们看到在上面的顶点坐标里不再局限于(-1, 1)了,因为我们使用了投影矩阵,此时的顶点坐标范围为(0,0)~(800, 600),这里未考虑深度,所以我们这样的用法或许更加适用于2D平面图。

通常在Windows的窗口系统中,窗口的左上角以(0,0)为坐标原点,而我们刚才设置的参数使得窗口的左下角(0,0)为原点,为此我们可以设置ortho函数的参数来让我的窗口坐标系统符合Windows窗口的坐标习惯。

mat4 projection = ortho(0.0f, 800.0f, 600.0f, 0.0f, 0.1f, 100.0f);  

这样设置就可以让y轴上下颠倒,实际效果就是窗口坐标原点到了左上角。

参考:LearnOpenGL CN 坐标系统

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值