1. 程式人生 > >OSG使用OpenGL頂點著色器和片元著色器

OSG使用OpenGL頂點著色器和片元著色器

目的:

使用OpenGL著色語言中的頂點和片元著色器,替代原有的固化函式管道的光照和材質計算,用於場景圖形中的節點選擇。(磚塊著色器程式來自3DLabs)

course14.1

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

概述:

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;
   }
}

祝你好運!