|
本帖最后由 gisthink 于 2013-6-7 23:29 编辑
第一次在osgchina中写东西。之前的老家是http://blog.csdn.net/yungis
osgmemorytest这个例子也从一帧入手。
eventTraversal();
updateTraversal();
renderingTraversals();
事件回调、更新回调、渲染。
OpenGL是状态机,调整好各个状态,然后绘制几何体。OSG中同理,renderingTraversals中根据每个StateSet绘制Drawable。无论是加载的模型还是自己绘制的几何体,最后都是Drawable。
renderingTraversals中最主要的还进行了剔除(CullVisitor),这里不多说,主要说OSG中OpenGL的状态的执行。
进入renderingTraversals函数内部,找到(*itr)->runOperations();(对于单线程来说),这句话进行了场景的绘制工作。顺着这个藤一直摸下去,为了思路清晰,列出序号:
1、调用了GraphicsContext::runOperations();
2、在GraphicsContext::runOperations()中找到(*(camera->getRenderer()))(this);
3、跟到了Renderer中的void Renderer:perator () (osg::GraphicsContext* context)
{
if (_graphicsThreadDoesCull)
{
cull_draw();
}
else
{
draw();
}
}。
4、在Renderer的draw方法中找到了 sceneView->draw();
5、如果不需要立体显示,在 sceneView->draw();中会找到_renderStage->drawPreRenderStages(_renderInfo,previous);
_renderStage->draw(_renderInfo,previous);
6、然后执行了RenderStage中的drawInner
7、RenderBin::draw(renderInfo,previous);
8、drawImplementation(renderInfo,previous);
9、RenderLeaf* rl = dw_itr->get(); rl->render(renderInfo,previous);
10、state.apply(rg->getStateSet());_drawable->draw(renderInfo);最终实现绘制
好复杂的一条路了,对于多线程而言与以上的步骤有些不同,但大体差不多。
几个重要的类,GraphicsContext--Renderer--SceneView--RenderStage(RenderBin)--RenderLeaf--Drawable。
最终的实现都在具体的Drawable中,就像上面说的,无论是加载的模型还是自己绘制的几何体,最后都是Drawable。这样最终会调用可用的Drawable实现绘制。
以上这么一条复杂的路线,要重点说的是第10步中的state.apply(rg->getStateSet());
下面从这个调用说起,State存储了OpenGL需要的所有的状态,是OSG与OpenGL状态的接口,进入这个函数中看看做了什么。
在这个函数中找到了applyAttributeList(_attributeMap,dstate->getAttributeList());这么一句话,深入下去。循环调用了applyAttribute这个函数,而传递的就是StateAttribute,这就是OSG中某个状态属性,在applyAttribute中找到了attribute->apply(*this);状态属性执行了apply把State传入进去。进入StateAttribute中的apply,不禁大失所望,什么也没有??
StateAttribute是基类,打开API文档,看看继承StateAttribute的状态属性吧,有几十个之多,我们重点找几个看看。
Fog,进入Fog的Fog::apply(State& state),在这里看见了OpenGL函数,glFogi以及一系列的设置。
PolygonOffset,进入PolygonOffset的PolygonOffset::apply(State&),在这里看见了glPolygonOffset执行多边形偏移。
Texture2D,进入Texture2D::apply(State& state),在这里看见了glTexImage2D。
...
attribute->apply(*this)这么短短的一句话,就执行了所有状态属性的设置。
这篇文章的标题是osgmemorytest,怎么绕了这么多?下面回到osgmemorytest例子中。
定义了好多的基类,MemoryTest、GLObject、GLMemoryTest。
有用的是ContextTest,osg::ref_ptr<osg::GraphicsContext> window = osg::GraphicsContext::createGraphicsContext(traits.get());创建了GraphicsContext,根据pbuffer来决定是PixelBuffer还是Window。
StateAttributeObject中执行了_attribute->apply(*renderInfo.getState());看到这里就知道了为什么上面说了那么多,都是在说这个类的作用。
TextureTest中最终都调用了StateAttributeObject。
FboTest中也调用了StateAttributeObject。
DrawableObject调用了_drawable->draw(renderInfo);
GeometryTest调用了DrawableObject中的函数。
从以上几个类的功能来说,不难看出他们所作的事情,1、创建窗口;2、设置状态;3、绘制;
因此整个的例子大体上描绘了OSG渲染的一个过程,而main函数中所做的就是创建窗口、设置状态、绘制。打印出contexts数目,objects applied次数已经执行所用的实际。 |
|