按键 x y z 可以调节灯光位置
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osg/Shape>
#include <osg/Shapedrawable>
#include <osg/MatrixTransform>
static char * vertexShader = {
"#version 140 \n"
"in vec4 MCvertex; \n"
"in vec3 MCnormal; \n"
"in vec3 osg_SimulationTime; \n"
"uniform mat4 osg_ModelViewMatrix; \n"
"uniform mat4 osg_ModelViewProjectionMatrix;\n"
"uniform mat3 osg_NormalMatrix;\n"
"uniform vec3 LightPosition ;\n"
"const float SpecularContribution = 0.3;\n"
"const float DiffuseContribution = 1.0 - SpecularContribution;\n"
"out float LightIntensity;\n"
"out vec2 MCposition;\n"
"void main()\n"
"{\n"
" vec3 ecPosition = vec3(osg_ModelViewMatrix * MCvertex); \n"
" vec3 tnorm = normalize(osg_NormalMatrix * MCnormal); \n"
" vec3 lightVec = normalize(vec3(LightPosition[0],LightPosition[1],LightPosition[2]*osg_SimulationTime) - ecPosition); \n"
" vec3 reflectVec = reflect(-lightVec, tnorm); \n"
" vec3 viewVec = normalize(-ecPosition); \n"
" float diffuse = max(dot(lightVec, tnorm), 0.0); \n"
" float spec = 0.0; \n"
" if (diffuse > 0.0) \n"
" {\n"
" spec = max(dot(reflectVec, viewVec), 0.0);\n"
" spec = pow(spec, 16.0);\n"
" }\n"
" LightIntensity = DiffuseContribution * diffuse + SpecularContribution * spec;\n"
" MCposition = MCvertex.xy;\n"
" gl_Position = osg_ModelViewProjectionMatrix * MCvertex;\n"
"} \n"
};
static char * fragShader = {
" #version 140 \n"
" uniform vec3 BrickColor = vec3(0,1,1), MortarColor = vec3(1,0,1);\n"
" uniform vec2 BrickSize = vec2(0.3,0.15);\n"
" uniform vec2 BrickPct = vec2(0.9,0.85);\n"
" in vec2 MCposition;\n"
" in float LightIntensity;\n"
" out vec4 FragColor;\n"
" void main()\n"
" {\n"
" vec3 color;\n"
" vec2 position, useBrick;\n"
" position = MCposition / BrickSize;\n"
" if (fract(position.y * 0.5) > 0.5)\n"
" position.x += 0.5;\n"
" position = fract(position);\n"
" useBrick = step(position, BrickPct);\n"
" color = mix(MortarColor, BrickColor, useBrick.x * useBrick.y);\n"
" color *= LightIntensity;\n"
" FragColor = vec4(color, 1.0);\n"
"}\n"
};
osg::Node * CreateNode()
{
osg::Geode * geode = new osg::Geode;
osg::Geometry* polyGeom = new osg::Geometry();
osg::Vec3Array* vertices = new osg::Vec3Array();
vertices->push_back(osg::Vec3(-10, 0, 0));
vertices->push_back(osg::Vec3(10, 0, 0));
vertices->push_back(osg::Vec3(0, 10, 10));
polyGeom->setVertexArray(vertices);
osg::ref_ptr<osg::Vec4Array> colorsArray = new osg::Vec4Array;
colorsArray->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
colorsArray->push_back(osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
colorsArray->push_back(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
polyGeom->setColorArray(colorsArray.get());
polyGeom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
osg::Vec3Array* normals = new osg::Vec3Array;
normals->push_back(osg::Vec3(0.0f, 1.0f, 0.0f));
normals->push_back(osg::Vec3(0.0f, 0.0f, 1.0f));
normals->push_back(osg::Vec3(1.0f, 0.0f, 0.0f));
polyGeom->setNormalArray(normals);
polyGeom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
polyGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES, 0, 3));
polyGeom->setVertexAttribArray(0, vertices);
polyGeom->setVertexAttribBinding(0, osg::Geometry::BIND_PER_VERTEX);
polyGeom->setVertexAttribArray(1, colorsArray.get());
polyGeom->setVertexAttribBinding(1, osg::Geometry::BIND_PER_VERTEX);
polyGeom->setVertexAttribArray(2, normals);
polyGeom->setVertexAttribBinding(2, osg::Geometry::BIND_PER_VERTEX);
geode->addDrawable(polyGeom);
return geode;
}
osg::MatrixTransform * lightPos;
class MyNodeVisitor : public osg::NodeVisitor
{
public:
MyNodeVisitor() :osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN){}
virtual void apply(osg::Geode& node)
{
for (int i = 0; i < node.getNumParents(); ++i)
{
osg::Geometry * polyGeom = dynamic_cast<osg::Geometry*>(node.getDrawable(i));
if (!polyGeom)return;
polyGeom->setVertexAttribArray(0, polyGeom->getVertexArray());
polyGeom->setVertexAttribBinding(0, osg::Geometry::BIND_PER_VERTEX);
polyGeom->setVertexAttribArray(1, polyGeom->getColorArray());
polyGeom->setVertexAttribBinding(1, osg::Geometry::BIND_PER_VERTEX);
polyGeom->setVertexAttribArray(2, polyGeom->getNormalArray());
polyGeom->setVertexAttribBinding(2, polyGeom->getNormalBinding());
}
}
};
class LightPosCallback : public osg::Uniform::Callback
{
public:
LightPosCallback()
{
}
virtual void operator()(osg::Uniform* uniform, osg::NodeVisitor* nv)
{
osg::Matrix m = lightPos->getMatrix();
uniform->set(m.getTrans());
}
};
osg::Node * createlight()
{
osg::ShapeDrawable *sun_sd = new osg::ShapeDrawable;
osg::Sphere* sun_sphere = new osg::Sphere;
sun_sphere->setName("SunSphere");
sun_sphere->setRadius(0.5);
sun_sd->setShape(sun_sphere);
sun_sd->setColor(osg::Vec4(1.0, 0.0, 0.0, 1.0));
osg::Geode* sun_geode = new osg::Geode;
sun_geode->setName("SunGeode");
sun_geode->addDrawable(sun_sd);
return sun_geode;
}
class KeyboardEventHandler : public osgGA::GUIEventHandler
{
public:
KeyboardEventHandler(){}
virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter&)
{
switch (ea.getEventType())
{
case(osgGA::GUIEventAdapter::KEYDOWN) :
{
if (ea.getKey() == 'x')//绕x轴旋转
{
osg::Matrix trans = lightPos->getMatrix();
trans = trans * osg::Matrix::rotate(osg::PI_2 / 10, osg::X_AXIS);
lightPos->setMatrix(trans);
}
if (ea.getKey() == 'y')//绕y轴旋转
{
osg::Matrix trans = lightPos->getMatrix();
trans = trans * osg::Matrix::rotate(osg::PI_2 / 10, osg::Y_AXIS);
lightPos->setMatrix(trans);
}
if (ea.getKey() == 'z')//绕z轴旋转
{
osg::Matrix trans = lightPos->getMatrix();
trans = trans * osg::Matrix::rotate(osg::PI_2 / 10, osg::Z_AXIS);
lightPos->setMatrix(trans);
}
}
}
return false;
}
};
int main()
{
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
osg::ref_ptr<osg::Node> geode = osgDB::readNodeFile("cow.osg");//CreateNode();
MyNodeVisitor visitor;
geode->accept(visitor);
osg::ref_ptr<osg::StateSet> stateSet = geode->getOrCreateStateSet();
osg::ref_ptr<osg::Shader> vShader = new osg::Shader(osg::Shader::VERTEX, vertexShader);
osg::ref_ptr<osg::Shader> fShader = new osg::Shader(osg::Shader::FRAGMENT, fragShader);
osg::ref_ptr<osg::Program> program = new osg::Program;
program->addShader(vShader.get());
program->addShader(fShader.get());
program->addBindAttribLocation("MCvertex", 0);
program->addBindAttribLocation("MCnormal", 2);
osg::ref_ptr<osg::Uniform> M4 = new osg::Uniform("LightPosition", osg::Vec3d(2, 0, 0));
M4->setUpdateCallback(new LightPosCallback());
stateSet->addUniform(M4.get());
stateSet->setAttributeAndModes(program.get(), osg::StateAttribute::ON);
lightPos = new osg::MatrixTransform;
lightPos->setMatrix(osg::Matrix::translate(0, 0, 5));
lightPos->addChild(createlight());
osg::Group * root = new osg::Group;
//root->addChild(osgDB::readNodeFile("d:/ah64_apache.3ds"));
root->addChild(lightPos);
root->addChild(geode);
viewer->addEventHandler(new KeyboardEventHandler());
viewer->setSceneData(root);
viewer->setUpViewInWindow(35, 35, 1024, 800);
viewer->realize();
osg::State* state = viewer->getCamera()->getGraphicsContext()->getState();
state->setUseModelViewAndProjectionUniforms(true);
return viewer->run();
}