#include <osg/Program>
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>static const char* vertSource = {"varying vec3 normal;\n"//易变量 用于着色器之间的传值"void main()\n""{\n"" normal = normalize(gl_NormalMatrix * gl_Normal);\n" //把法线向量从物体空间转化到视觉空间。" gl_Position = ftransform();\n" //相当于 gl_Position = ModelViewProjectionMatrix * gl_Vertex,//模型视图投影矩阵与空间顶点位置相乘,得到裁剪空间顶点位置。"}\n"
};static const char* fragSource = {"uniform vec4 mainColor;\n" //外面程序输入的颜色"varying vec3 normal;\n" //上面的顶点着色器传的法线"void main()\n""{\n"" float intensity = dot(vec3(gl_LightSource[0].position), normal);\n" //计算光照位置与法线的点积,为什么这么做,知道的朋友不吝赐教下。//按照我的理解就是计算了一下亮度值。//给输出的颜色赋值" if (intensity > 0.95) gl_FragColor = mainColor;\n" //如果这个值大于0.95,则输出颜色为mainColor,而uniform回调中每帧在来回改这个值,所//以这一部分会出现闪烁的效果。" else if (intensity > 0.5) gl_FragColor = vec4(0.6,0.3,0.3,1.0);\n"" else if (intensity > 0.25) gl_FragColor = vec4(0.4,0.2,0.2,1.0);\n"" else gl_FragColor = vec4(0.2,0.1,0.1,1.0);\n""}\n"
};/* 一直变量uniform回调类,主要用于每帧更新着色器中的用户数据,从而改变渲染的行为和输出结果。 */class ColorCallback : public osg::Uniform::Callback
{
public:ColorCallback() : _incRed(false) {}virtual void operator()(osg::Uniform* uniform, osg::NodeVisitor* nv){if (!uniform) return;osg::Vec4 color;uniform->get(color);//获取通过uniform 设置进去的值mainColorif (_incRed == true)//3、如果r减到0呢,就给他一直加。{if (color.x() < 1.0) color.x() += 0.1;else _incRed = false;//4、如果加到1就给他再减。}else{if (color.x() > 0.0) color.x() -= 0.1;//1、如果RGB中的r分量大于0,则一直减小。else _incRed = true;// 2、r减到0了。}uniform->set(color);}protected:bool _incRed;
};void createShaders(osg::StateSet& ss)
{osg::ref_ptr<osg::Shader> vertShader = new osg::Shader(osg::Shader::VERTEX, vertSource);osg::ref_ptr<osg::Shader> fragShader = new osg::Shader(osg::Shader::FRAGMENT, fragSource);osg::ref_ptr<osg::Program> program = new osg::Program;program->addShader(vertShader.get());program->addShader(fragShader.get());osg::ref_ptr<osg::Uniform> mainColor = new osg::Uniform("mainColor", osg::Vec4(0.5, 0.5, 0.5, 1.0));//这个部分的颜色是闪烁部分的颜色值。mainColor->setUpdateCallback(new ColorCallback);ss.addUniform(mainColor.get());ss.setAttributeAndModes(program.get());
}int main(int argc, char** argv)
{osg::ArgumentParser arguments(&argc, argv);osg::Node* model = osgDB::readNodeFiles(arguments);if (!model) model = osgDB::readNodeFile("cow.osg");createShaders(*(model->getOrCreateStateSet()));osgViewer::Viewer viewer;viewer.setSceneData(model);viewer.setUpViewInWindow(20, 20, 600, 600);return viewer.run();
}
效果如下: