查看: 1699|回复: 3

osgmotionblur例子

[复制链接]

该用户从未签到

发表于 2013-7-30 23:46:53 | 显示全部楼层 |阅读模式
该例子演示了运动模糊的效果。
以下内容是转自网上的:
原理:
引用内容
对于运动画面,将当前帧画面与上一帧画面进行alpha融合,以产生出残影——运动模糊效果。
通过使用累积缓存来完成这项工作。
OpenGL提供一个累积缓存,可以用来存储当前指定的颜色缓存里面的内容,并进行一定的运算操作。
通过函数glAccum可以对累积缓存进行操作。

glAccum介绍如下:
引用内容
void glAccum(GLenum op, GLfloat value)
op值用于指定操作类型,包括:
GL_ACCUM    从指定的颜色缓存里面读取像素数据,将其像素值(R, G, B, A)乘以value的结果加上累积缓存里面的值以后再保存到累积缓存;
GL_LOAD     从指定的颜色缓存里面读取像素数据,将其像素值乘以value的结果直接保存到累积缓存;
GL_ADD      将累积缓存里面的像素值与value相加以后保存到累积缓存;
GL_MULT     将累积缓存里面的像素值与value相乘以后保存到累积缓存;
GL_RETURN   将累积缓存里面的像素值乘以value以后保存到指定的颜色缓存;
在这个例子中,用到了GL_MULT、GL_ACCUM、GL_RETURN。
在主程序中osg:isplaySettings::instance()->setMinimumNumAccumBits(8,8,8,8);设置了积累缓冲区各位数。
然后,osgViewer::Viewer::Windows windows;
    viewer.getWindows(windows);
    for
(osgViewer::Viewer::Windows::iterator itr = windows.begin();
        itr !=
windows.end();
        ++itr)
    {
        (*itr)->add(new MotionBlurOperation

(persistence));
    }在视景体中每个图形窗体都添加了MotionBlurOperation类,MotionBlurOperation继承Operation,在virtual void operator () (osg::Object* object)方
法中如果是第一次渲染,则清楚积累缓冲区的值,glClearColor(0, 0, 0, 0);         
glClear(GL_ACCUM_BUFFER_BIT);
之后,glAccum(GL_MULT, s);
        glAccum(GL_ACCUM, 1 - s);
        glAccum(GL_RETURN, 1.0f);通过这三个函数计算。
我们一个一个的进行说明,首先,glAccum(GL_MULT, s);积累缓冲区中的值乘以s,结果写进积累缓冲区中,glAccum(GL_ACCUM, 1 - s);然后,颜色缓冲区中的值乘以1-s,结果写入积累缓冲区中,最后,glAccum(GL_RETURN, 1.0f);把积累缓存区中的值乘以1,写入颜色缓存区中,完成运动模糊的效果,这里可以看出积累缓冲区中的值只有一份,是每一帧不同比率的一个累计,也就是说第一帧的累计效果也是存在的,只是随着帧数的增加,第一帧的影像比率趋近于0了。这几个函数中不难得出,s值越大,前几帧的效果存在的时间越长,运动模糊效果越明显,如果s趋近于1,程序将很长时间是黑屏,因为glClearColor(0, 0, 0, 0);glClear(GL_ACCUM_BUFFER_BIT);积累缓冲区颜色值为黑色,s趋近于1,第一帧的影像非常大,所以很长时间一直为最初的颜色——黑色。

这里必须要深入研究一下,glAccum应用的时刻,以上的说明中可以看出,glAccum应该是一帧中颜色缓冲区中的值计算完之后应用,在这个例子中用了otionBlurOperation,
MotionBlurOperation继承Operation。我们就看看Operation是做什么的。到了Operation的定义,说它是实现图形操作的基类,子类必须重写virtual void operator () (Object*) = 0;方法,实现相应的功能。在GraphicsContext类中typedef std::list< ref_ptr<Operation> > GraphicsOperationQueue; GraphicsOperationQueue              _operations;定义了一个Operation类型的一个链表,这个链表又在什么地方应用的了?还回到GraphicsContext::runOperations()中,记得上一篇osgmemorytest例子中,提到过GraphicsContext::runOperations(),在这里实现(*(camera->getRenderer()))(this);渲染工作。这一次我们又找的了这个函数,(*_currentOperation)(this);遍历_operations这个链表,然后执行每个Operation中的operator () (Object*)方法,从runOperations()这个函数中,我们知道了osg的渲染过程,先进行渲染,然后在执行_operations中的操作。
我们回到例子中,MotionBlurOperation这个类,把它加入到了所有的图形上下文中osgViewer::Viewer::Windows windows;    viewer.getWindows(windows);
    for

(osgViewer::Viewer::Windows::iterator itr = windows.begin();
        itr !=
windows.end();
        ++itr)
    {
        (*itr)->add(new MotionBlurOperation
(persistence));
    },glAccum函数执行的时候正好和我们之前所判断的一样,先渲染,渲染后对颜色缓存区中的值进行累积。

对这个例子和积累缓冲区总算有了一些理解,但这里还存在一个问题,如果想只对场景中的某个部分做运动模糊应该如何处理???比如有一个足球场,一个运动中的足球,只对这个足球进行运动模糊处理,如何去做???

这个问题自己还没有去验证,自己想的一个大概方法是,相同位置的的两个相机,一个关注足球之外的场景,不做运动模糊处理;另外一个只关注足球,做运动模糊处理,然后,两幅场景融合为一个场景。

该用户从未签到

发表于 2013-7-31 07:45:52 | 显示全部楼层
good

该用户从未签到

发表于 2013-8-4 17:32:33 | 显示全部楼层
技术发展到今天,再做运动模糊无疑应该用shader的方法

该用户从未签到

发表于 2013-8-4 17:42:18 | 显示全部楼层
楼上正解~
支持分享~~
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

联系我们

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