效果:牛身上圈圈里的顏色在閃爍
代碼:
1 #include <osg/Program> 2 #include <osgDB/ReadFile> 3 #include <osgViewer/Viewer> 4 5 static const char* vertSource = { 6 "varying vec3 normal;\n"//易變量 用於着色器之間的傳值 7 "void main()\n" 8 "{\n" 9 " normal = normalize(gl_NormalMatrix * gl_Normal);\n" //把法線向量從物體空間轉化到視覺空間。 10 " gl_Position = ftransform();\n" //相當於 gl_Position = ModelViewProjectionMatrix * gl_Vertex, 11 //模型視圖投影矩陣與空間頂點位置相乘,得到裁剪空間頂點位置。 12 "}\n" 13 }; 14 15 static const char* fragSource = { 16 "uniform vec4 mainColor;\n" //外面程序輸入的顏色 17 "varying vec3 normal;\n" //上面的頂點着色器傳的法線 18 "void main()\n" 19 "{\n" 20 " float intensity = dot(vec3(gl_LightSource[0].position), normal);\n" //計算光照位置與法線的點積,為什么這么做,知道的朋友不吝賜教下。 21 //按照我的理解就是計算了一下亮度值。 22 //給輸出的顏色賦值 23 " if (intensity > 0.95) gl_FragColor = mainColor;\n" //如果這個值大於0.95,則輸出顏色為mainColor,而uniform回調中每幀在來回改這個值,所 24 //以這一部分會出現閃爍的效果。 25 " else if (intensity > 0.5) gl_FragColor = vec4(0.6,0.3,0.3,1.0);\n" 26 " else if (intensity > 0.25) gl_FragColor = vec4(0.4,0.2,0.2,1.0);\n" 27 " else gl_FragColor = vec4(0.2,0.1,0.1,1.0);\n" 28 "}\n" 29 }; 30 31 32 /* 一直變量uniform回調類,主要用於每幀更新着色器中的用戶數據,從而改變渲染的行為和輸出結果。 */ 33 34 35 class ColorCallback : public osg::Uniform::Callback 36 { 37 public: 38 ColorCallback() : _incRed(false) {} 39 40 virtual void operator()( osg::Uniform* uniform, osg::NodeVisitor* nv ) 41 { 42 if ( !uniform ) return; 43 44 osg::Vec4 color; 45 uniform->get( color );//獲取通過uniform 設置進去的值mainColor 46 47 if ( _incRed==true )//3、如果r減到0呢,就給他一直加。 48 { 49 if ( color.x()<1.0 ) color.x() += 0.1; 50 else _incRed = false;//4、如果加到1就給他再減。 51 } 52 else 53 { 54 if ( color.x()>0.0 ) color.x() -= 0.1;//1、如果RGB中的r分量大於0,則一直減小。 55 else _incRed = true;// 2、r減到0了。 56 } 57 uniform->set( color ); 58 } 59 60 protected: 61 bool _incRed; 62 }; 63 64 void createShaders( osg::StateSet& ss ) 65 { 66 osg::ref_ptr<osg::Shader> vertShader = new osg::Shader( osg::Shader::VERTEX, vertSource ); 67 osg::ref_ptr<osg::Shader> fragShader = new osg::Shader( osg::Shader::FRAGMENT, fragSource ); 68 69 osg::ref_ptr<osg::Program> program = new osg::Program; 70 program->addShader( vertShader.get() ); 71 program->addShader( fragShader.get() ); 72 73 osg::ref_ptr<osg::Uniform> mainColor = new osg::Uniform( "mainColor", osg::Vec4(0.5,0.5,0.5,1.0) );//這個部分的顏色是閃爍部分的顏色值。 74 mainColor->setUpdateCallback( new ColorCallback ); 75 76 ss.addUniform( mainColor.get() ); 77 ss.setAttributeAndModes( program.get() ); 78 } 79 80 int main( int argc, char** argv ) 81 { 82 osg::ArgumentParser arguments( &argc, argv ); 83 osg::Node* model = osgDB::readNodeFiles( arguments ); 84 if ( !model ) model = osgDB::readNodeFile( "cow.osg" ); 85 86 createShaders( *(model->getOrCreateStateSet()) ); 87 88 osgViewer::Viewer viewer; 89 viewer.setSceneData( model ); 90 viewer.setUpViewInWindow(20,20,600,600); 91 return viewer.run(); 92 }