Ogre中的多窗口渲染方法

最近由于工作的关系,希望用一个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的详细分析就留到明天继续吧,哈哈。

posted on 2007-06-16 22:27 雁过无痕 阅读(8711) 评论(5)  编辑  收藏

评论

# re: Ogre中的多窗口渲染方法[未登录] 2008-10-17 10:59 1

明显是要多次createRenderWindow。
每个Window包含所有一个正常Ogre Window的东西。
包括SceneManger , MeshManger等.

似乎那个Root->RenderWindow 属于 1~n 关系。
你没表明。  回复  更多评论   

# re: Ogre中的多窗口渲染方法 2009-05-15 17:21 操你妈

操你妈,把这个页面删了吧  回复  更多评论   

# re: Ogre中的多窗口渲染方法 2010-01-14 14:32 23

没有多窗口渲染的内容 ,文不对题啊  回复  更多评论   

# re: Ogre中的多窗口渲染方法 2011-06-05 11:37 ff

啥也没说  回复  更多评论   

# re: Ogre中的多窗口渲染方法 2012-09-28 19:09 楼主是个傻逼

楼主你是白痴吗?  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航:
博客园   IT新闻   Chat2DB   C++博客   博问  
 
<2007年6月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

导航

统计

常用链接

留言簿(7)

随笔档案

搜索

最新评论

阅读排行榜

评论排行榜