Billboard是一项使用非常普遍的技术,很多一些绚丽的特效可以使用它来实现,当然公告板、姓名板等是它较早的用途。
Billboard 的主要思想是在 XY 平面上建立一个绘图区域,在此区域上渲染一张贴图的一个区域,并且此平面要一直面向摄像机。
Billboard的主要实现:
1. Billboard的绘制区域是建立在自身坐标系的XY平面上,绘制区域的正面朝向为自身坐标系的Z轴的方向。由于Billboard需要朝向摄像机,所以Billboard在构造渲染顶点数据的时候需要将原始的Billboard绘制区域的左右对调后再填充定点数据(即原来的区域left与 right)。
2. Billboard朝向问题:
Billboard需要一直朝向摄像机,即通过Yaw\Picth\roll(由于旋转是相对于Billboard自身坐标系,所以Yaw\Picth\roll分别对应Y\X\Z)三次旋转后达到billboard永远朝向摄像机的目的。一般程序实现分两种,固定Yaw轴(Billboard的上方向不变)与不固定Yaw轴。
固定Yaw轴的Billboard旋转的时候要使Yaw轴保持固定所以不能进行Picth和Roll旋转,只需要沿Yaw轴旋转。
固定Yaw轴的Billboard需要三次旋转
Billboard旋转D3D代码:
//由于Billboard的旋转是按自身坐标系旋转,所以up/right/foward分别对应Y/X/Z轴
//首先得到billboard应该被设置成的朝向向量即摄像机的朝向向量的反方向
D3DXVECTOR3 lookAt(0.0f, 0.0f, 1.0f);
lookAt = -pCam->GetDirection();
//再得到lookAt投影到XZ平面上的向量,用于计算Pitch值(相当于沿X方向旋转的角度)
D3DXVECTOR3 adjustLookAt = lookAt;
adjustLookAt.y = 0.0f;
//必须要将向量变为单位向量
D3DXVec3Normalize(&lookAt, &lookAt);
D3DXVec3Normalize(&adjustLookAt, &adjustLookAt);
D3DXMATRIX rm_x;//沿X轴的旋转矩阵
D3DXMATRIX rm_z;//沿Y轴的旋转矩阵
D3DXMatrixIdentity(&rm_z);
//如果摄像机的上方向的Y值小于0则需要将Billboard的up方向向反方向调换一下
if (pCam && pCam->GetUp().y < 0.0f)
D3DXMatrixRotationAxis(&rm_z, &D3DXVECTOR3(0.0f, 0.0f, 1.0f), D3DX_PI);
//Billboard朝向与XZ平面的夹角
dot = D3DXVec3Dot(&adjustLookAt, &lookAt);
//如果Billboard朝向是沿Y轴向下则绕X轴正向旋转,否则沿X轴反向旋转,
//左手坐标系下的旋转符合左手定则,比划一下就能知道为什么
if (lookAt.y <= 0)
D3DXMatrixRotationAxis(&rm_x, &D3DXVECTOR3(1.0f, 0.0f, 0.0f), acos(dot));
else
D3DXMatrixRotationAxis(&rm_x, &D3DXVECTOR3(-1.0f, 0.0f, 0.0f), acos(dot));
rm_x = rm_z * rm_x;
D3DXMATRIX rm_y;//绕Y轴旋转的矩阵
//旋转的角度为Billboard朝向与Billboard原始朝向的夹角
dot = D3DXVec3Dot(&D3DXVECTOR3(0.0f, 0.0f, 1.0f), &adjustLookAt);
//根据Billboard朝向方向是偏X轴的正方向还是反方向决定绕Y轴的正方向或反方向
//同样用左手比划一下就知道为什么
if (adjustLookAt.x <= 0)
D3DXMatrixRotationAxis(&rm_y, &D3DXVECTOR3(0.0f, -1.0f, 0.0f), acos(dot));
else
D3DXMatrixRotationAxis(&rm_y, &D3DXVECTOR3(0.0f, 1.0f, 0.0f), acos(dot));
3. Billboard渲染时需要根据使用情况决定是否需要开启灯光渲染。