Unity中Shader裁剪空间推导(透视相机到裁剪空间的转化矩阵)

文章目录

  • 前言
  • 一、简单看一下 观察空间—>裁剪空间—>屏幕空间 的转化
    • 1、观察空间(右手坐标系、透视相机)
    • 2、裁剪空间(左手坐标系、且转化为了齐次坐标)
    • 3、屏幕空间(把裁剪坐标归一化设置)
    • 4、从观察空间到裁剪空间
    • 5、从裁剪空间到屏幕空间后
  • 二、透视相机的参数推导
    • 1、从XoY平面,求出X~v~从观察空间到裁剪空间的坐标投影 X~p~
    • 2、从YoZ平面,求出Y~v~从观察空间到裁剪空间的坐标投影 Y~p~
  • 三、把投影到近裁剪面的坐标 归一化设置
    • 1、求归一化设置后的 x~n~
    • 2、求归一化设置后的 y~n~
    • 3、得到最后化简的公式
  • 四、构建转化矩阵
    • 1、在OpenGL[-1,1]下:
    • 2、在DirectX[1,0]下:
    • 3、把A、B代入矩阵得


前言

我们把顶点坐标信息转化为裁剪空间。有可能使用到正交相机信息 或 透视相机。我们在这篇文章中,推导一下透视相机视图空间下的坐标转化到裁剪空间的矩阵。

在这里插入图片描述


一、简单看一下 观察空间—>裁剪空间—>屏幕空间 的转化

在这里插入图片描述

1、观察空间(右手坐标系、透视相机)

在这里插入图片描述

2、裁剪空间(左手坐标系、且转化为了齐次坐标)

在这里插入图片描述

3、屏幕空间(把裁剪坐标归一化设置)

在这里插入图片描述

4、从观察空间到裁剪空间

用透视投影矩阵先转化到裁剪空间
然后,在转化为齐次坐标

5、从裁剪空间到屏幕空间后

− 1 ≤ x c w ≤ 1 -1 \leq \frac{x_c}{w}\leq1 1wxc1

− w ≤ x c ≤ w -w \leq x_c\leq w wxcw


二、透视相机的参数推导

在这里插入图片描述

  • 我们对于远裁剪面只是已知 f,其他参数都是未知

1、从XoY平面,求出Xv从观察空间到裁剪空间的坐标投影 Xp

在这里插入图片描述

  • 点 V 是观察空间下的模型顶点,xyz是已知的
    已知: ( x v , y v , z v ) 、 − n (x_v,y_v,z_v) 、 -n (xv,yv,zv)n
  • 点P是该点在近裁剪面上的投影点,xyz是未知的
    未知: ( x p , y p , z p ) (x_p,y_p,z_p) (xp,yp,zp)
  • 我们在 XoZ平面上,能求的就是 xp
    求: x p x_p xp

z p = − n z_p = -n zp=n

y p 在 X o Z 平面下,无法计算 y_p 在XoZ平面下,无法计算 ypXoZ平面下,无法计算

  • v点向Z轴做垂线,原点连接v点,围成的两个三角形相似,可得:

x p x v = − n z v \frac{x_p}{x_v} = \frac{-n}{z_v} xvxp=zvn

x p = − n z v x v x_p = \frac{-n}{z_v} x_v xp=zvnxv

P = ( − n z v x v , 未知 , − n ) P = (\frac{-n}{z_v}x_v,未知,-n) P=(zvnxv,未知,n)

2、从YoZ平面,求出Yv从观察空间到裁剪空间的坐标投影 Yp

在这里插入图片描述

  • 点 V 是观察空间下的模型顶点,xyz是已知的
    已知: ( x v , y v , z v ) 、 − n (x_v,y_v,z_v) 、 -n (xv,yv,zv)n
  • 点P是该点在近裁剪面上的投影点,xyz是未知的
    未知: ( x p , y p , z p ) (x_p,y_p,z_p) (xp,yp,zp)
  • 我们在 YoZ平面上,能求的就是 yp
    求: y p y_p yp

z p = − n z_p = -n zp=n

x p 在 X o Z 平面下,无法计算 x_p 在XoZ平面下,无法计算 xpXoZ平面下,无法计算

  • v点向Z轴做垂线,原点连接v点,围成的两个三角形相似,可得:

y p y v = − n z v \frac{y_p}{y_v} = \frac{-n}{z_v} yvyp=zvn

y p = − n z v y v y_p = \frac{-n}{z_v} y_v yp=zvnyv

P = ( − n z v x v , − n z v y v , − n ) P = (\frac{-n}{z_v}x_v,\frac{-n}{z_v} y_v,-n) P=(zvnxv,zvnyv,n)


三、把投影到近裁剪面的坐标 归一化设置

P = ( − n z v x v , − n z v y v , − n ) P = (\frac{-n}{z_v}x_v,\frac{-n}{z_v} y_v,-n) P=(zvnxv,zvnyv,n)

化到[-1,1]之间
具体参考Unity中Shader裁剪空间推导(正交相机到裁剪空间的转化矩阵)

1、求归一化设置后的 xn

  • l ≤ x ≤ r l \leq x \leq r lxr 化为: − 1 ≤ 2 x w ≤ 1 -1 \leq \frac{2x}{w} \leq 1 1w2x1

− 1 ≤ − 2 n x v z v w ≤ 1 -1\leq \frac{-2nx_v}{z_vw}\leq 1 1zvw2nxv1

− 1 ≤ − 2 n w ⋅ x v z v ≤ 1 -1\leq \frac{-2n}{w}·\frac{x_v}{z_v}\leq 1 1w2nzvxv1

2、求归一化设置后的 yn

  • l ≤ y ≤ r l \leq y \leq r lyr 化为: − 1 ≤ 2 y h ≤ 1 -1 \leq \frac{2y}{h} \leq 1 1h2y1

− 1 ≤ − 2 n y v z v h ≤ 1 -1\leq\frac{-2ny_v}{z_vh}\leq1 1zvh2nyv1

− 1 ≤ − 2 n h ⋅ y v z v ≤ 1 -1\leq\frac{-2n}{h}·\frac{y_v}{z_v}\leq1 1h2nzvyv1

3、得到最后化简的公式

由于NDC下的坐标由透视除法而得
我们假设透视除法中的 w 为 -zv
还原到裁剪空间还需要乘以 -zv

  • X:

− 1 ≤ − 2 n w ⋅ x v z v ≤ 1 -1\leq \frac{-2n}{w}·\frac{x_v}{z_v}\leq 1 1w2nzvxv1

x n = − 2 n w x v z v x_n = \frac{-2n}{w}\frac{x_v}{z_v} xn=w2nzvxv

− x n z v = 2 n w x v -x_nz_v = \frac{2n}{w}x_v xnzv=w2nxv

  • Y:

− 1 ≤ − 2 n h ⋅ y v z v ≤ 1 -1\leq\frac{-2n}{h}·\frac{y_v}{z_v}\leq1 1h2nzvyv1

y n = − 2 n h y v z v y_n = \frac{-2n}{h}\frac{y_v}{z_v} yn=h2nzvyv

− y n z v = 2 n h y v -y_n z_v= \frac{2n}{h}y_v ynzv=h2nyv

  • Z:

z n = ? z_n = ? zn=?

− z n z v = − z v ? -z_nz_v = -z_v? znzv=zv?

  • W:

w = 1 w = 1 w=1

− w n z v = − z v -w_nz_v = -z_v wnzv=zv


四、构建转化矩阵

裁剪空间下的点 = 观察空间下的基向量 在 裁剪空间下的矩阵 * 点在观察空间下的坐标

P c = [ V c ] ⋅ P v P_c = [V_c]·P_v Pc=[Vc]Pv

P c = [ C v ] − 1 ⋅ P v P_c = [C_v]^{-1}·P_v Pc=[Cv]1Pv

P c = [ C v ] T ⋅ P v P_c = [C_v]^{T}·P_v Pc=[Cv]TPv

  • − x n z v = 2 n w x v -x_nz_v = \frac{2n}{w}x_v xnzv=w2nxv
  • − y n z v = 2 n h y v -y_n z_v= \frac{2n}{h}y_v ynzv=h2nyv
  • − z n z v = − z v ? -z_nz_v = -z_v? znzv=zv?
  • − w n z v = − z v -w_nz_v = -z_v wnzv=zv

