查看: 1505|回复: 4

关于帧速的几个问题

[复制链接]

该用户从未签到

发表于 2014-5-22 11:48:46 | 显示全部楼层 |阅读模式
            这几天在处理如何稳定帧速的过程中基本上看遍了论坛的帖子,但是基本上都达不到我的要求,但是也有些问题没有搞明白,在这里看看有没有大神理解,希望能为小弟解惑:

1.我希望的是将场景的帧速稳定在100,最开始是按照FreeSouth视频中的处理方法,即在while循环里的frame前后记录它的时间,在决定是否睡眠,可是这个的效果实在不怎么好,在看视频时也发现了这个问题,就是最开始FreeSouth将帧速稳定在10时效果也还可以,但是他后来将帧速稳定在30时效果就不怎么好了,误差已经有2-3左右了,在我将帧速稳定在100的测试过程中有些时候即时帧速到90了。

2.然后在论坛中搜索与帧稳定性相关的帖子,有两个帖子的解决方法是通过设置setRunMaxFrameRate函数:
http://www.osgchina.org/forum.ph ... amp;_dsign=3aed1ada
http://www.osgchina.org/forum.ph ... amp;_dsign=fdf5b991
最开始我使用setRunMaxFrameRate函数后没效果,后来查看OSG的源码,发现这个函数是在ViewBase类的run函数中调用的,而我的工程是使用while循环里加入frame函数实现的,所以设置这个函数没用,然后看setRunMaxFrameRate函数的源码,发现和1中FreeSouth的方法基本上是一样的,甚至处理的更粗糙一些。

3.然后发现了一个同样需要定时刷新的帖子,我这个要稳定帧速的需求和定时刷新感觉是一样的:
http://www.osgchina.org/forum.ph ... amp;_dsign=9b5eaf3f
array在里面说使用on demand模式,然后我在OSG的源码中也发现了这个模式,这个模式也是在ViewBase类的run函数中调用的,这是这个枚举变量的定义:
  1.         enum FrameScheme
  2.         {
  3.             ON_DEMAND,
  4.             CONTINUOUS
  5.         };
复制代码

然后在ViewBase类的run函数的使用方法如下:
  1. int ViewerBase::run()
  2. {
  3.     if (!isRealized())
  4.     {
  5.         realize();
  6.     }

  7.     const char* run_frame_count_str = getenv("OSG_RUN_FRAME_COUNT");
  8.     unsigned int runTillFrameNumber = run_frame_count_str==0 ? osg::UNINITIALIZED_FRAME_NUMBER : atoi(run_frame_count_str);

  9.     while(!done() && (run_frame_count_str==0 || getViewerFrameStamp()->getFrameNumber()<runTillFrameNumber))
  10.     {
  11.         double minFrameTime = _runMaxFrameRate>0.0 ? 1.0/_runMaxFrameRate : 0.0;
  12.         osg::Timer_t startFrameTick = osg::Timer::instance()->tick();
  13.         if (_runFrameScheme==ON_DEMAND)
  14.         {
  15.             if (checkNeedToDoFrame())
  16.             {
  17.                 frame();
  18.             }
  19.             else
  20.             {
  21.                 // we don't need to render a frame but we don't want to spin the run loop so make sure the minimum
  22.                 // loop time is 1/100th of second, if not otherwise set, so enabling the frame microSleep below to
  23.                 // avoid consume excessive CPU resources.
  24.                 if (minFrameTime==0.0) minFrameTime=0.01;
  25.             }
  26.         }
  27.         else
  28.         {
  29.             frame();
  30.         }

  31.         // work out if we need to force a sleep to hold back the frame rate
  32.         osg::Timer_t endFrameTick = osg::Timer::instance()->tick();
  33.         double frameTime = osg::Timer::instance()->delta_s(startFrameTick, endFrameTick);
  34.         if (frameTime < minFrameTime) OpenThreads::Thread::microSleep(static_cast<unsigned int>(1000000.0*(minFrameTime-frameTime)));
  35.     }

  36.     return 0;
复制代码

然后去看checkNeedToDoFrame这个函数的源码,发现它与我想象的不一样,它不是那种类似回调的实现,就是发送一个信号后就进入下一帧,这样就不知道如何使用定时刷新了,FrameScheme和checkNeedToDoFrame的含义是什么?array说使用ON_DEMAND模式到底是什么意思?


4.最后就是这个帖子了:
http://www.osgchina.org/forum.ph ... amp;_dsign=8dad14e5
这里面最开始说的是使用OnTimer函数,这个函数和MFC的定时器是一个原理吗?可是如何让这个函数来控制仿真的时间?
然后FlySky在下面的答复中是可以使用simulationTime时间来控制帧速,我又查看源码发现这个变量是很多函数的形参,并且有默认值0,可是如何通过这个变量来控制帧率?
FreeSouth在下面的说法是使用硬招,于是我尝试可不可以把垂直同步打开,然后修改显示器的刷新频率为100,这样要是能成功的话帧速应该可以稳定在100,可是显示器里的刷新频率没法手动设置啊?还有就是这种设置方法是1s渲染100帧后休息,还是平均0.01s渲染一帧?这两个概念对我而言是完全不同的。
最后array回复是不是表示显示器的刷新频率没法手动设置了?

问题有点多,希望大家懂的能帮忙解决下,谢谢!

该用户从未签到

发表于 2014-5-22 16:12:17 | 显示全部楼层
本帖最后由 cenfer 于 2014-5-22 16:59 编辑

1. 想将场景的帧速稳定在100,前提条件是frame()的执行时间小于1/100,不然是不可能的。
也就是说,想保持某个帧率,每帧的实际执行时间必须小于这个目标帧率的帧时间。

2. 解析下ViewerBase::run()


         //获得环境变量设置的总帧数,如果为0,把总帧数设置为无穷大
         const char* run_frame_count_str = getenv("OSG_RUN_FRAME_COUNT");
         unsigned int runTillFrameNumber = run_frame_count_str==0 ? osg::UNINITIALIZED_FRAME_NUMBER : atoi(run_frame_count_str);
         
        //_runFrameScheme 字面意思是:Frame的执行策略
        if (_runFrameScheme==ON_DEMAND) //按要求执行frame(),
        {
            if (checkNeedToDoFrame())  //有重绘要求则重绘,checkNeedToDoFrame()判断是否有各种重绘的标志
            {
                frame();
            }
            else  //没有重绘要求,不要占用CPU,休息0.01秒,
            {
                if (minFrameTime==0.0) minFrameTime=0.01;
            }
        }
        else    //循环执行frame(),默认模式
        {
            frame();
        }

该用户从未签到

发表于 2014-5-23 11:31:25 | 显示全部楼层
关闭显示器的垂直同步之后,当然可以达到更高的帧速率,同时CPU占用应该也会占满。而且对于显示的需求来说,高于60Hz是没有什么意义的
LED显示屏也不可能随便设置刷新频率,通常就是60或者75Hz。传统的CRT显示器可以设置到120Hz左右

该用户从未签到

 楼主| 发表于 2014-6-17 19:17:59 | 显示全部楼层
cenfer 发表于 2014-5-22 16:12
1. 想将场景的帧速稳定在100,前提条件是frame()的执行时间小于1/100,不然是不可能的。
也就是说,想保持 ...

场景不限速时帧率能达到200多。

该用户从未签到

 楼主| 发表于 2014-6-17 19:21:56 | 显示全部楼层
array 发表于 2014-5-23 11:31
关闭显示器的垂直同步之后,当然可以达到更高的帧速率,同时CPU占用应该也会占满。而且对于显示的需求来说 ...

thx
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

联系我们

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