【转载】3D/2D中的D3DXMatrixPerspectiveFovLH和D3DXMatrixOrthoLH投影函数详解
原文:3D/2D中的D3DXMatrixPerspectiveFovLH和D3DXMatrixOrthoLH投影函数详解
3D中z值会影响屏幕坐标系到世界坐标系之间的转换,2D中Z值不会产生影响(而只是屏幕宽高比会产生影响,z值只对深度剔除产生影响)。所以U3D中如果用2D摄像机那么屏幕坐标和世界坐标之间的转换需要用指定的2D摄像机才行,如果用主3D摄像机那么UI转换会产生计算结果异常。
一、D3DXMatrixPerspectiveFovLH函数
作用:Builds a left-handed perspective projection matrix based on a field of view.获得指定参数的透视投影矩阵,用于3D投影变换。
使用:
D3DXMATRIX proj;
D3DXMatrixPerspectiveFovLH(
&proj,
D3DX_PI * 0.5f, // 90 - degree
(float)Width / (float)Height,
1.0f,
1000.0f);
Device->SetTransform(D3DTS_PROJECTION, &proj); // 设置变换矩阵和状态,没有真正开始变换,提交后交给图形硬件
1.镜头平移:改变cameraPos用来计算观察位置
2.镜头拉近拉远缩放物体对象:
1).设置观察点的位置,cameraPos用来计算观察位置(没有忽略z值故可以)。
2) fovy z轴和zy上斜线之间夹角变小,那么物体也会变大(aspect不能随便变换否则就不等比例了)。
3.镜头拉高拉低:
1)cameraPos来拉高,y变就可以了。
原型:
D3DXMATRIX* D3DXMatrixPerspectiveFovLH(
_Inout_ D3DXMATRIX *pOut,
_In_ FLOAT fovy,
_In_ FLOAT aspect,
_In_ FLOAT zn,
_In_ FLOAT zf
);
pOut:透视变换矩阵,将视锥内的物体变换到(-1,-1,-1)->(1,1,1)的正方体内。
fovy:视锥体的上下夹角(6面体),z轴平分该夹角。
当fovy变小时候,因为也要在屏幕90度中用,所以高度方向被放大了,反之fovy变大,高度方向变小。
aspect:aspect = w / h,fovy = 90度,由投影矩阵的计算过程,投影yScale = cot(fovy/2); xScale = yScale /aspect.
当屏幕w:h = 100:20时,当aspect = 5:1,那么视锥内的[5,1]正方形截面世界将被变换映射到(1,1)的平面内,
xScale压缩了1/5,当透视投影映射到屏幕坐标时候[5,1],xScale方向需要根据屏幕放大5倍,这样视锥体里面的世界等比缩放到屏幕。
当aspect = 1变小;那么yScale = 1, xScale = 1,视锥体内的xy正方形截面[1,1]世界被放置到(1,1); 映射到屏幕为[5,1]xScale映射到屏幕被放大了5倍,yScale不变。
当aspect = 10变大,那么yScale = 1,xScale = 1/10,视锥体内的xy正方形截面[10,1]世界->(1,1)->[5,1],xScale被缩小了2倍,yScale不变。
zn,zf:z近裁剪面,z远裁剪面,z视锥体depth深度的改变,映射到屏幕上,也是zn深度变大了,那么屏幕上物体变小了,zn深度变小了,那么屏幕上物体将变大。
变换矩阵:
xScale 0 0 0
0 yScale 0 0
0 0 zf/(zf-zn) 1
0 0 -zn*zf/(zf-zn) 0
where:
yScale = cot(fovY/2) xScale = yScale / aspect ratio
yScale是根据视锥夹角求得的,xScale由屏幕大小来设置等于xScale = yScale / aspect = yScale * h / w,也就是希望: xScale /yScale = h / w.即当yScale = 1时,屏幕w/h = 4/3。那么xScale的缩放比例为 3 / 4,就是是cot(fovX / 2)更小,fovX越大投影的点越多;当xScale更小,除以w = z后,那么[-1,1]的设备坐标系x范围内可以放入更多的点,当转换到屏幕坐标系时,x方向的点放大为y方向放大的4/3, 所以x方向和y方向的缩放比例为1:1,也就是等比的缩放不会导致问题,主要的缩放来自于fovY视锥夹角,和摄像机位置。
也就是说xScale = yScale / aspect ratio是英明的公式,保证了等比缩放,而和真正的缩放分离了。
z轴方向的zf/(zf-zn)是对1/z插值的常数部分, -zn*zf/(zf-zn)是对1/z插值的系数部分。
m31 = 1是最隐秘的雕虫小技。
二、D3DXMatrixOrthoLH函数
作用:生成一个左手坐标系正交投影矩阵,用于视图坐标到投影坐标系的2D转换。
使用:
D3DXMatrix mOrtho
D3DXMatrixOrthoLH(&mOrtho, WINDOW_WIDTH, WINDOW_HEIGHT, 0.1f, 1000.0f);
g_pd3dDevice->SetTransform(D3DTS_PROJECTION,&mOrtho); // 设置变换矩阵和状态,没有真正开始变换,提交后交给图形硬件实现变换
1.镜头平移:改变cameraPos用来计算观察位置
2.镜头拉近放大物体对象:
1).Z深度值被丢弃了,可以通过放大屏幕投影来变大,那么需要放大正交投影的值,因为正交投影后2/w、2/h,所以可以通过缩小正交投影传入的w、h来实现放大;放大传入的w、h可以实现模拟的远离。
3.镜头拉高拉低:
1)cameraPos,y值变大来拉高;通过放大传入的w、h可以实现模拟的远离缩小。
原型:
D3DXMATRIX* D3DXMatrixOrthoLH(
_Inout_ D3DXMATRIX *pOut, // 输出的变幻矩阵
_In_ FLOAT w, // 屏幕的宽度
_In_ FLOAT h, // 屏幕的高度
_In_ FLOAT zn, // z深度缓存最小值
_In_ FLOAT zf // z深度缓存最大值
);
得到的变换矩阵为:
2/w 0 0 0
0 2/h 0 0
0 0 1/(zf-zn) 0
0 0 zn/(zn-zf) 1
2D正交变换将摄像机坐标空间里面的点变换到设备规范化坐标空间中
2/w,2/h对摄像机空间内的x,y进行正交投影,进行了一定的缩放,当w,h越大那么缩小越大,设备规范化坐标系内[-1,1]容纳的像素就越多,变换到屏幕坐标系中就感觉远离缩小了。z轴空间上是对z进行了线性插值,使得z值在[0,1]空间内,zn时候为0,zf时候为1(深度缓存用于遮挡剔除深度测试,和stencil测试)。
参考:
http://msdn.microsoft.com/en-us/library/windows/desktop/bb205350%28v=vs.85%29.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/bb204940%28v=vs.85%29.aspx
【转载】3D/2D中的D3DXMatrixPerspectiveFovLH和D3DXMatrixOrthoLH投影函数详解的更多相关文章
- 【转载】C++中替代sprintf的std::ostringstream输出流详解
一.简单介绍 ostringstream是C++的一个字符集操作模板类,定义在sstream.h头文件中.ostringstream类通常用于执行C风格的串流的输出操作,格式化字符串,避免申请大量的缓 ...
- pycaffe︱caffe中fine-tuning模型三重天(函数详解、框架简述)
本文主要参考caffe官方文档[<Fine-tuning a Pretrained Network for Style Recognition>](http://nbviewer.jupy ...
- 【python】Numpy中stack(),hstack(),vstack()函数详解
转自 https://blog.csdn.net/csdn15698845876/article/details/73380803 这三个函数有些相似性,都是堆叠数组,里面最难理解的应该就是stack ...
- Numpy中stack(),hstack(),vstack()函数详解
一`.stack 按指定维度堆叠数组. stack(a, b) 维度计算 axis=0: 2*m*n axis=1: m*2*n axis=-1: m*n*2 a = np.arange( ...
- Linux中fork()函数详解(转载)
linux中fork()函数详解 一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事, ...
- malloc 与 free函数详解<转载>
malloc和free函数详解 本文介绍malloc和free函数的内容. 在C中,对内存的管理是相当重要.下面开始介绍这两个函数: 一.malloc()和free()的基本概念以及基本用法: 1 ...
- 单元测试系列之四:Sonar平台中项目主要指标以及代码坏味道详解
更多原创测试技术文章同步更新到微信公众号 :三国测,敬请扫码关注个人的微信号,感谢! 原文链接:http://www.cnblogs.com/zishi/p/6766994.html 众所周知Sona ...
- 连接池中的maxIdle,MaxActive,maxWait等参数详解
转: 连接池中的maxIdle,MaxActive,maxWait等参数详解 2017年06月03日 15:16:22 阿祥小王子 阅读数:6481 版权声明:本文为博主原创文章,未经博主允许不得 ...
- [转载,感觉写的非常详细]DUBBO配置方式详解
[转载,感觉写的非常详细]DUBBO配置方式详解 原文链接:http://www.cnblogs.com/chanshuyi/p/5144288.html DUBBO 是一个分布式服务框架,致力于提供 ...
随机推荐
- P2668 斗地主
题目描述 牛牛最近迷上了一种叫斗地主的扑克游戏.斗地主是一种使用黑桃.红心.梅花.方片的AAA到KKK加上大小王的共545454张牌来进行的扑克牌游戏.在斗地主中,牌的大小关 系根据牌的数码表示如下: ...
- programming-languages学习笔记--第3部分
programming-languages学习笔记–第3部分 */--> pre.src {background-color: #292b2e; color: #b2b2b2;} pre.src ...
- 25、springboot与缓存整合Redis
默认使用ConcurrentMapCacheManager 将数据保存在下面的Map中 docker: 安装Redis: 查看官方文档: 添加约束 <dependency> <gro ...
- leetcode 1.Two Sum 、167. Two Sum II - Input array is sorted 、15. 3Sum 、16. 3Sum Closest 、 18. 4Sum 、653. Two Sum IV - Input is a BST
1.two sum 用hash来存储数值和对应的位置索引,通过target-当前值来获得需要的值,然后再hash中寻找 错误代码1: Input:[3,2,4]6Output:[0,0]Expecte ...
- Python自动化之Django中间件
django中间件 Django请求生命周期 中间件中可以定义方法,分别是 process_request(self,request) process_view(self, request, call ...
- 安装Centos 7 错误解决
dracut-initqueue[624]:Warning: Could not boot. dracut-initqueue[624]:Warning: /dev/root does not exi ...
- LORA芯片SX1272IMLTRT资料介绍
升特公司(Semtech)(纳斯达克:SMTC)日前推出新型远程RFIC平台的首款产品SX1272,可将器件的无线传输距离扩大至15公里. 该器件集成了升特公司的新型LoRa(远程)调制技术,相比其他 ...
- Gradle Goodness: Display Available Tasks
To see which tasks are available for our build we can run Gradle with the command-line option -t or ...
- 允许跨域资源共享(CORS)携带 Cookie (转载)
如何让CORS携带Cookie CORS 是一个 W3C 标准,全称是“跨域资源共享”(Cross-origin resource sharing).默认浏览器为了安全,遵循“同源策略”,不允许 Aj ...
- iOS:时间相关(18-10-13更)
先整理出时间相关的程序,以后有空再写成单例. 1.日历(NSCalendar) 2.时间格式() 3.时间戳 附录: 1.定时器 1.日历(NSCalendar) 1.想要获取 世纪.年.月.日.时. ...