统一D3D与OpenGL坐标系统
作者:游蓝海(http://blog.csdn.net/you_lan_hai)
DirectX 3D与OpenGL坐标系统的差异性,给我们带来非常大的麻烦。让跨平台编程的新手非常困惑。近期在做一个跨平台的游戏,细致看了下两者的矩阵。发现并没有什么大差别,将d3d左手系的矩阵传递给opengl shader全然能够正常工作。
先说一下两者一些概念上的差别:
(1)坐标系统不同
d3d左手坐标系,opengl右手坐标系
(2)矩阵行序不同
d3d行优先,opengl列优先。这两个不同,直接导致了坐标变换顺序与矩阵乘法顺序的相反性。假设是先缩放。再旋转,最后平移。相应的矩阵分别为S、R、T,则d3d的终于矩阵为M
= S * R * T。opengl为M = T * R * S
(3)裁减空间z取值范围不同
d3d是[0, 1]。opengl是[-1, 1]
表面上来看,两者矩阵区别非常大。但事实上不然。
1.左右手坐标系
对于显卡设备来说,设备坐标系是左手坐标系,即z轴指向屏幕里面。z值越大表示距离视线越远。
因此,opengl的右手系,在进入裁减空间的时候。会转换成左手系。
这也就是说。在渲染管线内部。坐标系是统一的。无论是左手坐标系矩阵,还是右手坐标系矩阵。仅仅要变换到裁减空间中的点是左手系就能够了。
2.矩阵行序
行矩阵和列矩阵,在逻辑上一个是还有一个的转置。但在物理存贮结构上却是全然一致的。如一个平移变换(x, y, z):
须要注意的是,矩阵乘法并不关心矩阵是行矩阵还是列矩阵。都是依照第一个矩阵的行去乘以第二个矩阵的列。对于列矩阵而言,这正是其蹩脚的地方,为了保证乘法意义的有效性,其坐标变换顺序跟矩阵乘法顺序恰好相反。
还要注意一点,在shader中,opengl的矩阵乘法规则跟d3d是不同的。
依照矩阵乘法规则(第一个矩阵行*第二个矩阵列):
d3d矩阵乘法: Ma(0 1 2 3) * Mb(0 4 8 12)
opengl矩阵乘法: Ma(0 4 8 12) * Mb(0 1 2 3)
因此。对于opengl shader而言。变换顺序跟矩阵乘法顺序依旧是反的。假设我们能将传入opengl shader的矩阵做一次转置。那么opengl shader的矩阵乘法意义将跟d3d shader全然一致!
3.改动投影矩阵
因为opengl的裁减空间z取值范围为[-1, 1]跟d3d的[0, 1]不同,我们不能简单的使用d3d投影矩阵。必须又一次定义d3d投影矩阵。
void Matrix::perspectiveProjectionLH2( float fov, float aspectRatio,
float nearPlane, float farPlane )
{
float h = (1.0f / tanf(fov * 0.5f));
float w = h / aspectRatio; float a = (farPlane + nearPlane) / (farPlane - nearPlane);
float b = -2.0f * farPlane * nearPlane / (farPlane - nearPlane); m[0][0] = w; m[0][1] = 0; m[0][2] = 0; m[0][3] = 0;
m[1][0] = 0; m[1][1] = h; m[1][2] = 0; m[1][3] = 0;
m[2][0] = 0; m[2][1] = 0; m[2][2] = a; m[2][3] = 1;
m[3][0] = 0; m[3][1] = 0; m[3][2] = b; m[3][3] = 0;
}
4.总结
使用左手系变换来统一两个平台是比較方便的。总结一下改动opengl渲染管线的步骤:
(1)在c++层统一使用左手坐标系变换。
(2)改动投影矩阵。以适应裁减空间z坐标范围[-1, 1];
(3)矩阵在传入shader的时候,将矩阵的转置矩阵传入;
(4)在shader层,统一使用左手坐标系变换。
假设,不想改动shader中的变换,仅仅用做到(1)和(2)就够了。
5.很多其它阅读
推导投影矩阵 http://blog.csdn.net/popy007/article/details/4091967
跨越opengl和d3d的鸿沟 http://www.cppblog.com/topjackhjj/articles/157038.html
统一D3D与OpenGL坐标系统的更多相关文章
- opengl坐标系统
概述 为了将坐标从一个坐标系变换到另一个坐标系,我们需要用到几个变换矩阵,最重要的几个分别是模型(Model).观察(View).投影(Projection)三个矩阵.我们的顶点坐标起始于局部空间(L ...
- OpenGL.Tutorial16_ShadowMapping
1. 2. In Tutorial 15 we learnt how to create lightmaps, which encompasses(包含) static lighting. While ...
- Vulkan vs OpenGL ES
Vulkan 简介 Vulkan是一个免费开放的.跨平台的.底层的图形API,在一定程度上比AMD Mantle.微软DirectX 12.苹果Metal更值得开发者关注. Vulkan的最大任务不是 ...
- OpenGL与Directx的区别
OpenGL 只是图形函数库. DirectX 包含图形, 声音, 输入, 网络等模块. 单就图形而论, DirectX 的图形库性能不如 OpenGL OpenGL稳定,可跨平台使用.但 OpenG ...
- OpenGL ES 入门
写在前面 记录一下 OpenGL ES Android 开发的入门教程.逻辑性可能不那么强,想到哪写到哪.也可能自己的一些理解有误. 参考资料: LearnOpenGL CN Android官方文档 ...
- OpenGL ES: (1) OpenGL ES的由来 (转)
1. 电脑是做什么用的? 电脑又被称为计算机,那么最重要的工作就是计算.看过三体的同学都知道, 电脑中有无数纳米级别的计算单元,通过 0 和 1 的转换,完成加减乘除的操作. 2. 是什么使电脑工作? ...
- 64 计算机图形学入门(1)——OpenGL环境配置与图形流水线(图像管线)
0 引言 最近想学一下计算机图形学方面的知识,原因如下.目前本人接触了数字图像处理(opencv)以及点云处理(PCL)方面的知识,对从图像和点云中提取特征信息,并将特征转化为底层/中层语义信息有了一 ...
- OpenGL在图形管道中调用了什么用户模式图形驱动程序(UMD)?
OpenGL在图形管道中调用了什么用户模式图形驱动程序(UMD)? 图形硬件供应商,需要为显示适配器编,编写用户模式显示驱动程序.用户模式显示驱动程序,是由Microsoft Direct3D运行时加 ...
- Opengl ES之纹理贴图
纹理可以理解为一个二维数组,它可以存储大量的数据,这些数据可以发送到着色器上.一般情况下我们所说的纹理是表示一副2D图,此时纹理存储的数据就是这个图的像素数据. 所谓的纹理贴图,就是使用Opengl将 ...
随机推荐
- 关于 拼接 url 连接 参数的问题(爬虫)。
比如这里 我找的 后台请求的json的链接: 第一页: http://www.igoldenbeta.com:8080/cn-jsfund-server-mobile/bkt/api?appkey=1 ...
- ES6 promise简单实现
基本功能实现: function Promise(fn){ //需要一个成功时的回调 var doneCallback; //一个实例的方法,用来注册异步事件 this.then = function ...
- 各种好用的代码生成器(C#)
各种好用的代码生成器(C#) 1:CodeSmith 一款人气很旺国外的基于模板的dotnet代码生成器 官方网站:http://www.codesmithtools.com 官方论坛:http:// ...
- mybatis 一级缓存和二级缓存
1.默认是会话期内 一级session缓存 2.二级缓存: 引入二级缓存的jar, 配置 ehcache.xml, mapper.xml引入缓存<cache type="org.myb ...
- Monty Hall悖论
Monty Hall悖论又称为蒙提·霍尔悖论.三门问题.Monty Hall是上个世纪60年代,电视游戏节目“Let's Make a Deal”的主持人,这个悖论便是以他的名字来命名的.节目的规则是 ...
- Entity Framework中使用DbCompiledModel中遇到的坑和解决方案
前段时间,在公司做项目时,引入Entity Framework Code First的方法. 我们公司的软件为SaaS结构,有N个企业注册,其中SQL Server中有一张表为t_User_企业注册号 ...
- Openstack 云主机深入了解 (十六)
一)云主机深入了解 1.云主机在计算节点以进程方式运行 2.监听vnc的端口,vnc默认端口从5900开始, 多台云主机,端口递增 3.云主机桥接网卡,与宿主机联通网络 提示:在openstack环境 ...
- ubuntu 16.04 LTS安装jenkins服务器
官方网站:https://jenkins.io/ 这里我们的系统是Ubuntu 16.04,所以选择Ubuntu的版本,另外,为什么选择2.60.3,而不是新的2.77?因为2.60.3是LTS版本, ...
- zoj 4020 The 18th Zhejiang University Programming Contest Sponsored by TuSimple - G Traffic Light(广搜)
题目链接:The 18th Zhejiang University Programming Contest Sponsored by TuSimple - G Traffic Light 题解: 题意 ...
- Kerberos KDC not reachable
水贴..我这里出现这个问题的原因是服务器上安装的是 oracle jdk, 但是没有安装 JCE 拓展包. 解决方式有两个: 1. 换成 openJDK 2. 安装上 JCE 拓展包 java 8 ...