opengl投影变换与逆变换

一个新手都在问的:opengl中如何将2d窗口坐标转换为3d空间坐标。

以下是测试代码,需用到glm库。

#include <string>
#include <cstdlib>
#include <iostream>
#include <glm/glm.hpp>
#include <glm/ext.hpp>
using namespace std;
using namespace glm;

void print(const vec4& v) {
    cout << v[0] << " " << v[1] << " " << v[2] << " " << v[3] << endl;
}

void print(const mat4& m) {
    print(glm::column(m, 0));
    print(glm::column(m, 1));
    print(glm::column(m, 2));
    print(glm::column(m, 3));
}

int main(int argc, char** argv) {
    //投影变换 mat4 proj
= glm::perspective(45.0f, 1.0f, 0.1f, 10.0f); { vec4 pos = vec4(3, 3, -9, 1); pos = proj*pos; print(pos); pos /= pos.w; print(pos); } cout<<endl;
    //投影逆变换 {
float x=0.5,y=0.5,z=-1; vec4 pos=vec4(x,y,z,1); mat4 invProj=glm::inverse(proj); pos=invProj*pos; print(pos); pos/=pos.w; print(pos); } return 0; }

文中忽略模型视图矩阵,就当相机固定在世界中心往负z轴方向观察。

3d转2d为投影变换,一般会经历以下流程:

1)在VertexShader中完成Position=ProjectionMatrix*Position,这就是裁剪坐标

2)Position/=Position.w,这就是ndc坐标

3)插值光栅化生成fragment,丢弃[-1,1]之外的fragment

4)执行FragmentShader

5)深度测试

2d转3d就是投影变换的逆过程。

1)窗口坐标x,y取值变换到[-1,1],该过程简单却表述麻烦,略过。

2)z取值为1表示3d点在相机远裁面上,-1表示在相机近裁面上,

   注意这时不是右手坐标系,这是投影矩阵相乘后的结果。

3)w取值为1,该值会被投影逆矩阵改变,因为投影变换不是线性变换。

4)这时构造出的position为vec4(x,y,1,1)

5)投影矩阵求逆并与position相乘:position=invProjectionMatrix*position

6)position/=position.w,3d点都要保证w为1

这时已经完成了2d转3d,得出的点在相机远裁面上,

该点连接相机位置就能构建出用于鼠标拾取的射线。

这里缺少的细节就是投影矩阵的推导,网上文章很多,以后可能也会写一篇。

posted on 2012-12-10 10:59  SoMiSoDo  阅读(3991)  评论(0)    收藏  举报

导航