filament渲染引擎中的坐标转换

文章目录

    • 背景
    • openGL中的坐标转换
      • 简单的概念介绍
    • 屏幕坐标转世界坐标
      • openGL的实现
      • filament通过射线拾取计算
      • filament官方给出的转换方式
      • filament实现坐标转换的QA
        • 1、View::pick()
        • 2、为什么filament的计算方式没有除以w分量?
        • 3、为什么别的资料上都是inverse(viewMatrix * projectionMatrix) ?
        • 4、怎么判断这个世界坐标是不是在模型上,也就是怎么判断是不是点击了模型?
    • 世界坐标转屏幕坐标
    • 矩阵运算

背景

模型渲染到屏幕上之后,鼠标点击屏幕,我们怎么知道是否点击了模型,点击了模型的哪个位置呢? 这些需求都需要坐标转换,常规来说就是从世界坐标系转换到屏幕坐标系,或者从屏幕坐标系转换到世界坐标系。

博主在渲染这块也是个新手,大家一起学习。
本文使用的是google的filament渲染引擎。

openGL中的坐标转换

提起坐标转换,就不得不提经典的openGL了,可以参考以下文章:
ModelMatrix、ModelViewMatrix、ProjectionMatrix、NormalMatrix模型矩阵、模型视图矩阵、投影矩阵、正规矩阵详解_妙为的博客-CSDN博客
经典渲染流程:
image.png
坐标转换流程:
image.png

简单的概念介绍

假定读者已经了解了基本的渲染知识,我们这里不做过多解释,毕竟不是重点。以下概念来源:OpenGL矩阵变换的数学推导-腾讯云开发者社区-腾讯云

  • 首先OpenGL有个世界坐标系,我们渲染的物体就是在世界坐标系中,我们的模型需要放到世界坐标系中,那么当我们还没放的时候,模型就和世界坐标系没有联系,它就还处于自己的坐标系中,我们叫做模型坐标系、局部空间、局部坐标系,也就是图中的LOCAL SPACE。
  • 当我们把模型放到世界坐标系中,模型就在世界坐标系里有了坐标,也就是原来在LOCAL SPACE中的那些坐标值,变成了世界坐标系中的坐标值,帮助我们完成这个变换的就是模型矩阵,对应图中的MODEL MATRIX,于是这样我们就把模型放到了世界坐标系WORLD SPACE中
  • 放到世界坐标系后,是不是就确定了我们渲染出来看到的样子?还没有,大家可以想像一下,我把一个东西放在世界坐标系的某个地方,我可以从近处看观察它,也可以从远处观察它,还可以从上下左右观察它,甚至还可以倒着观察它,因些还需要确定我们观察它的状态。OpenGL里帮我们虚拟出了一个Camera(特别注意,这里的Camera不是指我们硬件的Camera),从API的层面上看,我们只需要设置Camera的位置、朝向的点坐标、以及Camera的上方向向量就能将观察状态定下来,而这些设置最终会转换成OpenGL中的视图矩阵,对应图中的VIEW MATRIX -经过View Matrix的变换后,我们观察它的结果就确定了,图中是从距离它一定的距离、上往下观察它,这时候的点坐标就来到了视图坐标系下,对应图中的VIEW SPACE -这时候,我们能看到什么东西,基本已经确定了,不过还有一步投影变换,这是什么东西?大家想像一下,我们看到同一个东西,是不是通常都是近大远小?那么如何实现近大远小?就要靠投影变换,OpenGL提供正交投影和透视投影,正交投影没有近大远小的效果,不管在什么距离上看,都一样大,透视投影则有近大远小的效果,也是符合我们实际生活的一种效果,透视投影应用得比较多

还可以参考以下文章加深理解:
ModelMatrix、ModelViewMatrix、ProjectionMatrix、NormalMatrix模型矩阵、模型视图矩阵、投影矩阵、正规矩阵详解_妙为的博客-CSDN博客
[OpenGL]OpenGL坐标系及坐标转换-腾讯云开发者社区-腾讯云

屏幕坐标转世界坐标

openGL的实现

