网页功能: 加入收藏 设为首页 网站搜索  
自己写游戏引擎(04)
发表日期:2007-03-28作者:[转贴] 出处:  

  关于RenderTarget类的具体信息,还是放在后面比较好,因为我们还没有设计好shaders的支持、多重纹理的支持,基本场景管理(中的结点)等等。

  先来考虑简单的场景管理,最简单的应该是用Axis-Aligned-box(包围体盒),具体的算法就不说了(当然好像网上很少有讲的很清楚的,还是写完了octree的场景管理之后在总结一下),我们要有一用一个box(8个顶点)来约束我们要渲染的一个物体(或者物体和包围体的集合),简单一点,我们先给每个RenderTarget加上一个AxisAlignedBox,在变换的时候,我们计算这样一个box,然后进行简单的透视体剪裁(在不在视锥体内),再然后就是进行可视性剔除(看不看得见)。我们这里先不涉及剪裁的算法。
 
  设计基本的AxisAlignedBox的接口:
 
namespace UHEngine
{
     class _UHE_Export AxisAlignedBox
     {
     public:
         inline AxisAlignedBox()
         {
              this->m_bInit = false;
         }
 
         inline AxisAlignedBox( Vector3 & minZpoint, Vector3 & maxZpoint )
         {
              this->m_bInit = false;
              Init( minZpoint, maxZpoint );
         }
 
         virtual ~AxisAlignedBox();
 
         /// return true if the box is not initialized.
         inline bool IsNull(){ return !m_bInit; }
 
         /// fresh vertex data of the corners.
         inline void Update();
        
         /// get the corner with the max z val.
         inline const Vector3 & GenMaxZPoint(){ return m_maxZpoint; }
 
         /// get the corner with the min z val.
         inline const Vector3 & GenMinZPoint(){ return m_minZpoint; }
 
         /// update maxZpoint, after changes, usually internal uses.
         inline void GenMaxZPoint(UHEngine::Vector3 &point);
        
         /// update minZpoint, after changes, usually internal uses.
         inline void GenMinZPoint(UHEngine::Vector3 &point);
        
         /// do NOT use GenMaxZPoint after this, it already did that
         inline void SetMaxZPoint(Vector3 &point);
 
         /// do NOT use GenMinZPoint after this, it already did that
         inline void SetMinZPoint(UHEngine::Vector3 &point);
 
         /// create the box, and init all 8 corners
         inline void Init(UHEngine::Vector3 &minZpoint, UHEngine::Vector3 &maxZpoint);
        
         /// make the box bigger with a point
         inline void MergeBox(UHEngine::Vector3 &point);
        
         /// make the box bigger with another box
         inline void MergeBox(UHEngine::AxisAlignedBox &box);
 
         /// get maxZpoint
         inline Vector3 & GetMaxZPoint(){ return m_maxZpoint; }
 
         /// get minxZpoint
         inline Vector3 & GetMinZPoint(){ return m_minZpoint; }
        
     private:
         bool               m_bInit;
         Vector3            m_maxZpoint;
         Vector3            m_minZpoint;
         Vector3            m_corners[8];
     };
}

  在RenderTarget中,我们可以将变换后的点传给AxisAlignedBox的接口MergeBox(Vector3& point );以得到最后的包围体。(场景具体的实现我还没有完成,里面有很多的细节还没有想清楚,网上这个方面的资料比较少,要么就是只讲到原理,所以我还没有找到很有效的办法,来实现RenderTarget生成AxisAlignedBox;还有一个问题是,如何判断一个物理是否可见,要用到Ray来判断,那么Ray的粒度要达到什么程度呢?如果一个Box看不见那么它里面的子树结点也都不可见,但是,如果一个Box把另一个Box遮住,不一定后面的一个 Box就看不见了,这些都是比较麻烦的问题,大家可以想一下自己的实现方法,然后再去看一下网上或者书上是怎么写的)

  关于多重纹理,也是很难管理的东西,还涉及到很多的参数要设置,当然最起码的,我们要定义一些基本的类型,我们把一次pass里面用到的材质,多重纹理(最多8张)看成一个Skin(Skin是卡马克比较喜欢的术语,也有些引擎把这看成材质Material,比如torque)。定义一个枚举类,表示 multi-texture的类型:
 
     typedef enum _multiTexInfo
     {
         BLENDING_ORIGIN = 0,
         BLENDING_DARK_MAPPING,
         BLENDING_ANIMATED_DARK_MAPPING,
         BLENDING_MAT,
         BLENDING_DARKMAP_BLENDING_MAT,
         BLENDING_GLOW_MAPPING,
         BLENDING_DETAIL_MAPPING,
         BLENDING_MODULATE_ALPHA,
         BLENDING_FRAME_BUFFER,
         BLENDING_BUMP,
         BLENDING_HEIGHTMAP
     }MultiTexInfo;

  在后面,渲染器还需要根据不同的类型来设置参数。

  Skin类要包含八张纹理的信息,一张材质的信息(也许后面还需要加入纹理采样的参数信息):
 
namespace UHEngine
{
     class _UHE_Export Skin
     {
     public:
         typedef struct _texInfo
         {
              MultiTexInfo       multiTexInfo;
              UHETEXTURE             *pTex;
         } TEXINFO;
        
         enum TEX_CONST
         {
              MAX_NUM_TEX_PASS = 8, // max num of tex in one pass
         };
 
