上一节我们对完成了对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类生物---器官初始化四的更多相关文章

  1. 探索未知种族之osg类生物---器官初始化一

    我们把ViewerBase::frame()比作osg这类生物的肺,首先我们先来大概的看一下‘肺’长什么样子,有哪几部分组成.在这之前得对一些固定的零件进行说明,例如_done代表osg的viewer ...

  2. 探索未知种族之osg类生物---器官初始化三

    当判断到viewer中没有一个graphicContext可用时,osg就会默认的进行一次对viewer的实现操作,这样可以保证osg以后可以安心的在屏幕上进行作画.那我们就来看看这个osgViewe ...

  3. 探索未知种族之osg类生物---器官初始化二

    那我们回到ViewerBase::frame函数中来,继续看看为什么osg生命刚刚出生的时候会大哭,除了初始化了eventQuene和cameraManipulator之外还对那些器官进行了初始化.在 ...

  4. 《探索未知种族之osg类生物》目录

    精力有限,博客园不在更新<探索未知种族之osg类生物>.在这里列出所有文章目录(持续更新)有兴趣的同学可以看看. 探索未知种族之osg类生物[目录] 前序 探索未知种族之osg类生物--- ...

  5. [转][osg]探索未知种族之osg类生物【目录】

    作者:3wwang 原文链接:http://www.3wwang.cn/html/article_58.html 前序 探索未知种族之osg类生物---起源 ViewBase::frame函数中的Vi ...

  6. 探索未知种族之osg类生物---状态树与渲染树以及节点树之间的关系

    节点树 首先我们来看一个场景构建的实例,并通过它来了解一下“状态节点”StateGraph 和“渲染叶”RenderLeaf 所构成的状态树,“渲染台”RenderStage 和“渲染元”Render ...

  7. 探索未知种族之osg类生物---起源

    任何程序都是有生命的,是生命就需要呼吸.例如普通的windows程序,当运行完main()函数后,就需要进入消息循环,来监听用户的各种操作,以便做出及时的回应.这样的每次循环就像生命的每次呼吸,来维持 ...

  8. 探索未知种族之osg类生物---渲染遍历之器官协作

    好了,现在我们经过三节的介绍我们已经大体上明确了单线程模型(SingleThreaded)下 OSG 渲染遍历的工作流程.事实上无论是场景的筛选render还是绘制cull工作,最后都要归结到场景视图 ...

  9. 探索未知种族之osg类生物---呼吸分解之事件循环一

    事件循环和更新循环 终于到了我们嘴里经常念叨的事件循环.更新循环以及渲染循环了.首先我们来区分一下事件循环和渲染循环,他们两个首先是两个不同顺序执行的过程,我们有时候会用到任意node的updateC ...

随机推荐

  1. thymeleaf 的标准表达式

                                              

  2. 吴裕雄 python 机器学习-KNN算法(1)

    import numpy as np import operator as op from os import listdir def classify0(inX, dataSet, labels, ...

  3. 吴裕雄 19-Mysql 连接的使用

    JOIN 按照功能大致分为如下三类:INNER JOIN(内连接,或等值连接):获取两个表中字段匹配关系的记录.LEFT JOIN(左连接):获取左表所有记录,即使右表没有对应匹配的记录.RIGHT ...

  4. Python 如何创建2维空数组

    http://blog.csdn.net/yockie/article/details/46127829 myList = [ ( [0] * 3 ) for i in range(4) ] > ...

  5. 升级tensorflow1.0到1.3,报错ImportError: libcudnn.so.6: cannot open shared object file: No such file or directory Failed to load the native TensorFlow runtime.

    先定位问题,发现在 /usr/local/cuda/include/ /usr/local/cuda/lib64/ 下面只有 libcudnn.so.5 因此,只要下载cudnn6.*版本的文件分别覆 ...

  6. 使用qt creator4.XXX,b编辑和调试caffe,太好用了

    一直想看caffe的源代码,网上看了一个qt的例子,但是自己也有qt creator,怎么就不行 后面发现是自己的版本太低所以不好用(可能是自己能力有限) 可以参考下面这个链接: 使用qt creat ...

  7. BeanFactory的实现原理

    先来看看Java代码获取Spring中Bean的代码(一共有五种方式,这里只展示其中一种方法): 有没有发现上面的代码与利用反射实现工厂模式的代码很相似.对,你没有看错,Spring中的BeanFac ...

  8. Elasticsearch搜索异常-------org.elasticsearch.common.io.stream.NotSerializableExceptionWrapper: parse_exception

    异常问题: Caused by: org.elasticsearch.index.query.QueryShardException: Failed to parse query [LOL: Uzi和 ...

  9. 05_ssm基础(二)之mybatis优化

    06.mybatis优化之Mybatis工具类提取 优化原则(见官方文档): mybatis工具类存放位置: mybatis工具类代码: package com.day01.ssm.mybatisDe ...

  10. ArrayList集合类

    ⦁ 集合概述A:我们学习的是面向对象编程语言,而面向对象编程语言对事物的描述都是通过对象来体现的. 为了方便对多个对象进行操作,我们就必须对这多个对象进行存储,而要想对多个对象进行存储, 就不能是一个 ...