#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 设置进去的值mainColor
if (_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();
}
效果如下: