广告版技术BillBoard 原理与实现

来源:互联网 发布:单片机延时流程图 编辑:程序博客网 时间:2024/06/04 19:42

http://www.opengl-tutorial.org/cn/intermediate-tutorials/billboards-particles/billboards/

广告版技术BillBoard 原理与实现

原创 2016年04月10日 19:12:07

面向世界的广告板demo下载



广告板技术:

无论观察者处于什么位置观察任何图像,广告版都能提供一个朝向观众的面,这个面随着摄像机的改变而改变.BillBoard技术是计算机图形学领域中进行快速绘制的一种方法。在类似游戏这种对实时性要求较高的场景下采取BillBoard技术可以大大加快绘制的速度从而提高画面的流畅性。
把3D的物体用2D来表示,然后让该物体始终朝向镜头。比如场景中的一棵树,对于整个场景来说不是主要物体,因此无需花费大量的时间去计算树的每一部分的细节。通常的做法是首先准备好一张树的照片,然后镜头运动的时候使得树始终正对着镜头,我们看到的始终是树的正面。
我们在渲染树木,灌木丛,云,烟等效果时都会用到.

先看一下图片,这颗树就是广告板技术生成的


原理:

问题的实质就是我们知道结果是物体面对摄像机,然后求物体的世界变换矩阵.



我们看这张图,其中有两种坐标,一种是Camera,一种是Particle,其中Particle就是我们要讨论的广告板(BillBoard).

[cpp] view plain copy
  1. // 计算此物体的朝向矩阵,首先计算几个向量  
  2.     float3 v3Look  = normalize( + g_vEyePt.xyz - g_vLookAt.xyz );  
  3.     float3 v3Right = normalize( cross( float3( 0.0f , 1.0f , 0.0f ) , v3Look ));  
  4.     float3 v3Up    = cross( v3Look , v3Right );  

这是其中三行确定广告版坐标的代码.
v3Look图中Particle 蓝色箭头的方向,意思是朝向Camera的方向,这个很容易由两个向量相减得到,然后规范化.
v3Right是图中Particle中深绿色的箭头.首先由Particle中的浅绿色箭头(float3( 0.0f , 1.0f , 0.0f )),也就是Camera中间的Y方向向量,然后和v3Look 叉乘,最后规范化,可以得到深绿色的v3Right向量.
v3Up是图中Particle 中是深红色的向量.可以由v3Look和v3Right叉乘得到.




[cpp] view plain copy
  1. float4x4 matLookAt ;  
  2. matLookAt[ 0 ] = float4( v3Right.xyz , 0.0 );//将右向量作为矩阵的X变换分量  
  3. matLookAt[ 1 ] = float4( v3Up.xyz , 0.0 ); //将向上向量作为矩阵的Y变换分量  
  4. matLookAt[ 2 ] = float4( v3Look.xyz , 0.0 );//将向前向量作为矩阵的Z变换分量  
  5. matLookAt[ 3 ] = float4( g_vEyePt.xyz , 1.0 );//将观察位置作为矩阵的Z变化平移分量  
  6. float4x4 matLocal = mul( matLookAt , g_matWorld );  
  7. float4x4 matWorldView = mul( matLocal ,g_matView );  
  8. float4x4 matWorldViewProject = mul( matWorldView ,g_matProject );  
  9. Out.Position = mul( In.Position , matWorldViewProject );  

这样子就能得到真实世界的坐标了.

广告版的种类:

1.面向世界的广告板,大小随远近调整,也称精灵技术
2.某轴是巨鼎的,大小随远近变化
3.提示信息类,大小与远近距离无关

一.面向世界的广告板,大小随远近调整,也称精灵技术

