OSG 砖头 shader 例子 GLSL
OSG 砖块 shader 例子 GLSL

按键 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" "uniform mat4 MVMatrix; \n" "uniform mat4 MVPMatrix;\n" "uniform mat3 NormalMatrix;\n" "uniform vec3 LightPosition = vec3(10.0, 0.0, 0.0);\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(MVMatrix * MCvertex); \n" " vec3 tnorm = normalize(NormalMatrix * MCnormal); \n" " vec3 lightVec = normalize(LightPosition - 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 = MVPMatrix * 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 MVPCallback: public osg::Uniform::Callback { public: MVPCallback(osg::Camera * camera,int index):mCamera(camera),mIndex(index){ } virtual void operator()( osg::Uniform* uniform, osg::NodeVisitor* nv){ osg::Matrixf modelView = mCamera->getViewMatrix(); osg::Matrix projectM = mCamera->getProjectionMatrix(); if(mIndex == 1)//MVMatrix { uniform->set(modelView); }else if(mIndex == 2)//MVPMatrix { uniform->set(modelView * projectM); } else if(mIndex == 3)//NormalMatrix { osg::Matrix3 m3;m3.set(modelView.ptr()); uniform->set(m3); } } private: osg::Camera * mCamera; int mIndex; }; 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> M1 = new osg::Uniform("MVMatrix", osg::Matrix()); osg::ref_ptr<osg::Uniform> M2 = new osg::Uniform("MVPMatrix", osg::Matrix()); osg::ref_ptr<osg::Uniform> M3 = new osg::Uniform("NormalMatrix", osg::Matrix3()); osg::ref_ptr<osg::Uniform> M4 = new osg::Uniform("LightPosition",osg::Vec3(2,0,0)); M1->setUpdateCallback(new MVPCallback(viewer->getCamera(),1)); M2->setUpdateCallback(new MVPCallback(viewer->getCamera(),2)); M3->setUpdateCallback(new MVPCallback(viewer->getCamera(),3)); M4->setUpdateCallback(new LightPosCallback()); stateSet->addUniform(M1.get()); stateSet->addUniform(M2.get()); stateSet->addUniform(M3.get()); 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:/aixs.3ds")); root->addChild(lightPos); root->addChild(geode); viewer->addEventHandler(new KeyboardEventHandler()); viewer->setSceneData(root); viewer->setUpViewInWindow(35, 35, 1024, 800); return viewer->run(); }