billboard的原理

 
Billboard( 广告牌 , 公告牌 ) :就是使物体永远面对摄像机 , 摄像机旋转 , 物体也跟着旋转 , 使其始终朝向摄像机 . 我们在 渲染树木 , 灌木丛 , 云,烟等效果时都会用到 .
下面是一个效果演示 :billboard
原理 : 问题的实质就是我们知道结果是物体面对摄像机 , 然后求物体的世界变换矩阵
 
Plocal(0,0,0,1): 局部坐标原点
Pworld: 世界空间内的坐标
Pview:在 视图空间内的坐标
Mworld: 世界变换矩阵
Mview: 视图变换矩阵
PviewOri: 视图空间原点  
Mvtransform: 在视图空间内作的变换
 
关键是求 Mview 的逆矩阵,根据线性代数的知识我们知道正交矩阵的逆矩阵等于其转置矩阵 , 所以我们只要把 Mview 正交化,那么它的逆就等于它的转置矩阵了 , 所以
 
 
由上面的公式可以理解为:
billboard 物体的世界变换矩阵其实就是用物体在视图空间内的变换矩阵乘以视图矩阵的逆 ( 转置 )
ExpandedBlockStart.gif 代码
BOOL Do_Frame()
{
    D3DXMATRIX mat_view, mat_world;

    
//  clear device back buffer
    g_d3d_device -> Clear( 0 , NULL, D3DCLEAR_TARGET  |  D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA( 0 64 128 255 ),  1.0f 0 );
    
//  update the view position
     float  angle  =  ( float ) timeGetTime()  /   2000.0 ;
    
//  构建视图矩阵
    D3DXMatrixLookAtLH( & mat_view,  & D3DXVECTOR3(cos(angle)  *   400.0 200.0 , sin(angle)  *   400.0 ),
        
& D3DXVECTOR3( 0.0 0.0 0.0 ),  & D3DXVECTOR3( 0.0 1.0 0.0 ));
    
//  set view matrix
    g_d3d_device -> SetTransform(D3DTS_VIEW,  & mat_view);

    
//  Begin scene
     if (SUCCEEDED(g_d3d_device -> BeginScene()))
    {
#pragma  region draw ground
        
//  binds a vertex buffer to a device data stream
        g_d3d_device -> SetStreamSource( 0 , g_floor_vb,  0 sizeof (VERTEX));
        
//  set the current vertex stream declation
        g_d3d_device -> SetFVF(VERTEX_FVF);
        
//  assigns a texture to a stage for a device
        g_d3d_device -> SetTexture( 0 , g_floor_texture);
        
//  build world matrix, we only need identity matrix, because we do not need to change original floor position.
        D3DXMatrixIdentity( & mat_world);
        
//  set world matrix
        g_d3d_device -> SetTransform(D3DTS_WORLD,  & mat_world);   
        
//  renders a sequence of noindexed, geometric primitives of the specified type from the current set
        
//  of data input stream.
        g_d3d_device -> DrawPrimitive(D3DPT_TRIANGLESTRIP,  0 2 );
#pragma  endregion

        
//  2) draw the billboards
        g_d3d_device -> SetStreamSource( 0 , g_billboard_vb,  0 sizeof (VERTEX));
        g_d3d_device
-> SetTexture( 0 , g_billboard_texture);
        
//  enable alpha test
        g_d3d_device -> SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
        
// 用当前试图矩阵的转置矩阵作为世界变换矩阵(实际上应该是逆矩阵,只是因为正交矩阵的转置等于逆)        
        D3DXMatrixTranspose( & mat_world,  & mat_view); 
        
// 用这个也是可以的,不过求逆比求转置费D3DXMatrixInverse(&mat_world, &mat_view);
        
//  draw all billboard images
         for ( short  i  =   0 ; i  <   5 ; i ++ )
        {
            
// 对每一个树都先在视图空间内移动到理性的位置,再乘以上面求得的世界矩阵
             for ( short  j  =   0 ; j  <   5 ; j ++ )
            {
                mat_world._41 
=  i  *   80.0   -   160.0 ;
                mat_world._42 
=   0.0 ;
                mat_world._43 
=  j  *   80.0   -   160.0 ;
                g_d3d_device
-> SetTransform(D3DTS_WORLD,  & mat_world);

                
// 这里也可以用下面的代码代替
                 /*
                D3DXMATRIX tempTrans, tempWorld;
                                D3DXMatrixIdentity(&tempTrans);
                                D3DXMatrixTranslation(&tempTrans, i*80.0-160.0, 0, j*80.0-160.0);
                                D3DXMatrixMultiply(&tempWorld, &mat_world, &tempTrans);
                                g_d3d_device->SetTransform(D3DTS_WORLD, &tempWorld);            
*/     
                
//  draw polygon
                g_d3d_device -> DrawPrimitive(D3DPT_TRIANGLESTRIP,  0 2 );
            }
        }
        
//  disable alpha test
        g_d3d_device -> SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
        
//  release texture
        g_d3d_device -> SetTexture( 0 , NULL);
        
//  end the scene
        g_d3d_device -> EndScene();
    }

    
//  present the contents of the next buffer in the sequence of back buffers owned by the device
    g_d3d_device -> Present(NULL, NULL, NULL, NULL);

    
return  TRUE;
}

  下面是代码
 

转载于:https://www.cnblogs.com/bravesailor/archive/2010/01/05/1639528.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值