OSG 砖块 shader 例子 GLSL

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhuyingqingfen/article/details/44101619

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








猜你喜欢

转载自blog.csdn.net/zhuyingqingfen/article/details/44101619