     public:
         Skin( TextureMng *pTexMng, MaterialMng *pMatMng );
         virtual ~Skin();
        
         TextureMng * GetTexMng();
         MaterialMng * GetMatMng();
        
         /// set num of multi-tex in a pass
         void SetNumTex( int numTex );
 
         /// get num of multi-tex in a pass
         int GetNumTex();
        
         /*
             set tex info and create it in TextureMng,
             feel free to use this interface
             without thingking whether the tex is already created.
         */
         void SetTexInfo( char *chFileName,
              int texIndex,
              MultiTexInfo multiTexInfo = BLENDING_ORIGIN,
              bool bAlpha = false,
              float fAlpha = 1.0f );
 
         /// set mat value of the skin
         /// FIX ME!!! no check for equal mat value
         void SetMatInfo( const UHEMATERIAL *pMat );
        
         /// get tex by index in a pass
         UHETEXTURE * GetTexInMng(int texIndex);
 
         /// get mat value
         UHEMATERIAL * GetMatInMng();
        
     protected:
         TextureMng              *m_pTexMng;
         MaterialMng             *m_pMatMng;
         UHEMATERIAL         m_Mat;
         int                                m_numTex;
 
         TEXINFO                    m_TexInfoGroup[8];
     };
}
 

  简单的实现一下:
 

//File: UHESkin.cpp

#include "UHESkin.h"

 

namespace UHEngine

{

     Skin::Skin(UHEngine::TextureMng *pTexMng, UHEngine::MaterialMng *pMatMng)

         : m_pTexMng(pTexMng), m_pMatMng(pMatMng)

     {

         for( int i = 0; i < MAX_NUM_TEX_PASS; i++ )

         {

              m_TexInfoGroup[i].pTex = NULL;

              m_TexInfoGroup[i].multiTexInfo = BLENDING_ORIGIN;

              /*m_TexInfoGroup[i].texUsage = TEXUSE_ORIGIN;

              m_TexInfoGroup[i].name = "";*/

         }

     }

    

     Skin::~Skin()

     {

     }

    

     inline MaterialMng * Skin::GetMatMng()

     {

         return this->m_pMatMng;

     }

 

     inline TextureMng * Skin::GetTexMng()

     {

         return this->m_pTexMng;

     }

 

     inline void Skin::SetNumTex(int numTex)

     {

         numTex = numTex > MAX_NUM_TEX_PASS ? MAX_NUM_TEX_PASS : numTex;

         this->m_numTex = numTex > 0 ? numTex : 0;

     }

 

     inline int Skin::GetNumTex()

     {

         return this->m_numTex;

     }

 

     void Skin::SetMatInfo(const UHEngine::UHEMATERIAL *pMat)

     {

         if( pMat != NULL )

         {

              memcpy( &this->m_Mat, pMat, sizeof( UHEMATERIAL ) );

         }

     }

 

     void Skin::SetTexInfo(char *chFileName,

                            int texIndex,

                            MultiTexInfo multiTexInfo,

                            bool bAlpha,

                            float fAlpha)

     {

         if( texIndex > 0 && texIndex < MAX_NUM_TEX_PASS )

         {

              /*strcpy( this->m_TexInfoGroup[texIndex].name, chFileName );

              this->m_TexInfoGroup[texIndex].texUsage = texUsage;*/

              this->m_pTexMng->Create( TEXCOORD_2D, TEXUSE_ORIGIN, chFileName, bAlpha, fAlpha );

              this->m_TexInfoGroup[texIndex].pTex = m_pTexMng->GetTexByName( TEXCOORD_2D, chFileName );

              this->m_TexInfoGroup[texIndex].multiTexInfo = multiTexInfo;

         }

     }

 

     UHETEXTURE * Skin::GetTexInMng(int texIndex)

     {

         if( texIndex > 0 && texIndex < MAX_NUM_TEX_PASS )

         {

              return this->m_TexInfoGroup[texIndex].pTex;

         }

         return NULL;

     }

 

     UHEMATERIAL * Skin::GetMatInMng()

     {

         return &m_Mat;

     }

 

}
 
(今天就写到这里。再往后面,有很多的东西,我还没有实现,或者实现得很不好,或者还有一些地方想改进,所以后面的文章会以每个星期一两篇的速度更新,不会再快了。欢迎大家的建议!还是多多交流,just for FUN 的原则。)
我来说两句】 【加入收藏】 【返加顶部】 【打印本页】 【关闭窗口
中搜索 自己写游戏引擎(04)
本类热点文章
  DDraw和D3D立即模式编程手册
  矩阵求逆的快速算法
  本地化支持:OGRE+CEGUI中文输入:OGRE方..
  Direct3D中实现图元的鼠标拾取
  3D场景中的圆形天空顶
  OpenGL显卡编程
  一种高效的基于大规模地形场景的OCCLUS..
  一个完善的读取3DS文件例子
  如何制作一个可控制的人体骨骼模型
  Direct3D 入门之我见
  Slope(斜坡) 法线生成算法,在地形渲染..
  在Direct3D中渲染文字
最新分类信息我要发布 
最新招聘信息

关于我们 / 合作推广 / 给我留言 / 版权举报 / 意见建议 / 广告投放  
Copyright ©2003-2024 Lihuasoft.net webmaster(at)lihuasoft.net
网站编程QQ群   京ICP备05001064号 页面生成时间:0.00952