游戏开发论坛

 找回密码
 立即注册
搜索
查看: 2139|回复: 1

自己写游戏引擎——Get Your Hands Dirty(04 )

[复制链接]

22

主题

191

帖子

217

积分

中级会员

Rank: 3Rank: 3

积分
217
QQ
发表于 2006-8-12 05:37:00 | 显示全部楼层 |阅读模式
      关于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.pTex = NULL;

              m_TexInfoGroup.multiTexInfo = BLENDING_ORIGIN;

              /*m_TexInfoGroup.texUsage = TEXUSE_ORIGIN;

              m_TexInfoGroup.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 的原则。)

22

主题

191

帖子

217

积分

中级会员

Rank: 3Rank: 3

积分
217
QQ
 楼主| 发表于 2006-8-12 05:37:00 | 显示全部楼层

Re: 自己写游戏引擎——Get Your Hands Dirty(04 )

原文位置:
http://blog.csdn.net/xjyhust/archive/2006/08/12/1052907.aspx
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-25 02:29

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表