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