OSG使用OpenGL顶点着色器和片元着色器

时间:2022-05-11 03:53:42

目的:

使用OpenGL着色语言中的顶点和片元着色器,替代原有的固化函数管道的光照和材质计算,用于场景图形中的节点选择。(砖块着色器程序来自3DLabs)

OSG使用OpenGL顶点着色器和片元着色器

------------------------------------

概述:

OpenGL着色语言允许程序员编写自己的像素和顶点着色器。有关着色语言的更多信息,包括最低的硬件和软件需求,请参阅:
http://developer.3dlabs.com/openGL2/
OSG的osg::Program和osg::Shader类允许用户将着色器作为StateSet的一部分加入选定的场景图形子树。如果要在OpenSceneGraph中使用自定义的顶点和片元着色器,则需要使用下面的基类:

osg::Program - 在应用层级上封装了OpenGL着色语言的glProgramObject函数。Program类的对象继承自osg::StateAttribute类。即osg::Program类的实例可以关联到StateSet,并使用setAttributeAndModes()方法来许可自身的使用。开启Program渲染状态之后,与此渲染状态相关联的几何体均会使用该Program的着色器进行渲染。

osg::Shader - 在应用层级上封装了OpenGL着色语言的glShaderObject函数。这个类用于管理着色器源代码的加载和编译。osg::Shader类的实例可以与一个或多个osg::Program的实例相关联。Shader对象有两种类型:osg::Shader::FRAGMENT和osg::Shader::VERTEX。

代码:

要创建一个使用OpenGL像素和片元着色器的程序,可以按照下面的步骤:

  • 创建一个osg::Program实例;
  • 创建一个osg::Shader类的顶点(VERTEX)或片元(FRAGMENT)着色器实例;
  • 加载并编译着色器代码;
  • 将着色器添加到osg::Program实例;
  • 将osg::Program实例关联给StateSet类,并将其激活;

下面的代码用于加载和应用基本的顶点和片元着色器:

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

   osg::Program* brickProgramObject = new osg::Program;
   osg::Shader* brickVertexObject =
      new osg::Shader( osg::Shader::VERTEX );
   osg::Shader* brickFragmentObject =
      new osg::Shader( osg::Shader::FRAGMENT );
   brickProgramObject->addShader( brickFragmentObject );
   brickProgramObject->addShader( brickVertexObject );
   loadShaderSource( brickVertexObject, "shaders/brick.vert" );
   loadShaderSource( brickFragmentObject, "shaders/brick.frag" );

   brickState->setAttributeAndModes(brickProgramObject, osg::StateAttribute::ON);

下面的函数可以方便地加载着色器代码,并将编译后的代码关联给着色器对象:

bool loadShaderSource(osg::Shader* obj, const std::string& fileName )
{
   std::string fqFileName = osgDB::findDataFile(fileName);
   if( fqFileName.length() == 0 )
   {
      std::cout << "File /"" << fileName << "/" not found." << std::endl;
      return false;
   }
   bool success = obj->loadShaderSourceFromFile( fqFileName.c_str());
   if ( !success  )
   {
      std::cout << "Couldn't load file: " << fileName << std::endl;
      return false;
   }
   else
   {
      return true;
   }
}

祝你好运!