[ 2 v w 0 ? ? 0 2 n h ? ? 0 0 ? ? 0 0 ? ? ] T = [ 2 v w 0 0 0 0 2 n h 0 0 ? ? ? ? ? ? ? ? ] \begin{bmatrix} \frac{2v}{w} & 0 & ? &?\\ 0 & \frac{2n}{h} & ? &?\\ 0 & 0 & ? &?\\ 0 & 0 & ? & ?\\ \end{bmatrix}^T =\begin{bmatrix} \frac{2v}{w} & 0 & 0 & 0 \\ 0 & \frac{2n}{h} & 0 &0\\ ? & ? & ? &?\\ ? & ? & ? & ?\\ \end{bmatrix} w2v0000h2n00???????? T= w2v0??0h2n??00??00??

[ 2 v w 0 0 0 0 2 n h 0 0 ? ? ? ? ? ? ? ? ] ⋅ [ x v y v z v 1 ] = ( − x n z v , − y n z v , − z n z v , − w n z v ) \begin{bmatrix} \frac{2v}{w} & 0 & 0 & 0 \\ 0 & \frac{2n}{h} & 0 &0\\ ? & ? & ? &?\\ ? & ? & ? & ?\\ \end{bmatrix} · \begin{bmatrix} x_v\\ y_v\\ z_v\\ 1\\ \end{bmatrix} = (-x_nz_v,-y_nz_v,-z_nz_v,-w_nz_v) w2v0??0h2n??00??00?? xvyvzv1 =(xnzv,ynzv,znzv,wnzv)

最后一行由于相乘结果为1可以得出,把最后未知部分设为A,B
[ 2 v w 0 0 0 0 2 n h 0 0 0 0 A B 0 0 − 1 0 ] ⋅ [ x v y v z v 1 ] \begin{bmatrix} \frac{2v}{w} & 0 & 0 & 0 \\ 0 & \frac{2n}{h} & 0 &0\\ 0 & 0 & A &B\\ 0 & 0 & -1 & 0\\ \end{bmatrix} · \begin{bmatrix} x_v\\ y_v\\ z_v\\ 1\\ \end{bmatrix} w2v0000h2n0000A100B0 xvyvzv1

z c = A z v + B z_c = Az_v+B zc=Azv+B

− z n z v = − z v -z_nz_v = -z_v znzv=zv

z c − z v = A z v + B − z v \frac{z_c}{-z_v} = \frac{Az_v+B}{-z_v} zvzc=zvAzv+B

z n = A z v + B − z v z_n = \frac{Az_v+B}{-z_v} zn=zvAzv+B

1、在OpenGL[-1,1]下:

z n = A z v + B − z v z_n = \frac{Az_v+B}{-z_v} zn=zvAzv+B

