游戏学院 - 游戏开发、游戏制作、游戏策划




相关推荐

我的分类(专题)

日志更新

最新评论

留言板

链接

Blog信息
 
网上最新排行信息





自己写游戏引擎1
gamezz 发表于 2006-8-14 10:57:44
写了几个月的游戏引擎,有一些想法需要总结结一下,也想和同我水平差不多的朋友,或者比我水平还要菜的cn们分享一下,高手莫笑~~
这里的想法是,尽量和大家分享我的过程,我写的东西很烂(我的确这样觉得),我会在文中写下来我觉得还存在问题的地方,需要改进的地方,或者还没有想到很好解决的地方;希望同大家相互讨论,也非常欢迎高手们的建议和批评.Just for FUN! OK.
(ps:文中的代码都是片断,these don’t compile,如果你想要部分代码,可以和我联系,在引擎完成得差不多的时候我会邮给你,我的邮箱:xjyhust@gmail.com or xjyhust@126.com. )
 
       目标是写一个多渲染器的游戏引擎,先来谈其中的图形渲染部分,毕竟这个是关键,如果你想了解物理,网络或者其他的内容,很遗憾,这里没有(也许要等到很后面的了)。可以看一下我之前写的两篇blog,《游戏引擎中多渲染器的设计与实现》(1,2),里面讲到了用动态链接库实现的一种的方法,这里就不复习了,假设你已经完成了前面最基本的实现。
       引擎的核心部分是一切的前提,所以我们从这里开始。我强烈建议你在开始动手之前先看一下常用的3d模型的格式的解析——因为引擎的底层的基本数据类型的设计是非常重要,而且在后面是相当难以改动的——看一下常用的模型格式的解析,可以帮助你设计合理的底层数据类型(这里指的是像 纹理,材质,三角形等的表示)。先以MilkShape 3D的格式MS3D为例。在他们的网站上,你可以下到一个C++解析组件,先看头文件中的数据类型:
typedef struct
...{
    byte    flags;                                      // SELECTED | SELECTED2 | HIDDEN
    float   vertex[3];                                  //
    char    boneId;                                     // -1 = no bone
    byte    referenceCount;
} ms3d_vertex_t;

typedef struct
...{
    word    flags;                                      // SELECTED | SELECTED2 | HIDDEN
    word    vertexIndices[3];                           //
    float   vertexNormals[3][3];                        //
    float   s[3];                                       //
    float   t[3];                                       //
    byte    smoothingGroup;                             // 1 - 32
    byte    groupIndex;                                 //
} ms3d_triangle_t;

typedef struct
...{
    word edgeIndices[2];
} ms3d_edge_t;

typedef struct
...{
    byte            flags;                              // SELECTED | HIDDEN
    char            name[32];                           //
    word            numtriangles;                       //
    word*            triangleIndices;                    // the groups group the triangles
    char            materialIndex;                      // -1 = no material
} ms3d_group_t;

typedef struct
...{
    char            name[32];                           //
    float           ambient[4];                         //
    float           diffuse[4];                         //
    float           specular[4];                        //
    float           emissive[4];                        //
    float           shininess;                          // 0.0f - 128.0f
    float           transparency;                       // 0.0f - 1.0f
    char            mode;                               // 0, 1, 2 is unused now
    char            texture[128];                        // texture.bmp
    char            alphamap[128];                       // alpha.bmp
} ms3d_material_t;

       从代码中可以看出,Texture和Material都有name,都有fileName(指的是贴图文件名),Material中有4中颜色(这和图形学里面的物理意义也是一致的),然后就是Texture可以是alpha贴图,有属性transparency,这些都可以作为我们设计的参考。我们就停在这里,在后面我们还会看到这个经典的格式是怎样影响了我们的渲染批次的设计的。
     开始建立基础的数据类型:
    typedef struct _colorStruct
    ...{
        float r;
        float g;
        float b;
        float a;
    }UHECOLOR;

    typedef struct _materialStruct
    ...{
        UHECOLOR Diffuse;
        UHECOLOR Ambient;
        UHECOLOR Specular;
        UHECOLOR Emissive;
        float Power;
    }UHEMATERIAL;

    typedef struct _textureStruct
    ...{
        bool    bAlpha;
        float   fAlpha;
        char    chName[128];
        void    *pData;
        WORD    texType;
        WORD    texUsage;
    }UHETEXTURE;

    这里很奇怪的是,我在Texture里面用了一个void*。恩,这个是用来存储不同API中的纹理。比如,如果是用的DX,我会一直把这个void*看成LPDIRECT3DTEXTURE9*。在引擎中,我会大量的用到指针间的静态转换(非运行时)(hard core c++高手看到我的代码会说应该用static_cast,而不是用c语言里面的(typename)(…)。恩,我同意,只是有时候我忘了,或者懒了)。
    有很多的引擎,会将Texture单独的抽象成一个类,有相应的行为(成员函数);但是,我觉得,Texture的实质是一堆数据,既然Texture Manager(纹理管理器,简记为TextureMng)是必要的,那么单独的Texture的类的设计似乎没有太多的必要,我们有TextureMng的管理,这样似乎足够了,我暂时不想把事情搞得太复杂。
