opengl各个坐标系理解与转换公式
1、标准化设备坐标(Normalized Device Coordinates, NDC)
顶点坐标已经在顶点着色器中处理过,它们就应该是标准化设备坐标了,标准化设备坐标是一个x、y和z值在-1.0到1.0的一小段空间。任何落在范围外的坐标都会被丢弃/裁剪,不会显示在你的屏幕上。
2、UV坐标系
UV坐标系一般以左下角为原点(0,0),经常用于贴图上面。范围为0-1.
OpenGL 一个完整的空间变换流水线如下:
model coordinate system(模型坐标系)->world coordinate system(世界坐标系) --> eye coordinate system(相机坐标系) --> clip coordinate system(裁减平面坐标系) --> normalized device coordinate system(标准设备坐标系NDC) --> window device coordinate system(屏幕坐标系)。
- 模型变换和观察变换,使将物体的坐标从模型空间,通过旋转移动等复合变换,转换到了以摄像机为原点的观察空间坐标系下。在观察空间下,z轴上的数据表示了物体距离摄像机的远近,即深度,此时的深度值还是线性的。(观察空间使用的是右手坐标系,即 -z轴才是摄像机的正前方)
- 观察空间中,只有位于视锥体内的物体才会被摄像机渲染并且可见,所以需要将范围外的顶点剔除。但是视锥体是一个金字塔形状,由六个锥平面构成。使用六个锥平面直接进行裁剪判断会很麻烦; 因此,有一种更加方便的方法是:通过一个透视投影矩阵把顶点从观察空间转换到一个裁剪空间下,转换的过程实际是对x,y,z分量都进行了不同程度的缩放和平移。使x,y,z值满足:直接用w分量作为裁剪的范围值,如果变换后的x,y,z分量都位于[-w,w]这个范围内,就说明该顶点位于裁剪空间内,反之会被剔除。 以下是推导出的透视投影矩阵和顶点相乘后的坐标点(这里不做推导过程):
Near:近裁剪平面距离
Far:远裁剪平面距离
FOV:锥体竖直方向的张开角度
Aspect:摄像机的横纵比 - 在上一步操作中,我们可以得到裁剪空间下的 z 和 w 分量:
- 经过透视投影变换,坐标系转换到了裁剪空间下。紧接着,我们可以通过判断当前的 x,y,z 分量是否处于 [-w,w] 范围内,来判断坐标点是否处于视锥体内,并将视锥体外的坐标点剔除。在观察空间,世界空间,模型空间下,坐标点的w分量一直都是1,所以说,经过剔除后的裁剪空间下的坐标点的范围值为 [-1,1]。
- 当完成所有的裁剪工作后,就要进行真正的投影了,即把视锥体投影到屏幕空间中,从而得到真正的二维像素坐标。 期间需要进行两步操作,齐次除法和映射输出。
- 齐次除法:用齐次坐标系的 w 分量去除以x,y,z分量。以z轴分量为例:
经过齐次除法后,坐标系由裁剪空间转换到了NDC(归一化的设备坐标,Normalized Device Coordinates)下,此时的x,y,z分量的范围值为[-1,1]。
- 映射输出:NDC下的x和y的坐标范围是[-1,1],而屏幕空间左下角像素坐标是(0,0),右上角的像素坐标是(pixelWidth,pixelHeight),因此x和y会先除以2再加1/2,映射到[0,1],然后再分别乘以pixelWidth和pixelHeight:
上面的式子对x,y值做了处理,而z分量会直接被用于深度缓冲(Zbuffer),当然这个也不一定,会根据硬件选取合适的存储格式。 除此之外,为了能将z值存储到深度图中,需要将其范围映射到 [0,1]:
此时的 d 值就是 Unity 中深度图存储的数据。因为d是关于z_ndc的函数,z_ndc是关于1/z_visw的函数,因此 d 自然不是线性的了。 (z_ndc:ndc空间下的z值;z_visw:观察空间下的z值)
具体的转换方式:
(1)世界坐标系内的坐标乘以观察矩阵变换到眼坐标空间 eye.xyzw = viewMatrix * world.xyzw;
(2)眼坐标系内的坐标通过乘上投影矩阵变换到裁剪空间 clip.xyzw = projectMatrix * eye.xyzw;
(3)裁剪坐标系内的坐标通过透视除法(也就是 w 为 1 化) 到 规范化设备坐标系 ndc.xyz = clip.xyz / clip.w;
(4)设备规范化坐标系到窗口坐标系 win.z = (dfar - dnear)/2 * ndc.z + (dfar+dnear)/2;
可以看出gl_FragCoord.z 是 win.z 。dnear ,dfar 是由 glDepthRange(dnear, dfar) 给定的,按openGL 默认值 (0,1) , win.z = ndc.z/2 + 0.5。
有时候我们需要在 shader 内反算 眼坐标系 或 世界坐标系 内的坐标, 这在后处理或延迟着色中很有用,不需要另外使用颜色缓存保留物体位置信息,减少带宽占用。
由窗口空间坐标反算规范化设备空间坐标:
ndc.xyzw = ( gl_FragCoord.xy/viewport.wh * 2.0 - 1.0, gl_FragCoord.z * 2.0 - 1.0, 1.0 );
这样我们只需向shader 中传入矩阵信息就可以获得该片元在指定空间内的坐标 ,例如
- eye.xyzw = projectionMatrixInverse * ndc.xyzw;
- world.xyzw = modelViewProjectionMatrixInverse * ndc.xyzw
注意最终结果要除以 w 分量, eye.xyz = eye.xyz/eye.w;
vec3 decodeCameraSpacePositionFromDepthBuffer(in vec2 texCoord){ vec4 clipSpaceLocation;clipSpaceLocation.xy = texCoord*2.0-1.0; clipSpaceLocation.z = texture(depthTexture, texCoord).r * 2.0-1.0; clipSpaceLocation.w = 1.0; vec4 homogenousLocation = projectionMatrixInverse * clipSpaceLocation; return homogenousLocation.xyz/homogenousLocation.w;
}
vec3 decodeWorldSpacePositionFromDepthBuffer(in vec2 texCoord){ vec4 clipSpaceLocation; clipSpaceLocation.xy = texCoord*2.0-1.0; clipSpaceLocation.z = texture(depthTexture, texCoord).r * 2.0-1.0; clipSpaceLocation.w = 1.0; vec4 homogenousLocation = viewProjectionMatrixInverse * clipSpaceLocation; return homogenousLocation.xyz/homogenousLocation.w;
}
opengl各个坐标系理解与转换公式相关推荐
- OpenGL学习笔记(一):环境搭建、三维空间坐标系理解以及OpenGL的基本使用
原博主博客地址:http://blog.csdn.net/qq21497936 本文章博客地址:http://blog.csdn.net/qq21497936/article/details/7866 ...
- OpenGL(5)深入理解Pipeline, State, Context
OpenGL(5)深入理解Pipeline, State, Context Pipeline(管线/管道) 管线(pipeline),可以理解为渲染流水线.它的最终目的是将输入3D数据经过几个流程的处 ...
- opengl 坐标的理解
[目标]:学习OpenGL中的坐标系统. [参考]: 1.<计算机图形学(OpenGL版) (第三版)> Francis著 (本文主要涉及第三章~第七章) 2.<计算机图形学(Ope ...
- OpenGL之坐标系以及单位
1.1 OpenGL中默认的坐标系为右手坐标系,默认视点位置为原点,原点正好投影在投影窗口的中心,也正好投影在视口的中心. 1.2 在OpenGL中无绝对单位,只有相对的大小,相对于视锥体的大小来设定 ...
- OpenGL LookAt函数理解
前言:记录OpenGL学习过程中的一些知识点,以个人理解为主. LookAt函数将顶点的世界空间坐标转换为观察空间坐标,实际上是以相机为原点重新定义的三维空间. glm::mat4 LookAt(gl ...
- Android Camera OpenGL FBO的理解
背景概念: 首先,Android显示系统中,系统默认的渲染器是OpenGL,混合使用skia,各个厂商可能有不同的实现,大部分都是OpenGL. Android在系统启动时,经过BootLoader启 ...
- opengl微发展理解
1.什么是OpenGL? 一种程序,可以与界面和图形硬件交互作用.一个开放的标准 2.软件管道 请看上图 - Apllication层 表示你的程序(调用渲染命令.如opengl API) - ...
- 【我的OpenGL学习进阶之旅】【持续更新】关于学习OpenGL的一些资料
目录 一.相关书籍 OpenGL 方面 C方面 NDK 线性代数 二.相关博客 2.0 一些比较官方的链接 2.1 OpenGL着色器语言相关 2.2 [[yfan]](https://segment ...
- opengl中的glViewport,glOrtho,glFrustum 理解
在刚使用opengl时,会遇到对opengles中的一些视角等理解,需要用到glViewport,glOrtho,glFrustum 等函数,下面针对这些函数做一些说明 viewport建立视口,是视 ...
最新文章
- java数组排序之冒泡排序
- python3 日志检索异常抛出异常 raise KeyError(key),KeyError: 'formatters'
- Matlab中legend位置
- vb.net2019- 机器学习ml.net情绪分析(2)
- 【深度学习】你不知道的车牌识别系统
- Linux使用lvresize扩展或缩减LV逻辑卷大小
- Bigtable的些许重点
- 自动挡跑高速用S挡还是D挡? 回答
- WORD的POI处理与原理
- 移植u-boot.2012.04.01
- python基于tornade的高并发接口编程实战学习
- 深度置信网络学习总结
- vscode 弹窗报错~/AppData\LocalPrograms\Microsavs Code\unins000.exe
- linux制作虚拟机镜像,为OpenStack制作CoreOS虚拟机镜像(基于CoreOS官方提供镜像)
- python简单编程--ATM银行管理系统
- 无线局域网和蜂窝移动网络_干货!无线AP覆盖系统解决方案
- 电商网站后台九大功能模块详解
- word在另外计算机格式不对,为什么同一个word文档在两台电脑上打开里面的格式不一样...
- IntelliJ IDEA 13 皮肤/编辑器字体设置
- 五、Hive数据仓库(完整版)
热门文章
- 如何从 Github 中删除提交
- 中国拼图游戏市场现状研究分析与发展前景预测报告(2022)
- 最新版Win11系统22H2跳过联网验机-亲测可用
- vivox9怎么和计算机共享,vivo手机怎么分享软件给别人(共享软件的操作步骤)...
- JavaScript实战之简单的抽签器
- 考研英语前缀总结·十六
- 菜鸟的树莓派Raspberry Pi学习之旅(一)——认识树莓派硬件篇
- 2022亚马逊云科技re:Invent,与合作伙伴描绘宏伟蓝图
- 新版JESD625C 和 JESD625B 条款之间的区别变更说明
- PCNN 脉冲耦合神经网络整理