查看: 2805|回复: 3

根节点设置更新回调后,子节点stateset的uniform变量的update无效

[复制链接]

该用户从未签到

发表于 2011-3-21 11:27:46 | 显示全部楼层 |阅读模式
本帖最后由 qingfeng5211 于 2011-3-21 11:40 编辑

由于需要动态添加节点,我给根节点加入了更新回调

  1. //mRoot是根节点       mRoot = new osg::Group;
  2. mRoot->setDataVariance(osg::Object::DYNAMIC);
  3. mAddRemoveCallback = new CAddRemoveCallback();   //CAddRemoveCallback继承自NodeCallback
  4. mRoot->setUpdateCallback(mAddRemoveCallback);
复制代码


我需要实现这样的功能:给一个Cylinder实现水效果的纹理,用的代码是Array的myocean,我在添加函数中设置了cylinder的stateset,添加了uniform,如下:
  1. osg::StateSet* stateset = geode->getOrCreateStateSet();       //geode是要添加的子节点Cylinder
  2.         osg::Shader* vertexShader = new osg::Shader( osg::Shader::VERTEX );
  3.         osg::Shader* fragmentShader = new osg::Shader( osg::Shader::FRAGMENT );
  4.         vertexShader->loadShaderSourceFromFile( "D:\\Program Files\\OpenSceneGraph\\data\\ocean.vert" );
  5.         fragmentShader->loadShaderSourceFromFile( "D:\\Program Files\\OpenSceneGraph\\data\\ocean.frag" );

  6.         osg::Program* program = new osg::Program;
  7.         program->addShader( vertexShader );
  8.         program->addShader( fragmentShader );
  9.         stateset->setAttributeAndModes( program, osg::StateAttribute::ON );

  10.         osg::Uniform* param1 = new osg::Uniform( "LightPos", osg::Vec3(1.0, 1.0, 0.0) );
  11.         stateset->addUniform( param1 );
  12.         osg::Uniform* param2 = new osg::Uniform( "time", 0.0f );
  13.         param2->setUpdateCallback( new updateShader );
  14.         stateset->addUniform( param2 );
  15.         osg::Uniform* param3 = new osg::Uniform( "normalMap", 0 );
  16.         stateset->addUniform( param3 );
  17.         osg::Uniform* param4 = new osg::Uniform( "cubeMap", 1 );
  18.         stateset->addUniform( param4 );

  19.         osg::Image* image = osgDB::readImageFile( "D:\\Program Files\\OpenSceneGraph\\data\\water.bmp" );
  20.         osg::Texture2D* tex = new osg::Texture2D( image );
  21.         tex->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
  22.         tex->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
  23.         tex->setWrap(osg::Texture::WRAP_R, osg::Texture::REPEAT);
  24.         tex->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR);
  25.         tex->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
  26.         stateset->setTextureAttributeAndModes( 0, tex, osg::StateAttribute::ON);
  27.         stateset->setTextureAttributeAndModes( 1, readCubeMap(), osg::StateAttribute::ON);

复制代码


添加后,水的纹理效果出来了,但是水波没有变化,是固定的。我调试了一下,发现代码中设置的uniform的更新回调没有起作用——调试时updateShader类的operator()函数没有进入


  1. osg::Uniform* param2 = new osg::Uniform( "time", 0.0f );
  2. param2->setUpdateCallback( new updateShader );
复制代码


但是当我注释掉
  1. //mAddRemoveCallback = new CAddRemoveCallback();
  2. //mRoot->setUpdateCallback(mAddRemoveCallback);
复制代码
这两行代码,也就是去掉根节点的回调,就水纹就会变化,可以进入updateShader类的operator()函数,一切正常了。

考虑了半天也没想明白是什么原因?请大家指点指点。

未命名.JPG

该用户从未签到

发表于 2011-3-21 15:09:17 | 显示全部楼层
您的CAddRemoveCallback的内容是什么,它是否在operator()的末尾进行了节点树的继续traverse()?

该用户从未签到

 楼主| 发表于 2011-3-21 15:24:55 | 显示全部楼层
回复 2# array


operator函数里只是添加和删除节点啊。 我还发现,直接对根节点设置这个stateset,无论有没有添加CAddRemoveCallback,水纹理都是正常的,可以变化的,子节点就不变了。


  1. void CAddRemoveCallback:perator()(osg::Node * node, osg::NodeVisitor * nv)
  2. {
  3.         if(!_paused)
  4.         {
  5.                 OpenThreads::ScopedLock<OpenThreads::Mutex> lock(*_mutex);
  6.                 osg::Group* root = dynamic_cast<osg::Group*>(node);
  7.                 if ( root != NULL )
  8.                 {
  9.                         for ( size_t i = 0; i < _vtRemoving.size(); ++i )
  10.                         {
  11.                                 root->removeChild(_vtRemoving);
  12.                         }

  13.                         if (_vtRemoving.size()>0)
  14.                         {
  15.                                 _vtRemoving.clear();
  16.                         }
  17.                         for ( size_t i = 0; i < _vtAdding.size(); ++i )
  18.                         {
  19.                                 root->addChild( _vtAdding );
  20.                         }
  21.                         
  22.                         if (_vtAdding.size()>0)
  23.                         {
  24.                                 _vtAdding.clear();
  25.                         }
  26.                 }
  27.                 _paused = TRUE;

  28. }
  29. }

复制代码

该用户从未签到

 楼主| 发表于 2011-3-21 17:05:22 | 显示全部楼层
仔细看了看代码,明白了。没有继续向下遍历的原因。现在才明白了array的意思,是在operator结尾需要调用traverse函数。我以为array说加了traverse才导致不正常
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

联系我们

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