threejs已经有了sprite插件,这就方便了three的用户,直接可以使用threejs的sprite插件来制作GUI模型。sprite插件是阿里的lasoy老师改造过的,这个很厉害,要学习一哈他的源码。闲话少叙,我们来看一下如何用原生的webgl来实现sprite精灵效果。首先我们来看一个样例。

我们可以看到,这个数字模型的纹理贴图是“2”,他具有两个特性,第一他永远面向主相机,第二他在屏幕上的投影尺寸不随场景缩放而产生一丝一毫的变化。这就是sprite精灵的特点,我们来看看具体是怎么实现的这样的效果。第一我们先集中精力解决数字模型始终面向相机的问题,我们知道,模型在场景中的modelView矩阵是随场景的空间旋转,平移,缩放而重新计算的,那么问题来了,我们怎么知道场景的每一帧空间变换的平移,旋转,缩放的变化量呢,鲫鱼可以负责任的告诉大家,我们计算不出这3个空间变换的叠加。那是怎么实现数字模型空间变换使它每一帧都面向主相机的呢?好,我们就来看看数字模型是怎么每一帧计算空间变换矩阵的。
其中有一个技巧就是坐标系转换,我们知道,主相机和模型都在世界坐标系中,那么我们换个思路,能不能把数字“2”的模型放到主相机的局部坐标系下面,让他的x,y,z方向坐标轴和主相机的x,y,z方向坐标轴重合,这样不就使得数字模型“2”永远面对着主相机不产生相对旋转了吗,真是个好办法,鲫鱼我说干就干。
1 /** 2 * 统一两个矩阵的基 3 * mat1:参考矩阵 4 * mat2:要变换基的矩阵 5 * */ 6 Mat4.copyBasis = function(mat1, mat2){ 7 //x轴基向量 8 mat2[0] = mat1[0]; 9 mat2[1] = mat1[1]; 10 mat2[2] = mat1[2]; 11 //y轴基向量12 mat2[4] = mat1[4]; 13 mat2[5] = mat1[5]; 14 mat2[6] = mat1[6]; 15 //z轴基向量16 mat2[8] = mat1[8]; 17 mat2[9] = mat1[9]; 18 mat2[10] = mat1[10]; 19 }; 20 21 module.exports = Mat4;
首先理解空间变换矩阵的同学都知道列主序的矩阵的x轴分量即x轴基向量是mat[0],mat[1],mat[2];y轴分量即y轴基向量是mat[4],mat[5],mat[6];z轴分量即z轴基向量是mat[8],mat[9],mat[10];平移和缩放向量是mat[12],mat[13],mat[14]。那么好了,我们现在不关心平移和缩放,只关心旋转,所以我们只需要把数字模型的空间变换矩阵的x基,y基,z基照搬主相机的modelView矩阵的逆矩阵即可,注意是逆矩阵,因为主相机也在世界坐标系下,他的空间变换矩阵还是世界坐标系下的空间位置描述,他的空间变换矩阵的逆矩阵才是他的局部坐标系矩阵。我们直接按照这个步骤来操作。
1 /** 2 * 计算文字相对主相机的变换矩阵 3 * mat:要计算的缩放旋转矩阵 4 * */ 5 computeMatrix4MainCamera:function(mat){ 6 //场景主相机 7 let camera = this._viewer.getMainCamera(); 8 //相机坐标系矩阵 9 let modelViewMat = camera.getModelViewMatrix(); 10 //相机坐标系矩阵的逆矩阵11 let invMVMat = Mat4.MemoryPool.alloc(); 12 Mat4.invert(invMVMat, modelViewMat); 13 //构造文字变换矩阵14 Mat4.copyBasis(invMVMat, mat); 15 },
总共5行代码,第一步获取主相机;二、得到主相机的modelView矩阵;三和四、求modelView矩阵的逆矩阵;五、将逆矩阵的xyz轴向量基赋给我们的数字模型“2”的空间变换矩阵。做完这件事以后,鲫鱼惊喜地发现数字模型2完美地跟随相机转动起来,永远面对着相机。正如歌词所云,月亮走,我也走,月亮永远面向我,无论我走到哪儿。喝哈哈哈。
好了,第一件事情圆满解决,我们来看看第二件事情怎么处理。我们接下来要处理的是模型缩放,但数字模型“2”在屏幕上的投影大小不变。
要解决这件事,首先我们要清楚模型缩放的原理是什么,在我们的osg引擎中,是通过主相机靠近或远离模型来实现的缩放效果。那么就好办了,鲫鱼的思路就是相机靠近模型,我就把数字模型“2”缩小,相机原理模型,我就把数字模型“2”放大,通过近小远大来对抗视觉上的近大远小。我们知道,透视下的模型尺寸和到眼睛的距离是呈反比的关系。来看一张示意图。

我们可以很清楚的看明白,越远的物体越小,越近越大,物体尺寸在屏幕上的投影和到眼睛的距离成反比。那么鲫鱼为了固定数字模型“2”在屏幕上的投影尺寸,就要反过来缩放模型的尺寸,越近越小,越远越大,和模型到相机眼睛的距离成正比,就达到我们的目的了,下面是鲫鱼的源码。

