游戏开发论坛

 找回密码
 立即注册
搜索
查看: 2052|回复: 0

盖莫游戏引擎中的光照系统

[复制链接]

50

主题

69

帖子

69

积分

注册会员

Rank: 2

积分
69
发表于 2010-3-10 15:37:00 | 显示全部楼层 |阅读模式
盖莫游戏引擎中的光照系统
引擎中的光照系统是在就存在了的只是感觉一直有点问题,索性重新设计了.
光照系统的有关对象和单元有:
渲染基类
RenderBase
对象基类
Object
光描述符
LightDesc
光类
Light
光管理器
LightManager
在引擎中我们认识光是一种资源
所以光管理器是从资源管理器中获得的也就是:
RefPtr<LightManager> lightmanager  = resourcemanager->GetLightManager();

引擎的光管理器设计如下:

////////////////////////////////////////////////////////////
//! 定义引擎光管理器
////////////////////////////////////////////////////////////
class LightManager : public Manager<Light,std::string>, public Object  
{               
public:        
    ////////////////////////////////////////////////////////
        //! 构造,析构材质管理器
    ////////////////////////////////////////////////////////
        LightManager(){}
        ~LightManager(){}
public:         

    ////////////////////////////////////////////////////////
    /// 生成一个新的对象
    ////////////////////////////////////////////////////////        
        virtual RefPtr<Light> CreateObject(const std::string& name) = 0;
        virtual RefPtr<Light> CreateObject(const std::string& name, const LightDesc &desc) = 0;

    ////////////////////////////////////////////////////////
    /// 根据脚本数据生成一个新的光对象
    ////////////////////////////////////////////////////////
        virtual RefPtr<Light> CreateObject(const std::string& name, const std::string& script, const std::string &key) = 0;
   
    ////////////////////////////////////////////////////////
        //! 设置,获取全局环境光
    ////////////////////////////////////////////////////////        
    virtual void SetGlobalAmbient(const Color &color) = 0;        
    virtual void GetGlobalAmbient(Color &color) = 0;   
       
    ////////////////////////////////////////////////////////
        //! 应用全局光
    ////////////////////////////////////////////////////////       
        virtual void RenderGlobalAmbient(bool use = true) = 0;
       
    ////////////////////////////////////////////////////////
        //! 获取最大支持光源个数
    ////////////////////////////////////////////////////////        
        virtual uint8 GetMaxLightNumber()const = 0;
       
    ////////////////////////////////////////////////////////
        //! 启用,关闭光源
    ////////////////////////////////////////////////////////        
        virtual void EnableLight() = 0;
        virtual void DisableLight() = 0;
   
    ////////////////////////////////////////////////////////
        //! 获检测是否启用了光源
    ////////////////////////////////////////////////////////      
        virtual bool IsEnableLight()const = 0;
       
        DECLARE_OBJECT(LightManager);
};

唯一需要说明的就是
virtual RefPtr<Light> CreateObject(const std::string& name, const std::string& script, const std::string &key) = 0;
是根据脚本生成名叫name的光对象

再看光类
////////////////////////////////////////////////////////////
/// 定义光源类
////////////////////////////////////////////////////////////
class G_DLL_API Light : public RenderBase
{
public:
    ////////////////////////////////////////////////////////
    /// 构造,析构光源基类
    ////////////////////////////////////////////////////////  
    Light();
    Light(const LightDesc &desc);
    virtual ~Light(){}       

    ////////////////////////////////////////////////////////
    /// 光源类型设置和获取
    ////////////////////////////////////////////////////////        
        void SetLightType(LightType type){this->type = type;}
        LightType GetLightType()const{return type;}
       
    ////////////////////////////////////////////////////////
    /// 光源光参数设置和获取
    ////////////////////////////////////////////////////////
    void SetAmbient(const Color &color){ambient = color;}
    void SetDiffuse(const Color &color){diffuse = color;}
        void SetSpecular(const Color &color){specular = color;}
        Color GetAmbient()const{return ambient;}
        Color GetDiffuse()const{return diffuse;}
        Color GetSpecular()const{return specular;}

    ////////////////////////////////////////////////////////
    /// 光源位置设置和获取(对方向性光源无效)
    ////////////////////////////////////////////////////////
    void SetPosition(const Vector3f& pos){position = pos;}
    Vector3f GetPosition()const{return position;}         
       
    ////////////////////////////////////////////////////////
    /// 光衰减因子设置和获取(对方向性光源无效)(c,l,q)
    ////////////////////////////////////////////////////////       
        void SetAttenuation(const Vector3f &attenuation){this->attenuation = attenuation;}
        Vector3f GetAttenuation()const{return attenuation;}
       
