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();
}

OSG 砖头 shader 例子  GLSL