(ps:面对对象是很好的方法,但是引擎中的很多“东西”的实质还是数据的集合,在把他们变成类之前,考虑一下于他们相关的操作,考虑一下用类实现一些很小的数据体的时候效率的影响。。。像Quake3和Ogre就是两个设计的极端,是不是有时候结合两者会好一些?)
       还有很多的数据类型要写,比如很多的3D中的数学类,像Vector3,Matrix4,先把他们放一下。我比较喜欢迭代开发的感觉——用比较短的周期,作出简单的可运行的程序,然后在改进。好,我们就以dx sdk里面的例子开始,先实现一个Vertex的例子。
       我们需要定义一个VertexBuffer的抽象类,来给GL和DX提供公共的接口。
//file: UHEVertexBuffer.h
#ifndef _INCLUDE_UHEVERTEXBUFFER_H
#define _INCLUDE_UHEVERTEXBUFFER_H

namespace UHEngine
...{
    class _UHE_Export VertexBuffer
    ...{
    public:
        // init and malloc a bunch of memory.
        virtual void    Create( UINT length, DWORD dwFVF, DWORD dwUsage, DWORD dwPoolType )     = 0;

        // lock the whole buffer.
        // then can write to the buffer using GetLockedData() .
        virtual void    Lock()                                                                 = 0;

        // unlock the locked data.
        virtual void    Unlock()                                                             = 0;

        // delete .
        virtual void    Release()                                                             = 0;
        
        // return the vertex buffer.
        // ex. in dx, this would be trans to LPDIRECT3DVERTEXBUFFER9 .
        virtual void    *GetVertexBuffer()                                                     = 0;
        
        // return the addr of buffer after method Lock() .
        virtual void    *GetLockedData()                                                     = 0;
        
        // return FVF type of vertex in the buffer.
        virtual DWORD    GetFVF()                                                             = 0;
        
        // return the length of buffer( actual length in memory ).
        virtual UINT    GetLength()                                                             = 0;
        
        // return Usage of vertex in the buffer.
        virtual DWORD    GetUsage()                                                             = 0;
        
        // reutrn pool management type.
        virtual DWORD   GetPoolType()                                                         = 0;
    };
}
#endif
(ps:多渲染器引擎中,用抽象类(纯虚类)是一种实现中的设计,即使用不同的API的底层实现,对于用户来说,都是同一接口)
       在DX9渲染器中我们加入文件,UHEDX9VertexBuffer.h和UHEDX9VertexBuffer.cpp。
//file: UHEDX9VertexBuffer.h
#ifndef _INCLUDE_UHEDX9VERTEXBUFFER_H
#define _INCLUDE_UHEDX9VERTEXBUFFER_H

#i nclude "UHEDX9RenderBase.h"
#i nclude "UHEVertexBuffer.h"

namespace UHEngine
...{
    class _UHE_Export DX9VertexBuffer : public VertexBuffer
    ...{
    public:
        DX9VertexBuffer( LPDIRECT3D9 &pDX9, LPDIRECT3DDEVICE9 &pDevice )            ;
        ~DX9VertexBuffer()                                                            ;

        void    Create( UINT length, DWORD dwFVF, DWORD dwUsage, DWORD dwPoolType ) ;
        void    Lock()                                                                ;
        void    Unlock()                                                            ;
        void    Release()                                                            ;
        
        void    *GetVertexBuffer() ...{ return (void*)m_pDXVertexBuffer; }                ;
        void    *GetLockedData() ...{ return (void*)m_pData; }                            ;
        DWORD    GetFVF() ...{ return m_dwFVF; }                                        ;
        UINT    GetLength() ...{ return m_length; }                                    ;
        DWORD    GetUsage() ...{ return m_dwUsage; }                                    ;
        DWORD   GetPoolType()...{ return m_dwPoolType; }                                ;    
                                                                                     
    private:
        LPDIRECT3D9                    m_pDX9              ;
        LPDIRECT3DDEVICE9            m_pDevice          ;

        LPDIRECT3DVERTEXBUFFER9        m_pDXVertexBuffer ;
        void                        *m_pData          ;
        bool                        m_bIsLocked          ;

        DWORD                        m_dwFVF              ;
        UINT                        m_length          ;
        DWORD                        m_dwUsage          ;
        DWORD                        m_dwPoolType      ;
    };
}
#endif
       在UHEDX9VertexBuffer.cpp中,完成这些实现(看一下dx sdk,没有什么值得多说的了)

转自:gameres


阅读全文 | 回复(0) | 引用通告 | 编辑
 


发表评论:

    昵称:
    密码:
    主页:
    标题:

 游戏学院推荐:

 游戏学院总部  北京游戏学院  重庆游戏学院  成都游戏学院  西安游戏学院  华卓武汉游戏学院  长沙游戏学院  游戏学院数字基地校区  游戏制作联盟

 更多游戏制作信息:

 在google搜索游戏制作, 在yahoo搜索游戏制作, 在baidu搜索游戏制作 

 在google搜索游戏学院, 在yahoo搜索游戏学院, 在baidu搜索游戏学院

 其它推荐:

 进口轴承FAG轴承SKF轴承NSK轴承INA轴承IKO轴承大型轴承德国轴承轴承日本轴承


Powered by Oblog.