上面的图让我们知道了渲染的矩阵变换,从屏幕坐标到世界坐标其实就是反步骤来计算。例如顺序矩阵变化是viewMatrix * projectionMatrix,那么求逆就是inverse(viewMatrix * projectionMatrix) 了。
可以参考stack overflow的回答:https://stackoverflow.com/questions/46749675/opengl-mouse-coordinates-to-space-coordinates/46752492#46752492

通过逆矩阵的方式

mat4 inversePrjMat = inverse( prjMat );
vec4 viewPosH      = inversePrjMat * vec4(ndc_x, ndc_y, 2.0*depth - 1.0, 1.0)
vec3 viewPos       = viewPos.xyz / viewPos.w;

filament通过射线拾取计算

https://github.com/google/filament/discussions/5998?sort=new
这种是不使用官方的pick()函数,自己手写计算的射线拾取。这个issue主要存在的问题就是没有设置裁剪空间的w,并且也没有除以w。
射线拾取参考:屏幕坐标转世界坐标与射线生成

filament官方给出的转换方式

 /*** screen space coordinates in GL convention, this can be used to compute the view or* world space position of the picking hit. For e.g.:*   clip_space_position  = (fragCoords.xy / viewport.wh, fragCoords.z) * 2.0 - 1.0*   view_space_position  = inverse(projection) * clip_space_position*   world_space_position = model * view_space_position** The viewport, projection and model matrices can be obtained from Camera. Because* pick() has some latency, it might be more accurate to obtain these values at the* time the View::pick() call is made.*/

具体代码

// 1、获取clip_space_position
const Viewport& vp = view->getViewport();
float clip_space_x = (result.fragCoords.x / vp.width  - 0.5f) * 2.0f;
float clip_space_y = (result.fragCoords.y / vp.height - 0.5f) * 2.0f;
float clip_space_z = result.fragCoords.z * 2.0f - 1.0f;
float4 clip_space_position {clip_space_x, clip_space_y, clip_space_z, 1.0f};// 2、获取视图矩阵
mat4 projection = camera.getProjectionMatrix();
mat4 model = camera.getModelMatrix();
mat4 view_space_position = model * inverse(projection);
// 3、获取世界坐标系
float4 world_space_position = clip_space_position * view_space_position;

filament实现坐标转换的QA

1、View::pick()

View::pick()会有延迟,需要在pick()函数中获取模型矩阵,投影矩阵进行计算。在pick()函数外获取投影矩阵是不准确的,我踩的坑就是在pick()函数外获取的投影矩阵,在使用的时候发现矩阵变化了,导致inverse出来了inf和-nan等值。
inf 表示一个数超过了浮点类型所能表示的最大范围,通常为正无穷或负无穷。
nan 表示一个数不是一个合法的数字,通常出现在无法进行有效运算时。

2、为什么filament的计算方式没有除以w分量?

剪辑空间是齐次坐标系,转换成笛卡尔坐标系需要除以w,而我们设置的w是1.0,当缩放坐标的W为1时,坐标不会增大或缩小,保持原有的大小。所以,当W=1,不会影响到X,Y,Z分量的值。因此不影响最终结果。
什么是齐次坐标系?为什么要用齐次坐标系?

3、为什么别的资料上都是inverse(viewMatrix * projectionMatrix) ?

在filament中,viewMatrix = inverse(getModelMatrix()) ,所以:
inverse(viewMatrix * projectionMatrix) = inverse(viewMatrix) * inverse(projectionMatrix)
= getModelMatrix() * inverse(projectionMatrix)

参考:https://stackoverflow.com/questions/66160973/finding-world-position-of-element-in-screen-space
https://stackoverflow.com/questions/68870053/how-to-get-world-coordinates-from-the-screen-coordinates

4、怎么判断这个世界坐标是不是在模型上,也就是怎么判断是不是点击了模型?

filament中是通过pick()函数来实现的,获取到点击位置对应的实体,如果是模型的话,就可以获取到模型对应实体的name。底层是调用了driver.readPixels()方法来从渲染目标缓冲区中读取相应的像素信息,然后进行点击判断。

世界坐标转屏幕坐标

这部分的转换就是按照上面的渲染流程计算即可。

