我要发帖 回复

高级会员

109

主题

1366

积分

0

专家分

OSG-VR-GIS

忠于职守杰出贡献

:

私信
发表时间 : 2007-12-21 14:16:37 | 浏览 : 1640    评论 : 0
Navy14.3 - 更新着色器
目的:
3.jpg
持续更新OpenGL着色器程序所用的变量。
-----------------------------

概述:
本章演示了如何使用OpenGL着色器程序持续更新参数,从而实现对场景中对象的动态着色效果控制。我们将使用前述的凹凸贴图着色器,并更新其一致变量LightPosition,以模拟灯光环绕坦克模型移动的效果。我们将使用上一章所用的addUniform方法。不过,这一次我们将使用更新回调来实现变量更新的效果。回调类的主体用于持续改变灯光位置的向量。为了使用这个类的功能,我们简单地将其关联给场景中节点的更新回调。

  

代码:
着色器更新回调的定义如下:

class updateBumpShader : public osg::Uniform::Callback
{
public:
   virtual void operator()
      ( osg::Uniform* uniform, osg::NodeVisitor* nv )
   {
      float angle = nv->getFrameStamp()->getReferenceTime();
      float x = sinf(angle)*.2f;
      float y = cosf(angle)*.2f;
      osg::Vec3 lightPos(x,y,.6f);
      uniform->set(lightPos);
   }
};

其余的代码与上一章基本相同:设置场景和着色器的实例。唯一不同的是,我们需要将上面的回调类设置为场景中一个节点的更新回调。

int main( int argc, char **argv )
{
   osg::Group* rootNode = new osg::Group();
   osg::Node* tankNode = NULL;
   osg::Node* terrainNode = NULL;
   osg::PositionAttitudeTransform* tankXform =
      new osg::PositionAttitudeTransform();

   osgDB::FilePathList pathList = osgDB::getDataFilePathList();
   pathList.push_back
      ("C:\\Projects\\OpenSceneGraph\\OpenSceneGraph-
         Data\\NPSData\\Models\\T72-Tank\\");
   pathList.push_back
      ("C:\\Projects\\OpenSceneGraph\\OpenSceneGraph-
         Data\\NPSData\\Models\\JoeDirt\\");
   osgDB::setDataFilePathList(pathList);

   tankNode = osgDB::readNodeFile("T72-tank_des.flt");
   terrainNode = osgDB::readNodeFile("JoeDirt.flt");
   if (! (tankNode && terrainNode))
   {
      std::cout << "Couldn't load models, quitting." << std::endl;
      return -1;
   }
   rootNode->addChild(terrainNode);
   rootNode->addChild(tankXform);
   tankXform->addChild(tankNode);

   tankXform->setPosition( osg::Vec3(10,10,8) );
   tankXform->setAttitude(
      osg::Quat(osg::DegreesToRadians(-45.0), osg::Vec3(0,0,1) ) );

   osg::StateSet* bumpMapState = tankNode->getOrCreateStateSet();

   osg::Program* bumpMapProgramObject = new osg::Program;

   osg::Shader* bumpVertexObject =
      new osg::Shader( osg::Shader::VERTEX );
   osg::Shader* bumpFragmentObject =
      new osg::Shader( osg::Shader::FRAGMENT );

   bool ok =
      loadShaderSource( bumpVertexObject, "shaders/bumpmap.vert" )
      &&
      loadShaderSource
         ( bumpFragmentObject, "shaders/bumpmap.frag" ) ;

   if(!ok)
   {
      std::cout << "Couldn't load shaders" << std::endl;
      return -1;
   }

   bumpMapProgramObject->addShader( bumpFragmentObject );
   bumpMapProgramObject->addShader( bumpVertexObject );

   osg::Uniform* lightPosU =
      new osg::Uniform("LightPosition",osg::Vec3(0,0,1));
   osg::Uniform* normalMapU = new osg::Uniform("normalMap",1);
   osg::Uniform* baseTextureU = new osg::Uniform("baseTexture",0);

   bumpMapState->addUniform(lightPosU);
   bumpMapState->addUniform(normalMapU);
   bumpMapState->addUniform(baseTextureU);
   lightPosU->setUpdateCallback(new updateBumpShader() );

   bumpMapState->setAttributeAndModes
      (bumpMapProgramObject, osg::StateAttribute::ON);

   osg::Texture2D* tankBodyNormalMap = new osg::Texture2D;
   tankBodyNormalMap->setDataVariance(osg::Object::DYNAMIC);
   osg::Image* tankBody = osgDB::readImageFile("TankBump.png");
   if (!tankBody)
   {
      std::cout << " couldn't find texture, quiting." << std::endl;
      return -1;
   }

   tankBodyNormalMap->setImage(tankBody);
   bumpMapState->setTextureAttributeAndModes
      (1,tankBodyNormalMap,osg::StateAttribute::ON);

   osgViewer::Viewer viewer;

   viewer.setCameraManipulator(new osgGA::TrackballManipulator());
   viewer.setSceneData( rootNode );
   viewer.realize();

   while( !viewer.done() )
   {
      viewer.frame();
   }
   return 0;
}

编程愉快!

最近VR访客


OSG中国官方网站:http://www.osgChina.org
OSG中国官方讨论区:http://bbs.osgChina.org

OSG专业群-OSG地形研究者 49668412
      OSG地形专业研究 45763709

手机版|VR开发网 统计 津ICP备18009691号
网安备12019202000257

GMT+8, 2021-10-25 11:52 PM

返回顶部