(本文是LearnOpenGL的学习笔记, 教程中文翻译地址https://learnopengl-cn.github.io/(备用地址https://learnopengl-cn.readthedocs.io/zh/latest/),写于 2022-04-04)

0.前言

在之前的图形绘制操作中,都是将模型顶点坐标转换为屏幕坐标进行显示。但在进行如人机交互时,可能需要将屏幕坐标转换到世界坐标,比如点击物体进行选中,如果采用射线拾取法,就需要将屏幕坐标系的点转到世界坐标系去。

1.知识点

先复习下顶点的坐标转换流程,图1来自LearnOpenGL,图2来自OpenGL编程指南

顶点坐标通过模型矩阵、视图矩阵、投影矩阵转换到裁剪空间。 转换到裁剪空间后经过GPU的裁剪处理就可以得到最终需要被渲染的物体顶点坐标了,接下来GPU会做透视除法(xyz都除以w)将顶点转换到标准化设备坐标(Normalized Device Coordinate, NDC)中,透视除法将裁剪空间中顶点的4个分量都除以w分量,就从裁剪空间转换到了NDC了,NDC是一个长宽高取值范围为[-1,1]的立方体。将顶点坐标都转换到NDC后,下一步就是屏幕映射,这个就取决于最终要渲染到的窗体分辨率。

现在要做的就是将上面的步骤反过来走一遍。

先是将屏幕坐标转为NDC坐标:

因为屏幕只有一个xy平面,所以z值任取[-1,1]一点。(两个不同z值的点连成一条线,和场景中的物体做相交检测后,可以获取到离屏幕最近的一个面的z值)

NDC到裁剪空间,加一个为1的w分量作为齐次坐标。

剩下就是裁剪坐标到世界坐标,直接用mvp转换矩阵的逆矩阵计算。

2.代码实现

github链接(MyRayPick类):https://github.com/gongjianbo/OpenGLwithQtWidgets

float ndc_x = 2.0f * pos.x() / width() - 1.0f;
float ndc_y = 1.0f - (2.0f * pos.y() / height());
float ndc_z = 1.0f;//view视图矩阵和projection投影矩阵取渲染时的值
QVector3D ndc_ray = QVector3D(ndc_x, ndc_y, ndc_z);
QVector4D clip_ray = QVector4D(ndc_ray, 1.0f);
QVector4D eye_ray = projection.inverted() * clip_ray;
QVector4D world_ray = view.inverted() * eye_ray;
//转笛卡尔坐标
if(world_ray.w() != 0.0f){world_ray /= world_ray.w();
}

3.参考

LearnOpenGL:坐标系统 - LearnOpenGL CN

书籍:《OpenGL编程指南》(原书第九版)第五章

博客:[OpenGL]射线拾取RayPicking---(1)生成射线_HELLO_IHAD的博客-CSDN博客

博客:屏幕坐标转世界坐标与射线生成 - 知乎

博客:Clip Space、NDC、Screen Space - 简书

OpenGL with QtWidgets:屏幕坐标转世界坐标相关推荐

  1. ThreeJS 屏幕坐标与世界坐标互转

    文章目录 屏幕坐标系和标准设备坐标 屏幕坐标转世界坐标 世界坐标转屏幕坐标   要理解坐标系间的转换过程,需要提前了解: ThreeJS 中的几种坐标系 屏幕坐标系和标准设备坐标系   不想看链接中的 ...

  2. U3D屏幕坐标,世界坐标,像素坐标之间的关系

    U3D屏幕坐标,世界坐标,像素坐标之间的关系 U3D中,屏幕坐标和世界坐标单位一样,二者之间是直接的一一对应关系,不受屏幕分辨率影响.默认情况下屏幕空间画布的左下角坐标是世界原点(0,0,0),这种情 ...

  3. OpenGL 获取当前屏幕坐标对应的三维坐标

    转自原文 OpenGL 获取当前屏幕坐标对应的三维坐标,使用很简单glu库中的一个函数 #include <GL/glut.h> #include <stdlib.h> #in ...

  4. OSG——- 对点选物体平移(鼠标点选物体、物体随鼠标移动、屏幕坐标转世界坐标)

    之前的一篇博文是有一篇对点选物体进行平移.缩放旋转.那一篇是很简单的调用了OSG中定义的一些dragger,但这些dragger都有坐标轴或者tapbox等在模型上,与我最近要做的事情的需求不同.网上 ...

  5. UE5如何将屏幕坐标转为世界坐标和世界方向

    哈喽,大家好,一起分享一下关于UE5如何将屏幕坐标转为世界坐标的方法. 屏幕坐标转为世界坐标 在PlayerControoler下找到这个函数: DeprojectScreenPositionToWo ...

  6. Unity中屏幕坐标与世界坐标之间的转换

    世界坐标系转换为屏幕坐标 屏幕坐标转世界坐标 using System.Collections; using System.Collections.Generic; using UnityEngine ...

  7. OpenGL with QtWidgets:练习之甜甜圈

    甜甜圈是 <OpenGL 超级宝典>上的一个示例,用来演示面剔除和深度测试应用,原本的代码顶点和着色器部分不便于学习,我就重新写了下,略去了法线和光照相关. 当我们对渲染出来的甜甜圈进行旋 ...

  8. OpenGL with QtWidgets:练习之扑克翻转

    (本文是LearnOpenGL的学习笔记,教程中文翻译地址https://learnopengl-cn.github.io/(备用地址https://learnopengl-cn.readthedoc ...

  9. OpenGL with QtWidgets:投光物、多光源

     (本文是LearnOpenGL的学习笔记, 教程中文翻译地址https://learnopengl-cn.github.io/(备用地址https://learnopengl-cn.readthed ...

  10. OpenGL with QtWidgets:练习之绘制2D环形进度条

    1.实现思路 这里主要涉及几个点:绘制圆环,绘制文字,动画,抗锯齿. 绘制圆环网上有些人是计算好圆边的顶点后传入的,我这里直接在片段着色器里根据距离圆心的距离来渲染的圆环. void main() { ...

最新文章

  1. http 的一生: 一、特点与 URL解析
  2. 大家都在晒的支付宝3分钱付款截图,让千万人有了“半毛钱”关系
  3. netflix zuul 1.x与zuul2.x之比较
  4. day05 Spring中自定义注解的用处-之获取自定义的Servie
  5. typescirpt 知识点
  6. 如何用crontab每隔1分钟执行一个命令行脚本
  7. [转载]Linux下getopt()函数的简单使用
  8. 【UOJ#246】套路(动态规划)
  9. bootstrap-table之通用方法( 时间控件,导出,动态下拉框, 表单验证 ,选中与获取信息)
  10. 写了一篇关于 NLP 综述的综述!
  11. c语言 1 %3c%3c -253,结构体嵌套 姓名前后怎么输出两次??
  12. ModelDriven机制及其运用
  13. 在linux命令行利用SecureCRT上传下载文件
  14. 天文软件ds9对图片调整颜色和两张图片坐标自动匹对
  15. 算法:唯一路径Unique Paths 动态规划和二项系数解法
  16. Tp5 写随机数(商品货号)
  17. 揭密360急速免杀系列教程
  18. java 加载dll文件
  19. 微信小程序测试注意事项
  20. 金蝶怎么录入数量金额_金蝶KIS专业版如何录入初始余额

热门文章

  1. QT 车牌号正则验证
  2. iOS 超好用的本地视频播放器推荐!
  3. Itext对pdf模板进行电子签名
  4. C#逆向反编译工具:JetBrains dotPeek
  5. C#通过Aforge调用电脑摄像头(附代码)
  6. Linux基础知识、常用命令和操作
  7. 微信小程序锦鲤砍价 搭建教程完整版
  8. Nginx 使用的 epoll 模型详解
  9. 明解C语言【中级篇】
  10. 建筑电工模拟考试完整版在线讲解