【Unity Shader】从NDC(归一化的设备坐标)坐标转换到世界坐标的数学原理
从NDC(归一化的设备坐标)坐标转换到世界坐标要点
参考资料
How to go from device coordinates back to worldspace http://feepingcreature.github.io/math.html
《Unity Shader入门精要》
前情提要,从运动模糊说起
产生运动模糊效果,一般来说有两种做法,第一种是将当前帧和下一帧或上一帧等等图像混合起来作为当前的屏幕图像,这样做法可以导致物体运动时会出现多个残影(因为多个帧混合起来了),可以产生运动模糊效果,但效率不高。
第二种做法是,在Shader里面利用View-Projection矩阵及其逆矩阵获得当前帧和上一帧的世界坐标,通过这两个坐标得到当前像素的运动速度及其方向,再根据这个速度,向这个像素速度方向的N个纹素进行取样并混合,从而产生模糊效果。
而这第二种做法,就是我遇到问题的地方。
总所周知,在Shader里面,可以根据深度图和当前uv坐标得到当前像素的NDC坐标,那么只要采用View-Projection(视图-裁剪)的逆矩阵就可以将NDC坐标变换到世界坐标下(正是我们所需要的值),按理说,这样应该就可以了,但是我在《Unity Shader入门精要》中看到的计算方法却是下面这样。
1 fixed4 frag(v2f i) : SV_Target{
2 // 从深度图中获得深度
3 float d = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv_depth);
4 // 根据深度和当前uv坐标反推当前NDC坐标(注意这个坐标已经经过了齐次除法了)
5 float4 NDCPos = float4(i.uv.x*2-1, i.uv.y*2-1, d*2-1,1);
6 // 根据NDC坐标及View-Projection的逆矩阵,将NDC坐标变换到世界坐标下
7 float4 worldPos = mul(_CurrentViewProjectionInverseMatrix,NDCPos);
8
9 worldPos /= worldPos.w;
....
....
....
}
其中第9行是我最疑惑的内容,按说,你进行屏幕映射要除个w分量进行齐次除法我可以理解,但是你从NDC坐标变换到世界坐标还要除于w是个什么理喔?
百思不得其解之下,翻了下作者的GitHub,嗯,终于找到了答案(感谢作者及评论区的小伙伴!!!)。
在 http://feepingcreature.github.io/math.html 中有详细的数学证明,下面我给翻译一下~~
数学推导过程
已知条件
首先考虑从世界坐标是如何变换到NDC坐标下的。
很显然,首先世界坐标是通过VP矩阵(不用MVP,因为这里已经是世界坐标了,不用在从模型空间变换到世界空剑侠了)变换到了裁剪空间下,数学公式如下:
在裁剪空间下,通过进行齐次除法将坐标变换到NDC坐标中,公式如下:
最后,第三个已知条件是,世界坐标下的w分量在Unity中定义通常都是1,那么就是下面这样:
分析问题
那么,我们的问题就变成了下面这样:
已知:
①
②
③
三个公式,给定一个NDC坐标和一个View-Projection矩阵,求得该NDC坐标所对应的世界坐标.
推导
第一步,反转公式③,如下所示:
④
第二步,根据公式2可得:
⑤
同时,又因为clip=(clipxyz,clipw),所以可以根据公式⑤,可得下面的公式:
⑥
根据公式④和⑥,可得下面的公式:
⑦
下面有个解释不是很懂~,原文如下:
And note that since matrices are linear transforms, we can pull that clip_w in front of the matrix multiply:
大致意思是说,因为矩阵是线性变化的,所以可以把clipw放到矩阵的前面.(老实说clipw不是标量么,放哪里应该都可以把?)
总之,经过上面原文的解释,公式⑦变成下面这样.
⑦
clip的w分量怎么得?
那么,一个比较严重的问题就出现了,clip坐标的w分量我们并不知道欸~~~我们已知的只有NDC坐标下的(X,Y,Z)分量(分别可以通过当前像素的uv值和深度算出来).
别急,已知条件不是还有一个没用么,就下面这个已知条件.
①
已知世界坐标的w分量恒为1,根据公式①、⑦,在只关注运算过程和结果的w分量的情况下,有下面这个公式:
⑧
那么,clip的w分量就经过公式⑧算出来了。
最终结果
那么,已知clipw,根据公式⑧和公式⑦,得到下面的公式⑨。
⑨
总结
根据公式⑨,就可以知道为什么最后我们还要除于w分量了~~~~~因为下面的分母就是w分量啊。。
【Unity Shader】从NDC(归一化的设备坐标)坐标转换到世界坐标的数学原理的更多相关文章
- Unity Shader学习笔记-1
本篇文章是对Unity Shader入门精要的学习笔记,插图大部分来自冯乐乐女神的github 如果有什么说的不正确的请批评指正 目录 渲染流水线 流程图 Shader作用 屏幕映射 三角形遍历 两大 ...
- 【Unity Shader】(六) ------ 复杂的光照(上)
笔者使用的是 Unity 2018.2.0f2 + VS2017,建议读者使用与 Unity 2018 相近的版本,避免一些因为版本不一致而出现的问题. [Unity Sha ...
- 【Unity Shader】(七) ------ 复杂的光照(下)
笔者使用的是 Unity 2018.2.0f2 + VS2017,建议读者使用与 Unity 2018 相近的版本,避免一些因为版本不一致而出现的问题. [Unity Sha ...
- 《Unity shader入门精要》复习<第13章 关于NDC坐标和深度/法线纹理>
分为三个地方讲解. NDC(Normalize Device Coordinates)归一化的设备坐标 NDC坐标是世界空间坐标通过MVP变换之后再进行归一化得到的坐标.只需要再一步变换就能得到屏幕空 ...
- Unity Shader入门精要学习笔记 - 第4章 学习 Shader 所需的数学基础
摘录自 冯乐乐的<Unity Shader入门精要> 笛卡尔坐标系 1)二维笛卡尔坐标系 在游戏制作中,我们使用的数学绝大部分都是计算位置.距离.角度等变量.而这些计算大部分都是在笛卡尔坐 ...
- Unity Shader入门精要学习笔记 - 第2章 渲染流水线
来源作者:candycat http://blog.csdn.net/candycat1992/article/ 2.1 综述 渲染流水线的最终目的在于生成或者说是渲染一张二维纹理,即我们在电脑屏 ...
- Unity Shader入门精要读书笔记(一)序章
本系列的博文是笔者读<Unity Shader入门精要>的读书笔记,这本书的章节框架是: 第一章:着手准备. 第二章:GPU流水线. 第三章:Shader基本语法. 第四章:Shader数 ...
- Unity Shader入门精要学习笔记 - 第13章 使用深度和法线纹理
线纹理的代码非常简单,但是我们有必要在这之前首先了解它们背后的实现原理. 深度纹理实际上就是一张渲染纹理,只不过它里面存储的像素值不是颜色值而是一个高精度的深度值.由于被存储在一张纹理中,深度纹理里的 ...
- 《Unity Shader入门精要》读书笔记(1)
主要是对第二章的整理 渲染流水线:由一个三维场景出发,生成(渲染)一张二维图像. 渲染流程:应用阶段.几何阶段.光栅化阶段. 应用阶段: 1. 把数据加载到显存中 渲染所需数据从硬盘,到内存,再到显存 ...
随机推荐
- Web Services 根据wsdl生成代理类
生成代理类步骤: 一:找到Visual Studio 的工具文件夹 二:用管理员方式打开本机工具命令提示 三:输入要执行的脚本 wsdl /language:C# /n:xxxx.HermesMobi ...
- TiDB数据库 mydumper与loader导入数据
从mysql导出数据最好的方法是使用tidb官方的工具mydumper. 导入tidb最好的方法是使用loader工具,大概19.4G每小时的速度. 详细的步骤可以参考官网:https://pingc ...
- Jenkins 基于 Docker git JAVA CI/CD
准备两台机器 192.168.31.200 centos7 docker harbor git 192.168.31.201 centos7 docker jenkins maven git Ha ...
- C++第六次作业
前言 拿到作业的时候,整个人都不好了,虽然之前和同学说以后一起写游戏,画界面,然而现在的自己对界面的知识一窍不通,虽然同学分享了一些资料,但是通过这次作业,发现自己火候还是不够-- 问题描述及仓库地址 ...
- SDN期末
一.项目描述 负载均衡程序 二.小组分工 组名:我们真的很弱 组员:李佳铭.吴森杰.张岚鑫.薛宇涛.杨凌澜 三.代码演示及过程描述 四.课程总结
- .Net Core Api 跨域配置
.Net Core 和Asp.Net 不同,不需要再去引用其他的跨域组件.创建项目时,就有了. 让接口实现跨域,需要配置两个地方. 一.Startup.cs 这里需要配置两个地方 public voi ...
- 联想笔记本BIOS设置中文详解
对于很多新装系统的小伙伴们 可能很多都不是太懂BIOS中都是干什么用的,小编这里给大家详细介绍一下 联想笔记本的主板BIOS设置跟别的笔记本或许有些不同但大体相差不多,和大家分享一下. BIOS介绍 ...
- Linux命令一览
Linux系统中的命令参数有长短格式之分,长格式和长格式之间不能合并,长格式和短格式之间也不能合并,但短格式和短格式之间是可以合并的,合并后仅保留一个-(减号)即可. echo命令:用于在终端输出字符 ...
- 2-3 R语言基础 矩阵和数组
#矩阵Matrix 三个参数:内容(可省),行数,列数 > x <- matrix(1:6,nrow = 3,ncol = 2) #第一个是内容,第二个,第三个是行列> x[1,2 ...
- Android友盟推送
当前版本号:v3.0.5 1.下载SDK解压并导入(import module,compile project(':PushSDK')),里面有demo,用demo的包名去官网添加一个应用,然后替换d ...