Ogre中的多窗口渲染方法

来源:互联网 发布:阿里云服务器默认账号 编辑:程序博客网 时间:2024/06/05 06:44

最近由于工作的关系,希望用一个3D图形引擎实现棋牌类的2D游戏桌面。为了提供尽可能好的兼容性,选择了Ogre作为后台渲染引擎,因为它的评价在开源3D引擎中很不错,而且同时支持Opengl和D3D,所以没有多想就选择了它。到后期才发现,Ogre虽然是号称“Object Oriented Graphics Render Engine”,而且确实在场景,相机,窗口等等的三维对象的建模上做得相当不错,但是其对于OCP等原则的遵循仅仅是大面上,Ogre中随处可见一些巨大的对象类。所以要扩展它或者重用它的部分功能简直是太困难了,不得已而抛弃了Ogre。这倒不一定是Ogre的错,因为Ogre定位于游戏制作的,追求的是最新最酷的特效,这样肯定很难从一开始就抽象好的。而且它要同时支持Opengl和D3D,这也是一个抽象的困难点。

虽然没有使用Ogre,但是对于Ogre中多窗口渲染方式的实现还是很下了一番功夫的,不想这些功夫白白浪费,还是把它写出来与所有人共享吧。

为了提供同一个用户同时打多局游戏的可能,所以采用Ogre的话必须支持多桌面渲染,这里有两点需要考虑:

1. 窗口渲染而不是全屏幕渲染

2. 多窗口渲染,每一个窗口使用不同的三维场景数据。

先说说Ogre如何做到窗口渲染吧。Ogre中对应每一个渲染窗口有一个RenderWindow对象,该对象通过Root的CreateRenderWindow方法创建,为了与现有的GUI窗口兼容,我不希望Ogre为我产生新的HWND,而是把一个HWND作为参数传递给CreateRenderWindow方法,这是通过以下方法做到的:

Ogre::NameValuePairList parms;
parms["externalWindowHandle"] = Ogre::StringConverter::toStrin((long)hwnd);
bool bFullScreen = false; RECT rect; ::GetWindowRect(hwnd, &rect);
int windowWidth = rect.right - rect.left;
int windowHeight = rect.bottom - rect.top;
Ogre::RenderWindow* window = m_OgreRoot->createRenderWindow(windowName, windowWidth, windowHeight, bFullScreen, &parms);

关于多窗口渲染,则需要先说说Ogre中的场景结构:

如图所示,Ogre中一切起源于Root对象,它负责产生和销毁所有Manager。SceneManager负责管理场景数据,所以为了实现多窗口,必须要有多个SceneManager实例,SceneManager中包含MovableObject,顾名思义,MovableObject是场景中可以运动的物体,SceneManager中还有一些静止不变的数据,比如Terrain等等,图中并未列出。MovableObject如果不挂在SceneNode上在场景中是无法显示出来的,一个SceneNode上可以挂多个MovableObject,这样组织成一棵场景树的结构,值得一提的是MovableObject是无法共享的,也就是说它只能挂在一个SceneNode下,想共享的话,只有使用Mesh了。Mesh由MeshManager产生,它定义了基本几何形状。一辆汽车可以同时在场景多个部分出现,显然不需要每一辆汽车创建一个几何形状,公用一个Mesh即可,这正是Entity的工作方式。Entity还提供了位置,动画等信息的封装。

有了多个SceneManager之后如何让这些场景渲染到指定的多个窗口上呢。这要通过Camera和Viewport实现。这里也正是Ogre设计得比较精巧的地方。Camera定义了观察者从哪个位置以及角度观察场景,以及可以观察的范围(视角,最远与最近位置等等),而RenderWindow通过Camera创建一个自身的Viewport,使得场景可以渲染到RenderWindow上。具体的渲染机制我并没有深入研究,在Root中应该有相关代码。

说了这么多,还是来看看Ogre中多窗口渲染的代码吧

Ogre::NameValuePairList parms;
parms["externalWindowHandle"] = Ogre::StringConverter::toString((long)hwnd);

