路遥见人心,日久知马力

博客园 首页 新随笔 联系 订阅 管理

首先上结果(不会在博客园传视频、具体流程是鼠标点击屏幕上的任意一个点、向此处投射一条射线):

 


 

 实现的方法:

首先认清楚什么是一条射线、由于我们不是真的要画一条无限长度的线、那么用线段的起始和终止(当然是在世界坐标系里的起点和终点)就能代表这条射线、具体的shader可以用基本的MVPshader。

这个Ray类只是简单的用起点和终点画一条线而已,其中的 t 可以用来和别的表面求交点、所以暂时保留

 具体的、我们使用GLFW做窗口系统、先给GLFW注册一个点击事件函数、响应鼠标左键的单击、并且拿到像素坐标

(mouseX,mouseY)就是鼠标点击处的像素坐标!(左上角xy都最小,右下角xy都最大)

这里开始就比较有意思了、

首先:正着来的变换流程:

  模型--》世界--》观察变换(view)--》视锥体投影--》glViewPort转像素坐标

那么反着来、就需要先把(mouseX,mouseY)这种像素坐标转换到 [-1,1]的范围内:

 mouseX,mouseY在窗口左上角时为(0,0),可以代入这个公式里、发现 x = -1, y = 1,回忆 opengl NDC相关的知识、左上角确实是 (-1,1)!这个公式的正确性可以简单体会一下

关键在于 z 值的理解!z可以取 0 或者 1、取 0 代表我们鼠标点击的那一下是点到了【近平面】上、取 1 表示点击到了【远平面】上!

这里看图(鼠标画的确实不好看、将就一下!):

我们在屏幕上点了一下鼠标、要发射一条射线的话、需要确定起点和终点、起点一般就是我们的相机、而终点就是图上画的两个红色的 X 号、

相机和红色 X 之间的连线就是射线!我们取 z = -1 表示是近平面是那个红X、取 z = 1表示要取远平面的那个红X,其实两者和眼睛的连线是共线的,想取别的 z、只要在【-1,1】范围内、都是可以的、取远平面只是效果好点!

但取远平面能把线拉的长一点、方便观察结果!

 

 我们现在已经完成了像素--》NDC的转换、

回顾正着变换的方程:

Position(NDC) = P*V*Position(世界);

那么(简单移项):

Positon(世界) = 逆(P*V) * Position(NDC)

所以我们有:

 这样就能把屏幕转世界了

最后、new一个Ray对象(起点是相机位置、终点是逆变换到世界系的点)、放到全局的一个容器里、每次render时遍历容器(这里使用多态去处理、I_Drawable就是个接口):

后面就可以用 Ray 去做很多别的操作了!

完整工程下载:

链接:https://pan.baidu.com/s/1GFq0DIjHJMpG_u1U2ljiiA
提取码:s2m5

 

posted on 2022-11-02 17:27  只讲大白话  阅读(154)  评论(0编辑  收藏  举报