OpenGL——坐标系统与变换矩阵

为了将坐标从一个坐标系变换到另一个坐标系,我们需要用到几个变换矩阵

  • 局部空间(Local Space,或者称为物体空间(Object Space))
  • 世界空间(World Space)
  • 观察空间(View Space,或者称为视觉空间(Eye Space))
  • 裁剪空间(Clip Space)
  • 屏幕空间(Screen Space)

顶点坐标起始于局部空间(Local Space),在这里它称为局部坐标(Local Coordinate),它在之后会变为世界坐(WorldCoordinate),

观察坐标(View Coordinate),裁剪坐标(Clip Coordinate),并最后以屏幕坐标(Screen Coordinate)的形式结束。

  

  1. 局部坐标是对象相对于局部原点的坐标,也是物体起始的坐标。
  2. 将局部坐标变换为世界空间坐标,世界空间坐标是处于一个更大的空间范围的。
  3. 将世界坐标变换为观察空间坐标,使得每个坐标都是从摄像机或者说观察者的角度进行观察的。
  4. 坐标到达观察空间之后,需要将其投影到裁剪坐标。裁剪坐标会被处理至-1.0到1.0的范围内,并判断哪些顶点将会出现在屏幕上。
  5. 最后,裁剪坐标变换为屏幕坐标,将使用一个叫做视口变换(Viewport Transform)的过程。视口变换将位于-1.0到1.0范围的坐标变换到由glViewport函数所定义的坐标范围内。最后变换出来的坐标将会送到光栅器,将其转化为片段。

正射投影

    正射投影定义了一个类似立方体的平截头像箱(裁剪空间),在这个空间之外的顶点都会被裁剪掉;

       

     上面的平截头体定义了可见的坐标,它由由宽、高、近(Near)平面和远(Far)平面所指定。

透视投影

     投影矩阵将给定的平截头体范围映射到裁剪空间,除此之外还修改了每个顶点坐标的w值,从而使得离观察者越远的顶点坐标的w分量越大;变换到裁剪空间的坐标都会在-w到w的范围之间;OpenGL 要求所有可见的坐标都会落在-1.0到1.0范围内,作为顶点着色器的最后输出。

透视除法会被应用到裁剪空间坐标上,顶点坐标的每个分量都会除以它的w分量,距离观察者越远顶点坐标就会越小。

    glm::perspective(glm::radians(45.0f), (float)width/(float)height, 0.1f, 100.0f);

    a.  第一个参数定义了fov的值,它表示的是视野(Field of View),并且设置了观察空间的大小。

         如果想要一个真实的观察效果,它的值通常设置为45.0f,但想要一个末日风格的结果你可以将其设置一个更大的值。

    b. 第二个参数设置了宽高比,由视口的宽除以高所得。

    c. 第三和第四个参数设置了平截头体的平面。我们通常设置近距离为0.1f,而远距离设为100.0f。所有在近平面和远平            面内且处于平截头体内的顶点都会被渲染。

 

  一个顶点坐标将会根据以下过程被变换到裁剪坐标:

       注意矩阵运算的顺序是相反的(记住我们需要从右往左阅读矩阵的乘法)。最后的顶点应该被赋值到顶点着色器中的                     gl_Position,OpenGL将会自动进行透视除法和裁剪。

 

视口变换

       顶点着色器的输出要求所有的顶点都在裁剪空间内,这正是我们刚才使用变换矩阵所做的。OpenGL然后对裁剪坐标执行透视除法从而将它们变换到标准化设备坐标。OpenGL会使用glViewPort内部的参数来将标准化设备坐标映射到屏幕坐标,每个坐标都关联了一个屏幕上的点

 

观察空间

观察空间是以摄像机的视角作为场景原点时,场景中所有的顶点坐标:观察矩阵吧所有的世界坐标变换为相对于摄像机位置与方向的观察坐标。

定义一个摄像机:

     a. 摄像机的位置

         摄像机的位置简单来说就是世界空间中一个指向摄像机位置的向量

         glm::vec3 P = glm::vec3(0.0f, 0.0f, 3.0f);

     b. 摄像机的方向

         摄像机指向哪个方向,由于摄像机指向轴负方向,但我们希望方向向量(Direction Vector)指向摄像机的z轴正方向。如果我             们交换相减的顺序,我们就会获得一个指向摄像机正z轴方向的向量:

         glm::vec3 cameraTarget = glm::vec3(0.0f, 0.0f, 0.0f);

         glm::vec3 D= glm::normalize(cameraPos - cameraTarget);

     c. 右轴

         我们需要的另一个向量是一个右向量(Right Vector),它代表摄像机空间的x轴的正方向。为获取右向量我们需要先使用一个  小技巧:先定义一个上向量(Up Vector)。接下来把上向量和第二步得到的方向向量进行叉乘。两个向量叉乘的结果会同时垂直于两向量,因此我们会得到指向x轴正方向的那个向量(如果我们交换两个向量叉乘的顺序就会得到相反的指向x轴负方向的向量):

glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f);

glm::vec3 R = glm::normalize(glm::cross(up, cameraDirection));

      d. 上轴

          利用右轴和摄像机的方向进行叉乘获取一个指向摄像机y轴向量。

          glm::vec3 U = glm::cross(cameraDirection, cameraRight);

 

利用摄像机3个相互垂直的轴定义一个坐标空间,可以用这三个轴外加一个平移向量来创建一个矩阵,并且可以用这个矩阵倡议任何向量来将其变换到那个坐标空间,这就是LookAt矩阵所作的。

其中R是右向量,U是上向量,D是方向向量P是摄像机位置向量。注意,位置向量是相反的,因为我们最终希望把世界平移到与我们自身移动的相反方向。把这个LookAt矩阵作为观察矩阵可以很高效地把所有世界坐标变换到刚刚定义的观察空间。LookAt矩阵就像它的名字表达的那样:它会创建一个看着(Look at)给定目标的观察矩阵。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值