    ////////////////////////////////////////////////////////
    /// 聚光灯参数设置和获取(仅仅对聚光灯有效)
    ////////////////////////////////////////////////////////       
    ////////////////////////////////////////////////////////
    /// 聚光灯方向设置和获取
    ////////////////////////////////////////////////////////               
        void SetSpotLightDirection(const Vector3f &direction){this->spotdirection = direction;}
    Vector3f GetSpotLightDirection()const{return spotdirection;}       
    ////////////////////////////////////////////////////////
    /// 聚光灯光锥角度设置和获取
    ////////////////////////////////////////////////////////
    void SetSpotLightAngle(float angle = 180.0f){this->spotangle = angle;}
    float GetSpotLightAngle()const{return spotangle;}       
    ////////////////////////////////////////////////////////
    /// 聚光灯聚光指数设置和获取
    ////////////////////////////////////////////////////////
    void SetSpotExponent(float exponent = 0.0f){spotexponent = exponent;}       
        float GetSpotExponent()const{return spotexponent;}
protected:
    Color     ambient,diffuse,specular;  
    Vector3f  position;
        LightType type;       
        Vector3f  attenuation;
       
        //! 聚光灯参变量
        Vector3f  spotdirection;
        float     spotangle;
        float     spotexponent;
       
        DECLARE_OBJECT(Light)       
};

代码功能都是很简单的了,从软工角度看该类是一个巨类并不符合严格的设计要求O(∩_∩)O~
再看简单的光配置脚本:

-- 这是盖莫游戏引擎demo中的材质配置脚本
-- maker:核动力机器人

-- 定义一种光属性
light0 =
{
   ambient_red     = 0.4;     
   ambient_green   = 0.3;
   ambient_blue    = 0.2;
   ambient_alpha   = 1.0;
   diffuse_red     = 0.3;
   diffuse_green   = 0.1;
   diffuse_blue    = 1.0;
   diffuse_alpha   = 1.0;   
   specular_red    = 0.2;
   specular_green  = 0.3;
   specular_blue   = 0.2;
   specular_alpha  = 1.0;
   -- 0 for 方向性光源
   -- 1 for 位置性光源
   -- 2 for 聚光灯
   light_type      = 0;  
   position_x      = -10;
   position_y      = -10;
   position_z      = -10;
   -- 光衰减
   attenuation_x   = 1.0;
   attenuation_y   = 0.0;
   attenuation_z   = 0.0;
   -- 聚光灯聚光方向
   spot_dirx       = 1;
   spot_diry       = 1;
   spot_dirz       = -1;   
   -- 聚光灯光锥角
   spot_angle      = 180.0;
   -- 聚光指数
   spot_exponent   = 0.0;
};


-- 定义一种光属性
light1 =
{
   ambient_red     = 0.5;     
   ambient_green   = 0.3;
   ambient_blue    = 0.8;
   ambient_alpha   = 1.0;
   diffuse_red     = 0.3;
   diffuse_green   = 0.1;
   diffuse_blue    = 0.9;
   diffuse_alpha   = 1.0;   
   specular_red    = 1.0;
   specular_green  = 1.0;
   specular_blue   = 1.0;
   specular_alpha  = 1.0;
   -- 0 for 方向性光源
   -- 1 for 位置性光源
   -- 2 for 聚光灯
   light_type      = 2;  
   position_x      =  60;
   position_y      =  60;
   position_z      =  0;
   -- 光衰减
   attenuation_x   = 1.0;
   attenuation_y   = 0.0;
   attenuation_z   = 0.0;
   -- 聚光灯聚光方向
   spot_dirx       = -1;
   spot_diry       = -1;
   spot_dirz       = -1;   
   -- 聚光灯光锥角
   spot_angle      = 29.0;
   -- 聚光指数
   spot_exponent   = 0.3;
};

当前是采用简单的lua表显示配置光的(这样做的一个原因是我还对lua不太熟悉)

再上一段demo程序和贴图
(程序很简单的了只是为了说明问题)

#include <GEngine/Gaimo.hpp>
using namespace std;

//! 字体指针和字体初始化
core::RefPtr<core::Text> font;
bool InitFont(core:evice* device);

//! 光指针2个
core::RefPtr<core:ight> light[2];

//! 定义灯光控制器
sigc::signal<void,int,int> light_controller;
//! 按键回调
void LightCallBack(int button,int status);
//! 输入输出更新
void UpdateInput(core::Device*);