// 1、获取模型空间位置并将其转换为剪辑空间
vec4 clipSpacePos = projectionMatrix * (viewMatrix * vec4(point3D, 1.0));
// 2、从剪辑空间转换到标准化设备坐标空间(NDC 空间)
vec3 ndcSpacePos = clipSpacePos.xyz / clipSpacePos.w;
// 3、获取窗口位置
vec2 windowSpacePos = ((ndcSpacePos.xy + 1.0) / 2.0) * viewSize + viewOffset;

参考:https://stackoverflow.com/questions/8491247/c-opengl-convert-world-coords-to-screen2d-coords

矩阵运算

坐标转换离不开矩阵的运算,建议是再回头看看线性代数。。没时间系统的看的话,也可以先找一些网上的文章看看。以下几篇讲解的比较通俗,可以看看。
线性代数的秘密:矩阵相乘的本质是什么?
讲一点点数学:什么是矩阵?
线性代数的秘密:逆矩阵的意义是什么?(上)

模型矩阵,投影矩阵,视图矩阵的推导
OpenGL矩阵变换的数学推导-腾讯云开发者社区-腾讯云
屏幕坐标转世界坐标与射线生成

end

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/90195.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

idea开发Springboot出租车管理系统VS开发mysql数据库web结构java编程计算机网页源码maven项目

一、源码特点 springboot 出租车管理系统是一套完善的完整信息系统,结合springboot框架和bootstrap完成本系统,对理解JSP java编程开发语言有帮助系统采用springboot框架(MVC模式开发), 系统具有完整的源代码和数据…

(vue3)create-vue 组合式API

优势: 更易维护:组合式api,更好的TS支持 之前是选项式api,现在是组合式,把同功能的api集合式管理 复用功能封装成一整个函数 更快的速度 更小的体积 更优的数据响应式:Proxy create-vue 新的脚手架工…

计算机竞赛 深度学习OCR中文识别 - opencv python

文章目录 0 前言1 课题背景2 实现效果3 文本区域检测网络-CTPN4 文本识别网络-CRNN5 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 **基于深度学习OCR中文识别系统 ** 该项目较为新颖,适合作为竞赛课题方向,…

外汇天眼:外汇交易一周最佳外汇交易日!

外汇市场运行24小时,但并非每时每刻都适合交易。本文将为您介绍一周中最佳外汇交易日,以及哪些时间段最适合参与外汇交易。 首先,值得注意的是伦敦时段通常是外汇市场最繁忙的时段。然而,即便如此,一周中仍有特定的日…

c语言 - 实现每隔1秒向文件中写入当前系统时间

实现思路 主要是通过库函数和结构体获取当前系统时间(年月日和时分秒)保存到变量里,然后通过格式化输出函数将当前系统时间输出到文件中去。 但是需要注意的是题目要求每隔 1 s对系统时间进行输出,所以需要加入 sleep()函数进行调…

二、浏览器--事件循环(也叫事件环,也叫event loop)--任务队列(等待执行的任务(存放的定时器,http,事件等进程))--渲染三者的关系

引用B站视频,搜索标题:【事件循环】【前端】事件原理讲解,超级硬核,忍不住转载 本视频总结: 超级复杂的JS底层。事件循环和事件队列的关系。宏任务、微任务和raf回调这3个事件队列的关系。任务队列和执行栈的关系。d…

配置OSPFv3基本功能 华为笔记

1.1 实验介绍 1.1.1 关于本实验 OSPF协议是为IP协议提供路由功能的路由协议。OSPFv2(OSPF版本2)是支持IPv4的路由协议,为了让OSPF协议支持IPv6,技术人员开发了OSPFv3(OSPF版本3)。 无论是OSPFv2还是OSPFv…

设计模式2、抽象工厂模式 Abstract Factory

