FPS游戏利用矩阵实现透视,以单机版csgo为例,附源码,有详细注释。
网上现在有很多FPS方框透视教程,但是很多都是找到矩阵,用个易语言模块就实现了,但是这样我们局限性很大,没有模块的时候该怎么办?而且易语言的模块都看不到源码,所以我写了本篇文章说一下具体实现透视的算法,和大致的原理。
这个算法需要一点数学基础,与线性代数有关。 只要你不问我一个三行四列的行列式怎么算 ,你应该就可以看的懂。
我们取得矩阵的目的是什么呢,就是将人物的世界坐标转换为我们的屏幕坐标。
也就是将一个三维向量转为二维向量,这时候我们就需要矩阵的乘法来转换。
向量顾名思义就是既有方向又有大小的量。二维坐标系上的向量就是二维向量,如(2,3) 三维坐标系上的向量就是三维向量如(3,4,5)。
我们也可以这样写,这是一个列向量,也是一个矩阵。
一个游戏中一很多的坐标系如 世界坐标系 物体坐标系 观察坐标系等等。我们屏幕上显示物体的坐标x,y坐标就是通过世界坐标系中的坐标乘一个混合矩阵得到的。
这其中的数学原理我就不细讲了,因为这是做3d游戏需要学习的一些数学知识,想了解详情的可以参考知乎一篇文章:矩阵变换坐标系 深入理解 - 知乎 (zhihu.com)
我就举两个小例子,一个坐标系到另外一个坐标系 是通过平移,旋转和缩放实现的。
矩阵的乘法运算:
我这样写应该很容易理解,比百度百科上那些概念公式更容易看的懂。
比如我们将一个单位矩阵这个位置填上x,y,z坐标
做如下乘法
就相当于我们做了将(0,0,0)平移到了(x,y,z)
如果乘一个这样的矩阵呢
就完成了对z的缩放
这时候,你应该大致能理解为什么要乘以矩阵了,接下来我们用算法实现一下,世界坐标到屏幕坐标
这里我们找到的是竖矩阵,也就是这样的。因为我们游戏是directX的 如果是openGL可能就是横矩阵 ,那我们的算法就要变,但是很简单,只要举一反三就可以了
我们应该用矩阵乘世界坐标而不是世界坐标乘矩阵
因为矩阵的乘法只能是Anm*Bmj这样的也就是说前面矩阵的列数必须等于后面矩阵的行数,乘完我们就得到一个 n行j列的矩阵,也就是说矩阵的乘法不满足乘法交换率。
vec clipCoords;
clipCoords.x = pos.x * matrix + pos.y * matrix + pos.z * matrix + matrix;
clipCoords.y = pos.x * matrix + pos.y * matrix + pos.z * matrix + matrix;
clipCoords.z = pos.x * matrix + pos.y * matrix + pos.z * matrix + matrix;
clipCoords.w = pos.x * matrix + pos.y * matrix + pos.z * matrix + matrix;
我们这样乘完得到的是一个裁剪坐标
接着我们转换为DNC坐标,也就是标准化设备坐标
vec NDC;
NDC.x = clipCoords.x / clipCoords.w;
NDC.y = clipCoords.y / clipCoords.w;
NDC.z = clipCoords.z / clipCoords.w;、
为什么这样算呢 ,这不是我说的,是微软的文档说的,这些东西就是那些计算机图形学的知识了 ,可以知其然不知其所以然,但是不能完全不知道用别的写好的模块,我们需要自己会用。
下一步就是转换为屏幕坐标,一样也是文档里可以查阅到的公式,就是利用屏幕的宽和高进行一些计算,就得到了屏幕坐标。
screen.x = (windowWidth / 2 * NDC.x) + (NDC.x + windowWidth / 2);
screen.y = -(windowHeight / 2 * NDC.y) + (NDC.y + windowHeight / 2);
我们得到的这个坐标是人物脚下正中心的坐标,如果需要画方框我们需要找到头部坐标,把人物的身高算出来,画出完美大小的方框。
我这里就进行测试一下
可以看到坐标还是比较准确的
无论我们是在什么位置,都能在敌人的脚下画出我输入的文本。
我们需要找的数据也很少,其他的数据我就不说了 ,很好找。
我大致说一下矩阵的几个特点:
还是以我们找到的这个竖矩阵为例
1.
这个值的绝对值小于2
除非在狙击枪开镜的时候会大于2
2.
这几个值基本一样
3.
这大概率有个0.00
我们鼠标晃动的时候矩阵就会变,但是如果只移动人物 鼠标不动,就只有最后一列的值变动。
通过这些慢慢搜索出矩阵就可以了。
源码在附件
内容很好就是比较费号 一个三行四列的行列式怎么算? 原来是这样的原理,学习了! 感谢分享经验,看着挺复杂的 厉害了,感谢分享 学以致用:lol 关于矩阵我记得大学课程有系统化的讲解,不过很多写这些游戏辅助的人来说,他们不需要知道的这么详细,因为太多人只想得到成果,根本不会去看过程和细节{:301_1001:} 感谢分享经验 这会了不就牛比了吗 学习了不错