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,得出的点在相机远裁面上,
该点连接相机位置就能构建出用于鼠标拾取的射线。
这里缺少的细节就是投影矩阵的推导,网上文章很多,以后可能也会写一篇。
 
                    
                 
                
            
         
 浙公网安备 33010602011771号
浙公网安备 33010602011771号