int main(int argc, char **argv)
{
   
    //! 初始化引擎设备并得到设备指针
    core::Device* device = core::InitDevice("盖莫引擎光照测试");
    //! 获取场景管理器指针
    core::RefPtr<core::SceneManager> scenemanager = device->GetSceneManager();
    //! 获取摄像机指针
    core::RefPtr<core::Camera> camera = scenemanager->GetGlobalCamera(Vector3f(100,100,0),
                                                                      Vector3f(),
                                                                      Vector3f(0,1,0));
    //! 设置摄像机参数
    camera->SetViewport(0,0,640,480);
    camera->SetPerspective(45,640.0f/480.0f,3,300);                                                            
    //! 摄像机渲染
    camera->Render();
   
    //! 设置清屏色
    core::Render::SetClearColor(core::Color(0.3f,0.3f,0.6f));
   
    //! 获取资源管理器
    core::RefPtr<core::ResourceManager> resourcemanager = device->GetResourceManager();
   
    //! 获取光管理器指针
    core::RefPtr<core::LightManager> lightmanager = resourcemanager->GetLightManager();
    //! 设置环境光参数
    lightmanager->SetGlobalAmbient(core::Color(0.2f,0.2f,0.2f,1.0f));
    //! 启用环境光
    lightmanager->RenderGlobalAmbient(true);
    //! 启用光源
    lightmanager->EnableLight();
   
    //! 获取光指针(2个)
    light[0] = lightmanager->CreateObject("light1","..\\script//light.lua","light0");
    light[1] = lightmanager->CreateObject("light2","..\\script//light.lua","light1");

    //! 获取材质管理器
    core::RefPtr<core::MaterialManager> materialmanager = resourcemanager->GetMaterialManager();

    //! 获取一个材质指针(我们从脚本中载入材质数据O(∩_∩)O~)
    core::RefPtr<core::RenderBase> material = materialmanager->CreateObject("material","..\\script//material.lua","material");

    //! 字体初始化
    bool flag = InitFont(device);
    if(flag == false)
    {
        ShowMessage(初始化字体失败)        
        device->Close();
        device->Drop();
        return -1;     
    }
   
    GLUquadric* obj = gluNewQuadric();   

    material->Enable();
    material->Render();     
   
    glDepthFunc(GL_LESS);
    glEnable(GL_DEPTH_TEST);   

    light_controller.connect(sigc::ptr_fun(&LightCallBack));   
   
    int fps;
    char text[255];
    BEGIN_LOOP(device)
           glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);       
       fps = device->GetFPS();
       sprintf(text,"fps is: %d",fps);                
       font->Render(540,0,text);
       light[0]->Render();
       light[1]->Render();
       UpdateInput(device);
       gluSphere(obj,16,100,100);
    END_LOOP(device)
   
    gluDeleteQuadric(obj);
   
    device->Close();
    device->Drop();

    return 0;
}

bool InitFont(core::Device* device)
{
    //! 获取文件系统指针
    core::RefPtr<core::FileSystem> filesystem = device->GetFileSystem();

    filesystem->AddToSearchPath("..\\font\\font.zip");
    bool flag = filesystem->IsExists("accid.ttf");
    if(flag == false)
    {   
        return false;
    }      
   
    //! 读取文件数据
    core::RefPtr<core::ReadFile> file = filesystem->OpenRead("accid.ttf");

    //! 使用给定字体文件(ttf)
    font = device->GetResourceManager()->GetText("newfont",file,18);      
   
    (*device->GetLuaStateOwner())->DoFile("..\\script//light.lua");
   
    return true;
}

//! 按键回调
void LightCallBack(int button1,int button2)
{
    static int l1 =0;
    static int l2 = 0;
   
    //! 如果鼠标左键被按下(鼠标左键控制灯光1)
    if(button1 == MOUSE_BUTTON_LEFT)     
    {   
        if(l1 % 2 == 0)
        {   
             font->Render(10,10,"light1 is off");
             light[0]->Disable();               
        }
        else
        {
             font->Render(10,10,"light1 is on");
             light[0]->Enable();                    
        }      
        l1 ++;
    }   
    //! 如果鼠标右键被按下(鼠标右键控制灯光2)
    if(button2 == MOUSE_BUTTON_RIGHT)     
    {   
        if(l2 % 2 == 0)
        {   
             light[1]->Disable();               
        }
        else
        {
             light[1]->Enable();                    
        }      
        l2 ++;
    }
   
    if(light[0]->IsEnable())
        font->Render(10,10,"light1 is on");
    else  
        font->Render(10,10,"light1 is off");  
    if(light[1]->IsEnable())
        font->Render(10,35,"light2 is on");
    else  
        font->Render(10,35,"light2 is off");                        
}

void UpdateInput(core::Device* device)
{
    core::RefPtr<core::Input> input = device->GetInput();
    if(input->IsPressedMouse(MOUSE_BUTTON_LEFT) == true)
    {
        light_controller.emit(MOUSE_BUTTON_LEFT,MOUSE_BUTTON_LEFT);                                            
    }
    else if(input->IsPressedMouse(MOUSE_BUTTON_RIGHT) == true)                                 
    {
        light_controller.emit(MOUSE_BUTTON_RIGHT,MOUSE_BUTTON_RIGHT);                                                  
    }
    else
    {
        light_controller.emit(MOUSE_BUTTON_MIDDLE,MOUSE_BUTTON_MIDDLE);               
    }
}



下面是其贴图(截屏的程序fps总是有点偏低)


您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2024-5-13 12:54

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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