Evolution3D中的Billboard系统

来源:互联网 发布:boyd holbrook 知乎 编辑:程序博客网 时间:2024/06/07 00:35

其实做一个Billboard系统本身并不难。但是要集成一个使用容易,效率高的Billboard系统还有些技巧的。

主要得问题在于,美术在3Ds Max里可以随意放置很多Billboard,程序导出以后,这些物体通常为单独的Quad。这样就会严重导致渲染的效率低下。

我们希望,美术还是依照自由的方式在场景放置Billboard。设置这些Billboard是可以任意形状,不限于矩形。在导出之前,美术可以将这些物体Attach成一个Mesh。当然也可以导出后由Evolution3D的模型优化工具来塌陷。

与一般物体的区别就在于,美术需要告诉导出插件,这些是一个Billboard物体。


Evol3D系统中的Billboard系统就是为了目的设计。

方案:

1. Billboard面向摄像机的特性在 Vertex Shader中来计算。

2. 模型数据中保存一个平面中心的位置,在Evol3D中,这个数据目前保存在Binormal中。因为一般的Billboard是不会参与法线贴图光照计算的。如果计算那就乱了。


因为在View Matrix,我们可以知道摄像机的UP/Left/等信息。所有只要将当前顶点的位置减去平面中心的位置,然后跟Tangent和Binormal做个点积。 就可知道应该可以计算出这个点在屏幕上的位置了。


这样的Billboard对引擎的上层来说,是极为透明的,只要指定不同的材质就可以了。


VS如下。

PS_INPUT main( VS_INPUT input )
{
      PS_INPUT output = (PS_INPUT)0;
      float4 inPos = input.Pos;
      float4x4 _matWorld = matWorld;
 if(input.Binormal.w <= 0.01f)
 {
 float3 polyCen = input.Binormal.xyz;
 float3 _pos    = vecMul( float4(polyCen.xyz , 1.0f) , _matWorld).xyz;
 float3 _delta  = input.Pos.xyz  - polyCen;


#ifdef _D3D9_
 float3 vX  = float3(matView[0][0] , matView[1][0] , matView[2][0]);
 float3 vY  = float3(matView[0][1] , matView[1][1] , matView[2][1]);
#else  
 float3 vX  = float3(matView[0][0] , matView[0][1] , matView[0][2]);
 float3 vY  = float3(matView[1][0] , matView[1][1] , matView[1][2]);
#endif
 float3 _tan = normalize(input.Tan.xyz);
 float3 _bin = normalize( cross(input.Nor , input.Tan ).xyz);

 float _vLen = dot(_delta.xyz , _bin);
 float _uLen = dot(_delta.xyz , _tan);
 inPos.xyz  = _pos.xyz + _uLen * vX + _vLen * vY;
 }
      
      output.Tex   = float4(input.Tex , 1.0f , 1.0f);
      output.Tex1  = float4(input.Tex1, 1.0f , 1.0f);
      float4 vertexColor  = input.Color.xyzw  * MaterialDiffuse;


      float4   _Position = inPos;
      float4   _Normal   = input.Nor;
      float4   _Tangent  = input.Tan;


    float4x4 matModelView = matMul(_matWorld , matView);
    output.wPosition      = vecMul     ( _Position  , matView     );
    output.wNormal        = transNormal( _Normal    , matModelView);
    output.wTangent       = transNormal( _Tangent   , matModelView);


    output.tPos           = vecMul( output.wPosition  , matProject ); 
    output.Pos            = output.tPos;
    output.Color          = vertexColor;
    output.wPosition.w    = output.Pos.w;
    return output;
}