| 
 | 
 
盖莫游戏引擎中的光照系统  
引擎中的光照系统是在就存在了的只是感觉一直有点问题,索性重新设计了. 
光照系统的有关对象和单元有: 
渲染基类 
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总是有点偏低) 
 
 
  |   
 
 
 
 |