[cpp] view plain copy
  1. VS_OUTPUT RenderSceneVS( VS_INPUT In )  
  2.   {  
  3.     VS_OUTPUT Out = ( VS_OUTPUT )0;  
  4.     // 计算此物体的朝向矩阵,首先计算几个向量  
  5.     float3 v3Look  = normalize( + g_vEyePt.xyz - g_vLookAt.xyz );  
  6.     float3 v3Right = normalize( cross( float3( 0.0f , 1.0f , 0.0f ) , v3Look ));  
  7.     float3 v3Up    = cross( v3Look , v3Right );  
  8.     // 通过几个向量建立矩阵  
  9.     float4x4 matLookAt ;  
  10.     matLookAt[ 0 ] = float4( v3Right.xyz , 0.0 );  
  11.     matLookAt[ 1 ] = float4( v3Up.xyz , 0.0 );  
  12.     matLookAt[ 2 ] = float4( v3Look.xyz , 0.0 );  
  13.     matLookAt[ 3 ] = float4( g_vEyePt.xyz , 1.0 );  
  14.     float4x4 matLocal = mul( matLookAt , g_matWorld );  
  15.     float4x4 matWorldView = mul( matLocal ,g_matView );  
  16.     float4x4 matWorldViewProject = mul( matWorldView ,g_matProject );  
  17.     Out.Position = mul( In.Position , matWorldViewProject );  
  18.     Out.TextureUV = In.TextureUV;  
  19.     return Out;  
  20.   }  

三个变量建立起了matLookAt矩阵,再使用此矩阵与世界矩阵相乘后到世界位置.

二.某轴是巨鼎的,大小随远近变化

比如上面的树木的效果,模型只会随Y轴变化而转动.
要建立起轴向固定的布告栏变化矩阵,需要以下几个变量,观察者的位置,向上方向,和被观察的位置.实际上,观察方向在Y轴上的投影为0,所以Y轴不参与变换,即观察变量v3Look = float3(v3Look.x,0.0,v3Look.z),同时 float3 v3Up    = float3( 0.0f , 1.0f , 0.0f ),即v3Up向量也要变为向Y轴的.

[cpp] view plain copy
  1. VS_OUTPUT RenderSceneVS( VS_INPUT In )  
  2.   {  
  3.     VS_OUTPUT Out = ( VS_OUTPUT )0;  
  4.     // 计算此物体的朝向矩阵,首先计算几个向量  
  5.     float3 v3Look  = normalize( + g_vEyePt.xyz - g_vLookAt.xyz );  
  6.     v3Look = float3( v3Look.x , 0.0 , v3Look.z );//重点是这行  
  7.     float3 v3Right = normalize( cross( float3( 0.0f , 1.0f , 0.0f ) , v3Look ));  
  8.     float3 v3Up    = float3( 0.0f , 1.0f , 0.0f );//cross( v3Look , v3Right );  
  9.     // 通过几个向量建立矩阵  
  10.     float4x4 matLookAt ;  
  11.     matLookAt[ 0 ] = float4( v3Right.xyz , 0.0 );  
  12.     matLookAt[ 1 ] = float4( v3Up.xyz , 0.0 );  
  13.     matLookAt[ 2 ] = float4( v3Look.xyz , 0.0 );  
  14.     matLookAt[ 3 ] = float4( g_vEyePt.xyz , 1.0 );  
  15.     float4x4 matLocal = mul( matLookAt , g_matWorld );  
  16.     float4x4 matWorldView = mul( matLocal ,g_matView );  
  17.     float4x4 matWorldViewProject = mul( matWorldView ,g_matProject );  
  18.     Out.Position = mul( In.Position , matWorldViewProject );  
  19.     Out.TextureUV = In.TextureUV;  
  20.     return Out;  
  21.   }  


三.提示信息类,大小与远近距离无关

有时候,需要某种提示信息的广告版技术,即广告板随物体运动,但是大小不会随远近而变换.
这里,此广告板有一些特性,提示框与屏幕对齐,用于实现文字或图形信息.\
这说明广告板的坐标的X轴和Y轴是随着物体变化而变化的.所以广告版的X坐标就是物体X坐标,广告板Y坐标就是物体Y坐标.



面向世界的广告板demo下载