RECT rect;
::GetWindowRect(hwnd, &rect);
int windowWidth = rect.right - rect.left;
int windowHeight = rect.bottom - rect.top;
Ogre::RenderWindow* window = m_OgreRoot->createRenderWindow(ogreNameFactory::applyWindowName(), windowWidth, windowHeight, false, &parms);

// Create SceneManager
m_SceneManager = m_OgreRoot->createSceneManager(Ogre::ST_GENERIC, ogreNameFactory::applySceneManagerName());
// Set ambient light
m_SceneManager->setAmbientLight(Ogre::ColourValue(1.0, 1.0, 1.0));

//Create Camera
m_Camera = m_SceneManager->createCamera(ogreNameFactory::applyCameraName());
m_Camera->setProjectionType(Ogre::PT_ORTHOGRAPHIC);

m_Camera->setFixedYawAxis( true, Ogre::Vector3(0, -1, 0) );
//// Position it at 500 in Z direction
m_Camera->setPosition(Ogre::Vector3(Ogre::Real(windowWidth)/2.0, Ogre::Real(windowHeight)/2.0, -260));
//// Look back along -Z
m_Camera->lookAt(Ogre::Vector3(Ogre::Real(windowWidth)/2.0, Ogre::Real(windowHeight)/2.0, 0));

m_Camera->setFOVy(Ogre::Degree(180.0 - 1.6416));
m_Camera->setNearClipDistance(5);
m_Camera->setFarClipDistance(271);

// Create one viewport, entire window
Ogre::Viewport* vp = window->addViewport(m_Camera);
vp->setBackgroundColour(Ogre::ColourValue(0,0,0));

//// Alter the camera aspect ratio to match the viewport
m_Camera->setAspectRatio(Ogre::Real(windowWidth) / Ogre::Real(windowHeight));

////Used for Hittest

Ogre::Ray aimRay = m_Camera->getCameraToViewportRay( 0, 0 );
m_RaySceneQuery = m_SceneManager->createRayQuery(aimRay);

// Make window active and post an update
window->setActive(true);
window->update();

代码中与相机设置相关的部分看不懂美关系,关于相机的设置,我会在另一篇文章中详细分析之。以上的代码将成功的在hwnd上初始化渲染环境,现在要做得就是在SceneManager中添加Entity了,需要重绘的时候调用RenderWindow的update()即可。

时间不早了,打算今晚去星美看通宵电影,关于Camera的详细分析就留到明天继续吧,哈哈。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 北京怎么办残摩行驶证 报考驾照三年到期了怎么办 车辆违章扣3分怎么办 驾照过期忘审了怎么办 外省港澳证办了居住证怎么办 电动车交警罚单丢了怎么办 在外地开车违章扣分怎么办 郑州车在外地扣分违章怎么办 电工证掉了应该怎么办 毕业回国美国驾照过期了怎么办 a2驾驶证4年没交体检报告怎么办 中国驾照在美国丢了怎么办 拿了驾照不敢开车怎么办 刚拿驾照不敢上路怎么办 雅思考试作文格式写错了怎么办 英国银行卡注销后钱怎么办 本科毕业有毕业证没有学位证怎么办 莫名收到平安一账通验证码怎么办 新车没带行驶证怎么办 深圳行驶证副本丢了怎么办 新车行驶证是怎么办的 新车怎么办牌和行驶证 b本扣12分了怎么办 车的绿本丢了怎么办 车辆落户查不到购车发票怎么办 扣车凭证丢了怎么办 三轮车驾驶证被扣了怎么办 违章12分不够扣怎么办 忘记带行驶证了怎么办 开车不带行驶证怎么办 屏幕没碎黑屏了怎么办 三星s6屏幕不亮怎么办 苹果手机掉水里屏幕黑屏怎么办 三星s6电池不耐用怎么办 台式电脑显示屏坏了怎么办 三星笔记本电脑不显示韩文怎么办 三星s6开不开机怎么办 电脑显示屏显示检测信号线怎么办 三星s8屏幕坏了怎么办 手机挤压漏液了怎么办 三星显示器跳白色线条怎么办动