探索未知种族之osg类生物---器官初始化四
上一节我们对完成了对osg生物内部非常重要器官graphicsContext的初始化工作。这样就可保证我们场景中至少有一个graphicContext存在,不至于刚出生就面临夭折。我们根据上一节中osg代码的研究也就知道了,在我们正常使用osg时,是怎么完成对camera以及graphicContext的创建的了。
回到Viewer::realize()中我们继续向下看,现在我们对osg::DisplaySettings以及osg::GraphicsContext::WindowingSystemInterface,有了新的认识,我在这里再补充一张camera,graphicContext以及windowingSystemInterface的关系图有利于大家进一步了解osg的内部组成。
回到Viewer::realize()中我们继续向下看,得到所有的GraphicsContext,遍历所有的GraphicsContext,然后判断是否设置了同步交换缓冲区(这一般是渲染的最后一步),这是osg提供的多机同步swapbuffer机制,他会默认调用内置的swapbuffer的回调函数(osg::SyncSwapBuffersCallback中,作用主要是等待client端的同步锁,实现多机同步执行swapbuffer)。如果developer想干预的话 可以调用 osg::GraphicsContext::setSwapCallback(SwapCallback* rc)来设置自定义的缓存交换回调。自定义的回调必须调用GraphicsContext::swapBuffersImplementation()函数.
再根据所依据的平台(windows,linux,mac等)默认制定的,或者用户后期修改的最大纹理池和最大对象缓冲池的大小,进一步对各个graphicsContext的相应属性值进行设置。然后正式完成对graphicsContext的初始化定义,下一步就是通过调用gc.realize()来使graphicsContext处于可用的状态。Osg::GraphicsContext::realize()函数的实现都是在它的继承类中通过realizeImplementation()函数完成的。
特别是windows平台的实现,使用windows+opengl的同学对这一段GraphicsWindowWin32::realizeImplementation()函数肯定非常了解,因为这里会涉及到很多windows平台特有的一些属性,就不做过多的介绍了,以后有机会我会再写一份opengl的入门教程,其中肯定会提到函数中涉及的东西。敬请期待。
当GraphicsContext可用了,就需要更新上下文gc->makeCurrent()。那我们就看看GraphicsContext::makeCurrent()完成了什么工作。
gc->makeCurrent()
GraphicsContext::makeCurrent()首先判断opengl与osg是否是同一个线程,(使用qt5+osg3.x的同学一定遇到过osg的threadmode只能设置singlethread。其他三种threadmode都会报一个同样的错误,错误的原因就是这里。至于怎么完美的结合qt5与osg3,请移步到我的github下 https://github.com/JimmieKJ/osgQTWidget 有具体的实现细节)。其实GraphicsContext::makeCurrent()的根本是通过调用子类的makeCurrentImplementation()实现。
当我们移步到bool GraphicsWindowWin32::makeCurrentImplementation()同样会发现,这里和使用opengl的程序有很大的相同之处,其实就是把dc和rc进行绑定。当makeCurrentImplementation返回true的时候,就代表graphicsContext更新成功。然后就是opengl的思路,需要解绑hc和rc防止资源浪费,这就需要调用gc->releaseContext(),其实就是调用子类的releaseContextImplementation()函数。
再次聚焦到realize函数上(/src/osgViewer/Viewer.cpp::realize()函数),_incrementalCompileOperation,用于预编译GraphicContext,主要作用是,想在程序运行开始时就加在一个资源文件但是又不想或者没有到显示到界面的时机,则会用到这个预加载操作。具体的用法如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
//从Viewer获取 osgUtil::IncrementalCompileOperation的指针: osgUtil::IncrementalCompileOperation* pIcompOperation = viewer.getIncrementalCompileOperation(); //从Viewer获取 osgUtil::IncrementalCompileOperation的指针: // 创建compileSet: osg::ref_ptr compileSet = osgUtil::IncrementalCompileOperation::CompileSet(NODE, true ); //从CompileCompletedCallback派生新类,然后重写Completed函数,在内部隐藏节点: //将 派生类 绑定到 compileSet。 compileSet->compileSet->_compileCompletedCallback = newCompileCompletedCallback; //设置 IncrementalCompileOperation 过期策略 pIcompOperation->setCompileAllTillFrameNumber(50); 再往下就是使鼠标聚焦到osg的绘制窗口上这个一个功能。 // initialize the global timer to be relative to the current time. osg::Timer::instance()->setStartTick(); // pass on the start tick to all the associated event queues setStartTick(osg::Timer::instance()->getStartTick()); // configure threading. setUpThreading(); |
首先调用 osg::Timer::setStartTick 函数,启动 OSG 内部定时器并开始计时。
随后, Viewer::setStartTick 函数的工作是找到当前视景器和所有 GraphicsContext 设备的事件队列_eventQueue,并设定它们的启动时刻为当前时间。下一行是调用 ViewerBase::setUpThreading 函数(这个多线程问题我们以后再深入讨论)
请回到 realize 函数,现在这个函数的执行已经接近了尾声,不过我们又遇到了一个问题:编译上下文(也就是 Compile Contexts,)如果要启用它的话并不困难,只需要在调用 realize 之前执行:osg::DisplaySettings::instance()->setCompileContextsHint(true);随后,正如您在 realize 函数的 最后一个for循环看到的,系统将设法遍历所有可能的GraphicsContext 设备,针对它们分别再各自添加一个新的 GraphicsContext 设备(也就是说如果系统中已经有了数个图形上下文,那么现在又将新增同样数量的图形上下文与之对应),所用的函数为 GraphicsContext::getOrCreateCompileContext。
这之后,分别执行了创建图形线程,设置 CPU 依赖性,以及启动图形线程的工作,具体的实现内容可以暂时忽略。观察 getOrCreateCompileContext 函数的内容,很快我们就可以发现其中的重点:这些新增的 GraphicsContext 对象使用了 pBuffer 的特性,并与对应的已有对象共享同一个图形上下文(Traits::sharedContext 特性)。事实上,这是 OSG 利用 OpenGL 的像素缓存(Pixel Buffer)技术,为图形上下文的后台编译提供的一种新的解决方案。这样不仅可以提高图形刷新的速度,还可以方便用户为某一特定的 GraphicsContext 设备添加特殊的处理动作,方法是使用osg::GraphicsContext::getCompileContext 获取后台图形上下文,再使用 GraphicsContext::add函数向其中追加 osg::Operation 对象,类似的例子可以参看 osgterrain。
欢迎大家来我的新家看一看 3wwang个人博客-记录走过的技术之路
探索未知种族之osg类生物---器官初始化四的更多相关文章
- 探索未知种族之osg类生物---器官初始化一
我们把ViewerBase::frame()比作osg这类生物的肺,首先我们先来大概的看一下‘肺’长什么样子,有哪几部分组成.在这之前得对一些固定的零件进行说明,例如_done代表osg的viewer ...
- 探索未知种族之osg类生物---器官初始化三
当判断到viewer中没有一个graphicContext可用时,osg就会默认的进行一次对viewer的实现操作,这样可以保证osg以后可以安心的在屏幕上进行作画.那我们就来看看这个osgViewe ...
- 探索未知种族之osg类生物---器官初始化二
那我们回到ViewerBase::frame函数中来,继续看看为什么osg生命刚刚出生的时候会大哭,除了初始化了eventQuene和cameraManipulator之外还对那些器官进行了初始化.在 ...
- 《探索未知种族之osg类生物》目录
精力有限,博客园不在更新<探索未知种族之osg类生物>.在这里列出所有文章目录(持续更新)有兴趣的同学可以看看. 探索未知种族之osg类生物[目录] 前序 探索未知种族之osg类生物--- ...
- [转][osg]探索未知种族之osg类生物【目录】
作者:3wwang 原文链接:http://www.3wwang.cn/html/article_58.html 前序 探索未知种族之osg类生物---起源 ViewBase::frame函数中的Vi ...
- 探索未知种族之osg类生物---状态树与渲染树以及节点树之间的关系
节点树 首先我们来看一个场景构建的实例,并通过它来了解一下“状态节点”StateGraph 和“渲染叶”RenderLeaf 所构成的状态树,“渲染台”RenderStage 和“渲染元”Render ...
- 探索未知种族之osg类生物---起源
任何程序都是有生命的,是生命就需要呼吸.例如普通的windows程序,当运行完main()函数后,就需要进入消息循环,来监听用户的各种操作,以便做出及时的回应.这样的每次循环就像生命的每次呼吸,来维持 ...
- 探索未知种族之osg类生物---渲染遍历之器官协作
好了,现在我们经过三节的介绍我们已经大体上明确了单线程模型(SingleThreaded)下 OSG 渲染遍历的工作流程.事实上无论是场景的筛选render还是绘制cull工作,最后都要归结到场景视图 ...
- 探索未知种族之osg类生物---呼吸分解之事件循环一
事件循环和更新循环 终于到了我们嘴里经常念叨的事件循环.更新循环以及渲染循环了.首先我们来区分一下事件循环和渲染循环,他们两个首先是两个不同顺序执行的过程,我们有时候会用到任意node的updateC ...
随机推荐
- 吴裕雄 python 机器学习-DMT(1)
import numpy as np import operator as op from math import log def createDataSet(): dataSet = [[1, 1, ...
- Java的学习03
今天依然记录一下,学习情况,可以看到自己每一天都在进步. import java.text.DateFormat; import java.text.ParseException; import ja ...
- Dictionary在多线程情况下
Add时出错 错误信息: Index was outside the bounds of the array. 详细信息: at System.Collections.Generic.Dictiona ...
- NBU 还原LINUX ORACLE 数据库(EHR)
一.E-HR数据库(全备)恢复 目录 一.E-HR数据库(全备)恢复... 1 1. 使用bplist 命令读取备份文件... 1 2. 启动到nomount状态... 2 3. 利用rman还原控制 ...
- 安装 pygame,找不到Python version 2.7
今天在安装pygame时出错,提示“Python version 2.7 required, which was not found in the registry”,经过网上查找资料后发现只需要新建 ...
- 如何用 Postman 处理 json请求格式
下边是其他博友写的 http://blog.163.com/huan12_8/blog/static/130519090201611711213719/
- Unity 场景分页插件 World Streamer 支持无限大地图的解决方案(二)
Terrain Streaming 可以用WorldCreator创建Tile地形,然后用WorldStreamer实现分块地图.比如10000*10000(16平方公里) 的地形,需要1000*10 ...
- JSON Extractor
JMeter处理responses 的json 对于请求1返回的结果,处理以后作为请求2的参数,JMeter提供了JSON 提取器 比如 responses 返回: {"statusCode ...
- stm32DMA
源和目标地址必须按数据传输宽度对齐 支持循环的缓冲器管理 可编程的数据传输数目:最大为65536 每一个通道都有一组寄存器 DMA_CPARx.DMA_CMARx是没有差别的,它们都可以存放外设的地址 ...
- html5文件读取+按钮样式重置+文件内容预览
FileReader读取文件详细介绍请访问:http://www.cnblogs.com/xyyt/p/9066882.html FileReader提供了如下方法: readAsArrayBuffe ...