解释说明:提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类。 简言之,一个工厂可以提供创建多种相关产品的接口,而无需像工厂方法一样,为每一个产品都提供一个具体工厂 抽象工厂(Abstra…

学校安全用电管理系统解决方案

随着科技的发展和进步,电力已成为我们日常生活和学习的重要支柱。然而,电力的使用也带来了一定的安全风险。特别是对于学校这个复杂而又活跃的环境,安全用电管理系统的角色显得尤为重要。 一、学校用电管理系统的现状 目前&#xff0…

win10默认浏览器改不了怎么办,解决方法详解

win10默认浏览器改不了怎么办,解决方法详解_蓝天网络 在使用Windows 10操作系统时,你可能会遇到无法更改默认浏览器的情况。这可能是因为其他程序或设置正在干扰更改。如果你也遇到了这个问题,不要担心,本文将为你提供详细的解决…

CSS基础

目录 一.CSS介绍 三种CSS的写法 1.内部样式 2.内联样式 3.外部表示 二.CSS选择器 1.标签选择器 2.类选择器 ​编辑 3.ID选择器 ​编辑 4.后代选择器 ​编辑 5.子选择器 6.并集选择器 7.伪类选择器 三.CSS常用属性值 1.字体设置 2.文本属性 1.文字颜色 2.文…

华为云云耀云服务器L实例评测 | 实例使用教学之简单使用:通过命令行管理华为云云耀云服务器

华为云云耀云服务器L实例评测 | 实例使用教学之简单使用:通过命令行管理华为云云耀云服务器 介绍华为云云耀云服务器 华为云云耀云服务器 (目前已经全新升级为 华为云云耀云服务器L实例) 华为云云耀云服务器是什么华为云云耀云服务…

深入理解传输层协议:TCP与UDP的比较与应用

目录 前言什么是TCP/UDPTCP/UDP应用TCP和UDP的对比总结 前言 传输层是TCP/IP协议栈中的第四层,它为应用程序提供服务,定义了主机应用程序之间端到端的连通性。在本文章,我们将深入探讨传输层协议,特别是TCP和UDP协议的原理和区别…

在 .NET 8 Release Candidate 1 中推出 .NET MAUI:质量

作者:David Ortinau 排版:Alan Wang 今天,我们很高兴地宣布 .NET MAUI 在 .NET 8 Release Candidate 1 中已经可用,该版本带有适用于生产应用程序的正式许可证,因此您可以放心地将此版本用于生产环境。我们在 .NET 8 中…

IDEA 2019 Springboot 3.1.3 运行异常

项目场景&#xff1a; 在IDEA 2019 中集成Springboot 3.1.3 框架&#xff0c;运行异常。 <?xml version"1.0" encoding"UTF-8"?><project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSch…

C++之传指针、引用、vector<shared_ptr<string>>应用总结(二百三十三)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

Spring面试题13:Spring中ApplicationContext实现有哪些?Bean工厂和Applicationcontext有什么区别

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:Spring中ApplicationContext实现有哪些? 在Spring框架中,有以下几种ApplicationContext的实现: ClassPathXmlApplicationContext:从类路径下的…

算法通过村第十关-并归|黄金笔记|手撕并归排序

文章目录 前言并归排序的原理总结 前言 提示&#xff1a;有时我会担心你们发现我其实很普通。爱并不需要你与众不同。--查理麦克西《男孩、鼹鼠、狐狸和马》 并归排序算是经典的分治思想中的问题&#xff0c;这个非常典型的题目。 并归排序的原理 并归排序&#xff0c;简单来说…

Shiro高级及SaaS-HRM的认证授权

Shiro在SpringBoot工程的应用 Apache Shiro是一个功能强大、灵活的&#xff0c;开源的安全框架。它可以干净利落地处理身份验证、授权、企业会话管理和加密。越来越多的企业使用Shiro作为项目的安全框架&#xff0c;保证项目的平稳运行。 在之前的讲解中只是单独的使用shiro&…

成为吃鸡战场的王者!分享顶级战术干货,助您提高战斗力!

各位吃鸡战场的玩家们&#xff0c;欢迎来到本视频&#xff01;在这里&#xff0c;我将为您呈现一些与众不同的吃鸡干货&#xff0c;帮助您提高战斗力、轻松吃鸡&#xff01; 首先&#xff0c;让我们谈一谈作图工具推荐。绝地求生作图工具是吃鸡玩家们的必备利器。我将给大家推荐…