游戏世界三维坐标转换为屏幕坐标原理分析:三角函数转换与矩阵变换

在3D游戏中获得游戏人物敌人坐标xyz后,并不能直接绘制到屏幕上,需要进行一系列的转换算法,目前主流的算法包括三角函数转换与矩阵变换,三角函数转换方法过时且繁琐,这里不推荐使用,本文主讲矩阵变换原理

一、游戏中多种坐标矩阵的转换关系

游戏中用CE可以找到敌人的world space坐标,也就是XYZ的游戏世界空间坐标, 通过矩阵变换得到Clip Space坐标(剪切坐标),通过透视分割算法得到NDC坐标,最后将NDC坐标视窗映射矩阵即可获得屏幕坐标

二、D3D和opengl中矩阵存储形式

 Direct3D 采用行主序(Row major)存储

“Effect matrix parameters and HLSL matrix variables can define whether the value is a row-major or column-major matrix; however, the DirectX APIs always treat D3DMATRIX and D3DXMATRIX as row-major.”

OpenGL 采用列主序(Colume major)存储

“The m parameter points to a 4x4 matrix of single- or double-precision floating-point values stored in column-major order. That is, the matrix is stored as follows”

  存储顺序说明了线性代数中的矩阵如何在线性的内存数组中存储,d3d 将每一行在数组中按行存储,而opengl将每一列存储到数组的每一行中:

  因此,对于线程代数中的同一个矩阵,则在d3d和OpenGL中有不同的表示形式:

                  线代矩阵:a11,a12,a13,a14            d3d保存:  a11,a12,a13,a14            OpenGL保存: a11,a21,a31,a41
                       a21,a22,a23,a24                         a21,a22,a23,a24                       a12,a22,a32,a42
                       a31,a32,a33,a34                         a31,a32,a33,a34                       a13,a23,a33,a43
                       a41,a42,a43,a44                         a41,a42,a43,a44                       a14,a24,a34,a44

三、算法实现流程(以D3D为例)

1.假设敌人的世界坐标为X, Y, Z,W;其中W为其次项,一般设置为1(D3D规范如此,这个不必计较)

2.计算剪切坐标:

剪切坐标X = a11*X + a12*Y + a13*Z + a14

剪切坐标Y = a21*X + a22*Y + a23*Z + a24

剪切坐标Z = a31*X + a32*Y + a33*Z + a34

剪切坐标W = a41*X + a42*Y + a43*Z + a44

(此处注意设置筛选条件,仅剪切坐标w>0的才可以继续以下操作,小于0的可以忽略,因为不在你的视角内,PS:不信的同学可以最后试一下加与不加的区别)

3.计算NDC坐标:(透视分割算法:用剪切坐标XYZ除以W即可)

NDC坐标X = 剪切坐标X / 剪切坐标W

NDC坐标Y = 剪切坐标Y / 剪切坐标W

NDC坐标Z = 剪切坐标Z / 剪切坐标W

4.NDC坐标转屏幕坐标:

转换公式如下:

屏幕坐标.x = 窗口宽度 ÷ 2 × NDC坐标.x + NDC坐标.x + 窗口宽度 ÷ 2
屏幕坐标.y = -(窗口高度 ÷ 2 × NDC坐标.y) + NDC坐标.y + 窗口高度 ÷ 2

至此,已经描述完世界坐标转换屏幕坐标的算法了

如果对NDC转屏幕坐标感兴趣的小伙伴可以继续往下看:

四、NDC转屏幕公式解析

如图所示,我们通过视口变换矩阵ViewPort与NDC坐标进行矩阵乘,即可得到以上公式,但是对于屏幕坐标Y的公式不可由该矩阵乘推得,注意公式前面的符号:屏幕坐标.y = (窗口高度 ÷ 2 × NDC坐标.y) + NDC坐标.y + 窗口高度 ÷ 2,

按照矩阵乘推理,应该没有负号,但是此处有,原因如下:

先普及下正常的屏幕坐标系和屏幕视口坐标系的区别:

由此可以知道,在与VIewPort做矩阵乘运算中,Y应该为与原来相反,所以在

[x,

y;

z,

1]竖矩阵中将y加上符号,再做矩阵乘,即可得到以上正确的算法公式,自己动手算一遍就会懂了。

参考文献:

https://www.bilibili.com/video/BV1UK4y1D781/?spm_id_from=trigger_reload

https://www.cnblogs.com/icmzn/p/13531265.html

https://space.bilibili.com/442168898/channel/detail?cid=123750

https://www.bilibili.com/video/av286268338/

猜你喜欢

转载自blog.csdn.net/THMAIL/article/details/114462827
今日推荐