{ z v = − n , z n = − 1 z v = − f , z n = 1 \begin{cases} z_v = -n,z_n=-1 \\ z_v = -f,z_n = 1 \end{cases} {zv=n,zn=1zv=f,zn=1

{ − 1 = − A n + B n 1 = − A f + B f \begin{cases} -1 = \frac{-An+B}{n}\\ 1 = \frac{-Af + B}{f} \end{cases} {1=nAn+B1=fAf+B

{ − n = − A n + B f = − A f + B \begin{cases} -n = -An+B\\ f = -Af + B \end{cases} {n=An+Bf=Af+B

B = A n − n B = An - n B=Ann

f = − A f + A n − n f = -Af +An-n f=Af+Ann

f + n = A ( n − f ) f + n= A(n-f) f+n=A(nf)

A = n + f n − f A = \frac{n+f}{n-f} A=nfn+f

B = n + f n − f n − n B = \frac{n+f}{n-f}n-n B=nfn+fnn

B = n 2 + f n n − f n 2 − n f n − f B = \frac{n^2 + fn}{n-f}\frac{n^2-nf}{n-f} B=nfn2+fnnfn2nf

B = 2 n f n − f B = \frac{2nf}{n-f} B=nf2nf

2、在DirectX[1,0]下:

z n = A z v + B − z v z_n = \frac{Az_v+B}{-z_v} zn=zvAzv+B

{ z v = − n , z n = 1 z v = − f , z n = 0 \begin{cases} z_v = -n,z_n=1 \\ z_v = -f,z_n = 0 \end{cases} {zv=n,zn=1zv=f,zn=0

{ 1 = − A n + B n 0 = − A f + B f \begin{cases} 1 = \frac{-An+B}{n}\\ 0 = \frac{-Af+B}{f} \end{cases} {1=nAn+B0=fAf+B

{ n = − A n + B 0 = − A f + B \begin{cases} n = -An+B\\ 0 = -Af+B \end{cases} {n=An+B0=Af+B

B = A f B = Af B=Af

n = − A n + A f n = -An+Af n=An+Af

n = A ( f − n ) n = A(f-n) n=A(fn)

A = n f − n A =\frac{n}{f-n} A=fnn

B = n f f − n B = \frac{nf}{f-n} B=fnnf

3、把A、B代入矩阵得

  • OpenGL
    [ 2 v w 0 0 0 0 2 n h 0 0 0 0 n + f n − f 2 n f n − f 0 0 − 1 0 ] \begin{bmatrix} \frac{2v}{w} & 0 & 0 & 0 \\ 0 & \frac{2n}{h} & 0 &0\\ 0 & 0 & \frac{n+f}{n-f} &\frac{2nf}{n-f}\\ 0 & 0 & -1 & 0\\ \end{bmatrix} w2v0000h2n0000nfn+f100nf2nf0
  • DirectX
    [ 2 v w 0 0 0 0 2 n h 0 0 0 0 n f − n n f f − n 0 0 − 1 0 ] \begin{bmatrix} \frac{2v}{w} & 0 & 0 & 0 \\ 0 & \frac{2n}{h} & 0 &0\\ 0 & 0 & \frac{n}{f-n} &\frac{nf}{f-n}\\ 0 & 0 & -1 & 0\\ \end{bmatrix} w2v0000h2n0000fnn100fnnf0

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

android studio 将含有jni c++ 的library项目封装成jar并调用

请参考博客:android studio 4.1.1 将library项目封装成aar 并调用_android studio 4.1 aar release-CSDN博客 一 . 简单叙述 android studio 中可以创建Module 的两种属性,可以在build.gradle 中查看: 1. application属性:可以独…

字符串转换tuple对象

给定“前导空格分隔的元组字符串”,还原成合法的python元组tuple对象。 (笔记模板由python脚本于2023年12月29日 19:29:03创建,本篇笔记适合熟悉Python元组tuple的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网:https://www.python.org…

腾讯云标准型S5服务器4核8G配置优惠价格表

腾讯云4核8G服务器S5和轻量应用服务器优惠价格表,轻量应用服务器和CVM云服务器均有活动,云服务器CVM标准型S5实例4核8G配置价格15个月1437.3元,5年6490.44元,轻量应用服务器4核8G12M带宽一年446元、529元15个月,腾讯云…

docker入门概念详解

本篇文章对docker的一些基础概念和周边概念进行了详细解释。帮助你可以很好的理解docker是用来干什么的,docker是怎么工作的。其中有docker所运用到的技术解释,docker的不同发展版本,dokcer的架构,docker的生态等等详解。希望本片…

Django 文件上传(十二)

当 Django 处理文件上传时,文件数据最终会被放置在 request.FILES 。 查看文档:文件上传 | Django 文档 | Django Django工程如下: 创建本地存储目录 在static/应用目录下创建uploads目录用于存储接收上传的文件 在settings.py 配置静态目…

Shell脚本-bin/bash: 解释器错误: 没有那个文件或目录-完整路径执行-“/”引发的脑裂

引起该不适的一种可能以及解决方案,网上较多,比如: 但按以上方式操作,并经过查看,发现仍然未能解决问题。 因为两种方式执行,有一种能成功,有一种不能,刚开始未怀疑是文件问题&…

写实风格3D模型材质贴图

在线工具推荐: 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 写实3D模型的制作过程包括建模、材质贴图、灯光设置和渲染等步骤。首…

ViT的极简pytorch实现及其即插即用

先放一张ViT的网络图 可以看到是把图像分割成小块,像NLP的句子那样按顺序进入transformer,经过MLP后,输出类别。每个小块是16x16,进入Linear Projection of Flattened Patches, 在每个的开头加上cls token和位置信息,…

【软件测试】为bug而生

为什么定位问题如此重要? 可以明确一个问题是不是真的“bug” 很多时候,我们找到了问题的原因,结果发现这根本不是bug。原因明确,误报就会降低多个系统交互,可以明确指出是哪个系统的缺陷,防止“踢皮球”&…

【23.12.29期--Redis缓存篇】谈一谈Redis的集群模式

谈一谈Redis的集群模式 ✔️ 谈一谈Redis的集群模式✔️主从模式✔️ 特点✔️Redis主从模式Demo ✔️哨兵模式✔️Redis哨兵模式Demo✔️特点 ✔️Cluster模式✔️Redis Cluster模式Demo✔️特点 ✔️ 谈一谈Redis的集群模式 Redis有三种主要的集群模式,用于在分布…

电气产品外壳常用材质PA、PC、PBT、ABS究竟是什么?

在如今工业制造领域,各种改性塑料、复合材料以及轻质合金材料的运用日趋成熟。在电气领域,不同电气产品的外壳、组件材质采用不同材料,以同为科技(TOWE)电气产品为例,工业连接器系列产品采用PA6外壳材质、机…

【SD】一致性角色 - 表情差异生成 【1】

原理:通过segment 局部重绘 可以根据lora 产生面部表情图片 模型:sam_vit_h_4b8939.pth 导入图片到segment 开启:Enable GroundingDINO GroundingDINO Detection Prompt :输入 face 然后点击:Preview Segmentation …

如何文件从电脑传到iPhone,这里提供几个方法

本文介绍了如何使用Finder应用程序、iTunes for Windows、iCloud和谷歌照片将照片从Mac或PC传输到iPhone。 如何将照片从Mac传输到iPhone 如果你有一台Mac电脑,里面装满了你想转移到iPhone的照片,这是一件非常简单的事情。只需遵循以下步骤&#xff1a…

LIUNX进程程序替换

1.什么是程序替换 a.一个程序,只能执行自己的代码 b.如果想要一个程序执行,别的程序的代码呢? 我们就可以创建一个子进程,将这个子进程替换为我们想要执行的程序。 2.样例代码-----execl(接口) 返回值&…

跨进程通信 macOS XPC 创建实例

一:简介 XPC 是 macOS 里苹果官方比较推荐和安全的的进程间通信机制。 集成流程简单,但是比较绕。 主要需要集成 XPC Server 这个模块,这个模块最终会被 apple 的根进程 launchd 管理和以独立进程的方法唤起和关闭, 我们主app 进…

交叉编译aarch64架构支持openssl的curl、libcurl

本文档旨在指导读者在x86_64平台上交叉编译curl和openssl库以支持aarch64架构。在开始之前,请确保您的系统环境已正确配置。 1. 系统环境准备 系统是基于Ubuntu 20.04 LTS,高版本可能会有问题。首页,安装必要的开发工具和库文件。打开终端并…

QML 怎么调用 C++ 中的内容?

以下内容为本人的学习笔记,如需要转载,请声明原文链接 微信公众号「ENG八戒」https://mp.weixin.qq.com/s/z_JlmNe6cYldNf11Oad_JQ 先说明一下测试环境 编译器:vs2017x64 开发环境:Qt5.12 这里主要是总结一下,怎么在…

Java——猫猫图鉴微信小程序(前后端分离版)

目录 一、开源项目 二、项目来源 三、使用框架 四、小程序功能 1、用户功能 2、管理员功能 五、使用docker快速部署 六、更新信息 审核说明 一、开源项目 猫咪信息点-ruoyi-cat: 1、一直想做点项目进行学习与练手,所以做了一个对自己来说可以完成的…

MFC随对话框大小改变同时改变控件大小

先看一下效果; 初始; 窗口变大,控件也变大; 二个也可以; 窗口变大,控件变大; 默认生成的对话框没有WM_SIZE消息的处理程序;打开类向导,选中WM_SIZE消息,对CxxxDlg类添加该消息的处理程序;默认生成的函数名是OnSize; 添加了以后代码中会有三处变化; 在对话框类的…

嵌入式SOC之通用图像处理之OSD文字信息叠加的相关实践记录

机缘巧合 机缘巧合下, 在爱芯元智的xx开发板下进行sdk的开发.由于开发板目前我拿到是当前最新的一版(估计是样品),暂不公开开发板具体型号信息.以下简称板子 .很多优秀的芯片厂商,都会提供与开发板配套的完善的软件以及完善的技术支持(FAE),突然觉得爱芯…