转自http://blog.sina.com.cn/s/blog_6bd83ee00100zrjz.html
这篇文章来自Billboarding Tutorial,原作者为António Ramires Fernandes。
伪Billboarding技术-快速而简单的实现球形Billboards将要介绍的这种方法并不是一种真正意义上的billboarding,但是他提供了一种廉价的方法以达到近似的效果,对于一部分程序来说已经足够了。
下面这幅图是一个演示画面。它显示了一个雪人和一些经过billboard处理过的树。虽然很难说这些树就是严格面朝相机的,但是它们确实面向了与相机视线垂直的一个平面。
下面的图表更加清晰的反映了这种关系。位于底部的黑色圆点代表相机。由相机发出的矢量箭头表示了相机目前的视线方向。同时这个矢量也确定了一个与相机视线方向垂直的平面。图中的物体01,02,03被旋转使得它们的正面矢量朝着这个平面。这里假设所有物体都被置于圆点并且面向Z轴的正方向。
为了实现这一效果需要获取模型视图矩阵。首先你应该知道模型视图矩阵存储了几何图形的变换包括旋转,缩放和平移。这个矩阵包含了所有需要的变换,通过这些变换将你输入的坐标和世界坐标转换为相机坐标。
矩阵的第四列的上面3个值代表了关于相机位置和方向的本地原点的位置。上面的3X3子矩阵包含了缩放和旋转操作。将这个子矩阵置为单位矩阵可以有效的将这些操作屏蔽,以便使相机的视线方向与世界坐标系Z轴方向一致。相机的向上和向右矢量也和世界坐标系一致,也就是说这种billboard方式是一种伪球形billboarding.这个billboard的中心是原点。如果你打算使用这种billboarding方式,那么当使用者向上或向下看时树好像在向前或向后弯曲,这多少会有些尴尬。这是因为billboard的定向依赖于和相机位置相反的相机方向。
实际上,将子矩阵置为单位矩阵意味着你所绘制的物体不会发生任何旋转。因此,如果相机视线对着Z轴负方向,那么物体总是以同样的方式绘制。
缩放操作也同时无效,如果你用这种方式将无法让树变高,除非你在改变模型视图矩阵之后再进行缩放。
第一步操作是保存当前模型视图矩阵,之后获取模型视图矩阵。再将3X3的子矩阵置为单位矩阵。将这个矩阵加载到OpenGL状态机中,然后在本地坐标系中绘制你的物体。最后恢复原来的模型视图矩阵。
float modelview[16];
int i,j;
// save the current modelview matrix
glPushMatrix();
// get the current modelview matrix
glGetFloatv(GL_MODELVIEW_MATRIX , modelview);
// undo all rotations
// beware all scaling is lost as well
for( i=0; i<3; i++ )
for( j=0; j<3; j++ )
{ if ( i==j )
modelview[i*4+j] = 1.0;
else
modelview[i*4+j] = 0.0;
}
// set the modelview with no rotations and scaling
glLoadMatrixf(modelview);
drawObject();
// restores the modelview matrix
glPopMatrix();
上面的代码段可以使物体旋转至面朝相机视线垂直的平面,旋转的中心为坐标原点。