查看: 6920|回复: 17

一种提高osg帧率的设想,欢迎讨论

[复制链接]

该用户从未签到

发表于 2014-4-1 16:49:19 | 显示全部楼层 |阅读模式
  当待加载数据比较多或待并入场景的节点体积比较大时,程序常常会卡顿,必须承认,这暴露了数据源优化得不够或者调度策略上的不足,但是能否通过重写databasepager内部分函数的方式来改善这种状况呢?以下提出本人改动databasepager的一种设想:
  当多线程完成待读节点队列(read_queue)的构建以及pagedlod节点的加载后,紧接着会更新场景(updategragh()),除了从场景中去除过期节点,还会将待加入的数据并入场景中(addLoadedDataToSceneGraph)。我们可以修改待加入数据并入场景这一步,不要直接把待合并列表(_dataToMergeList)里的节点一次性置换(swap)给本地文件加载列表(localFileLoadedList),因为这样的话renderingTraversals()时需要完成所有本地文件加载列表中节点的渲染工作,这些节点可能很多,也可能很复杂。这里,我们试着让合并列表中的节点一次只置换一个节点到本地文件加载列表中,那么渲染遍历阶段的任务势必会减少很多,这时在程序中看到的效果是pagedlod节点一个个依次出现在场景中,从而有效缓解卡顿现象,提高了帧率。
      以上是本人的设想,希望大家能提出其中的缺陷,我这边暂时没有实现,重写databasepager后无法正常渲染,代码实现上还有点问题,所以不确定这种提高帧率的法子是否可行。我相信很多朋友可能已经通过类似的策略有效提高了帧率,希望能给点提示或者好的建议,先谢过!
  

该用户从未签到

 楼主| 发表于 2014-4-1 21:33:30 | 显示全部楼层
自己顶一下,期待高人留言!

该用户从未签到

发表于 2014-4-1 21:57:03 | 显示全部楼层
这样做可以缓解一次读入大量数据卡顿的问题,但是并不能提高帧率。大部分情况下用户对3、4秒钟的载入时间并不是很敏感,反而读入一个模型卡一下会影响操作流畅性。所以大部分游戏和软件都是采取一次性读取的方式。

该用户从未签到

发表于 2014-4-1 22:15:37 | 显示全部楼层
就反问楼主一句,你不是一次调入,假定一点一点的调入,最后不还是那么多数据载入场景?渲染不还是一样要遍历所有的载人节点?
pagedlod节点的原理和你的思想一致吗?(并不是把所有的数据都依次载人吧,是根据设定的范围载入对应的节点吧)

该用户从未签到

 楼主| 发表于 2014-4-1 22:32:04 | 显示全部楼层
可能我没讲得解释足够情况,是这样的,某帧pagedlod节点是在多线程的情况下被载入的,这里载入不仅是入列,而是通过readnode给读入到内存了,在rendertraversal前可能是读了一个,也可能是读了很多个吧(这点我不确定),执行databasepager中的updategraph时,不管_dataToMergeList列表swap到几个,都需要在一帧内渲染(至少是试图在一帧内渲染),我是想通过减少从列表中swap出datarequest的数量来减少渲染时间,从而间接提高帧率,下一帧接着把_dataToMergeList列表中节点渲染至场景。这样,3楼说的情况应该不会发生,渲染层每一帧的压力减至一个节点了,应该不至于卡顿;至于4楼提到的情况,我是把多个节点通过配合多线程载入逐帧输出到场景,即把定量的节点分更多帧渲染到场景,量没变,但分更多帧完成了。

该用户从未签到

发表于 2014-4-1 22:40:04 | 显示全部楼层
你还是看看ARRAY的“最长的一帧”吧!
就再问你一句,你场景是不是一帧一帧的显示?你第一帧显示A,第二帧就不显示A,这是个什么场景(闪烁OR动画)?

该用户从未签到

 楼主| 发表于 2014-4-1 23:03:09 | 显示全部楼层
回复4楼,我是想突出这个一边多线程读入节点,一边分步渲染的过程,compile过程会建立几何体与纹理资源的映射吧,它不用反复去建立的吧,而且,卡顿过程都发生在所有渲染节点都被加入到环境中的那一帧吧,一旦加入到节点中的节点,下一帧再被扫时我是感受不到卡顿的。通过这种分步渲染的方式提高帧率的方法我是见到过的,只是不知道别人是用的什么手段罢了,所以才有了上面的猜想,希望您能继续提宝贵建议。

该用户从未签到

发表于 2014-4-1 23:18:04 | 显示全部楼层
多线程思想是对的,但切入点不对!
你应该是考虑与pagedlod相同的原理,想办法把每一帧中渲染的节点减少,而不是把节点分散到延后帧中,那是做静态渲染,如3DMAX渲染静态图片的类似效果!
    每一帧中渲染的节点:可以采取动态载入相机一定范围内的节点(LOD思想),不是把所有节点都载入,只载入可视范围内的节点!

该用户从未签到

发表于 2014-4-2 21:32:54 | 显示全部楼层
我在别的帖子里应该说过,卡顿的问题是资源的编译,而非单纯加载数据造成的。因为新加载的数据在下一帧会突然大量传入到OpenGL管线,生成纹理、显示列表、VBO等资源,因此造成突然的frame drop。OSG里面已经有应对的方法即incrementalCompileOperation

当然您说的方案也是可以的,我以前已经实现过了,效果还是不错的;以前的DoPreCompile选项也有类似的作用(不过新版本已经被替代)

该用户从未签到

 楼主| 发表于 2014-4-2 22:30:43 | 显示全部楼层
array 发表于 2014-4-2 21:32
我在别的帖子里应该说过,卡顿的问题是资源的编译,而非单纯加载数据造成的。因为新加载的数据在下一帧会突 ...

敢问锐总,如果用incrementalcompileoperation解决卡顿的话该怎么做呢?我在发帖前曾试过setMaximumNumOfObjectsToCompilePerFrame(),但是改善不明显,有哪种设置方式可以达到我所描述的那种方案效果呢?如果光简单设置还不够的话,还想问问您具体是怎么做到的,非常希望能得到您的提点!!

该用户从未签到

发表于 2014-4-4 09:07:02 | 显示全部楼层
感觉也是可行,卡顿就是上一帧和下一帧渲染内容相差太多的缘故。想办法平衡这些应该可以解决,你的想法是有道理的

该用户从未签到

 楼主| 发表于 2014-4-9 22:52:42 | 显示全部楼层
谢谢大家,谢谢array;设想一个星期前已经实现了,一定程度上降低了渲染速度,但卡顿感基本消失,现在有了新的目标,想通过预先查阅_dataToMergeList列表,对其中的databaserequest进行识别分类,让vpb地形或者大个儿节点率先渲染到场景,其它节点再依次渲染,如何是好?试过标记父节点名字,然后nodevisitor遍历追索进行识别的方式,可能是因为节点本身并未进入树形节点结构,遍历失败。还是想请教下大家,看看有没有什么好法子,还是自己先顶一下!

该用户从未签到

发表于 2014-4-12 08:54:30 | 显示全部楼层
array 发表于 2014-4-2 21:32
我在别的帖子里应该说过,卡顿的问题是资源的编译,而非单纯加载数据造成的。因为新加载的数据在下一帧会突 ...

应该使用这个方法。
OSG的DataBasePager是支持在载入模型之后进行预编译的(实际上就是将Image变成OpenGL的纹理句柄,DisplayList创建好,等等)。
载入卡顿就是没有预编译所导致的,你打开开关之后,卡顿现象直接消失,不信你自己试试看,也就几行代码就可以打开这个开关,自己去找啦。

该用户从未签到

发表于 2014-4-12 14:36:26 | 显示全部楼层
消除卡顿的问题实际上很容易解决,倒是如何改进OSG来提高帧率,是一个值得考虑的问题。当场景图的规模很大的时候,怎么提高帧率呢?

通常对于GIS系统,尤其是类似GoogleEarth那样的Globe系统,往往一个视口内部的OSG节点就非常多,而且每一个节点都有自己的MatrixTransform,实现坐标变换所用。

CullVisitor每一帧都要遍历整个场景图,若场景图比较大,肯定会比较慢,帧率上不来。
其实我现在也面临了这种问题,现在初步设想,是将cullVisitor里头做一个线程池,因为场景图基本上不会出现环状,因此在一帧之内,是可以做到并行的Cull的。

这也只是一个设想,对于单核的CPU,这种并行根本提升不了帧率。当前我不考虑单核的CPU,现在的电脑一般都是i5以上的配置。这里需要解决的是渲染台的线程安全性,以及那几个fastStack的线程安全性问题。
不知道是否有人做过这方面的尝试,效果如何呢?

该用户从未签到

发表于 2014-4-20 20:35:36 | 显示全部楼层
OSG的线程模式中已经有并行的Cull,不过肯定是针对多个Context的并行。不太可能针对一个场景图;因为就算没有环,也有共享子节点的问题存在
CullVisitor单纯遍历整个场景的消耗,通常并不像您想象的那么大,除非您是完全并列的节点关系,那样在节点图上已经不合理了

该用户从未签到

发表于 2014-5-6 19:55:43 | 显示全部楼层
array 发表于 2014-4-20 20:35
OSG的线程模式中已经有并行的Cull,不过肯定是针对多个Context的并行。不太可能针对一个场景图;因为就算没 ...

锐总: 我现在想让 一个root节点 被多个 viewer 执行view->setSceneData(root);发现这样的结果是 root节点在多个view中出现 纹理图无法一起渲染的问题。 纹理被一个view渲染了,其它view(camera)就看不到了吗?或者,你有实现过 类似VP的 channel的显示效果吗?

该用户从未签到

发表于 2014-5-16 17:08:54 | 显示全部楼层
为什么不直接用CompositeViewer
您需要登录后才可以回帖 登录 | 注册

本版积分规则

OSG中国官方论坛-有您OSG在中国才更好

网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

联系我们

  • 工作时间:09:00--18:00
  • 反馈邮箱:1315785073@qq.com
快速回复 返回顶部 返回列表