[osg-users] Texture projection on terrain and gl_TextureMatrix[0...7]

Sebastian Messerschmidt sebastian.messerschmidt at gmx.de
Fri Dec 23 05:53:48 PST 2016



Hi Ekaterina:
> Hello,
>
> after checking more the forum, I have found another topic
> http://forum.openscenegraph.org/viewtopic.php?t=9182&highlight=jotschi
>
> with the following code, which I have slightly modified.
>
> I would be very grateful, if someone can explain to me why the basic model is black and how to avoid it?

Because the shader is written to only project the texture. If you need 
to blend it on top, you will need to either explicitly use the original 
texture information or do a multipass rendering with this code blending 
additively over your current scene.

Cheers
Sebastian
>
> Or maybe, someone has a very simple example with any texture projection on the terrain.
>
> #include <osg/Version>
> #include <osg/Camera>
> #include <osg/NodeVisitor>
> #include <osg/TexGenNode>
> #include <osg/TexMat>
>
> #include <osgSim/MultiSwitch>
>
> #include <osgDB/ReadFile>
> #include <osgDB/FileUtils>
> #include <osgDB/FileNameUtils>
> #include <osgDB/DatabasePager>
>
> #include <osgViewer/ViewerEventHandlers>
>
> #include <osgGA/TrackballManipulator>
> #include <osgGA/FlightManipulator>
> #include <osgGA/DriveManipulator>
> #include <osgGA/KeySwitchMatrixManipulator>
> #include <osgGA/StateSetManipulator>
> #include <osgGA/AnimationPathManipulator>
> #include <osgGA/TerrainManipulator>
> #include <osgGA/CameraManipulator>
>
>
> #include <iostream>
> #include <osg/Notify>
> #include <osg/MatrixTransform>
> #include <osg/ShapeDrawable>
> #include <osg/PositionAttitudeTransform>
> #include <osg/Geometry>
> #include <osgGA/TrackballManipulator>
>
> #include <osg/Texture2D>
> #include <osg/Geode>
> #include <osg/LightSource>
> #include <osg/TexGenNode>
> #include <osg/TexMat>
> #include <osgDB/WriteFile>
> #include <osgUtil/Optimizer>
>
> #include <osgDB/Registry>
> #include <osgDB/ReadFile>
>
> #include <osgViewer/Viewer>
> #include <osgViewer/CompositeViewer>
>
> using namespace std;
>
> osgViewer::View* viewA = new osgViewer::View;
> osg::TexMat* texMat = new osg::TexMat;
> osg::Uniform* ViewMatInv = new osg::Uniform(osg::Uniform::FLOAT_MAT4,
> 	"ViewMatInv");
> int spotTUnit = 3;
>
>
>
> const char* VertexShader = {
> 	"uniform mat4 ViewMatInv;\n"
> 	"void main()\n"
> 	"{\n"
> 	"vec4 posEye = gl_ModelViewMatrix * gl_Vertex;\n"
> 	"gl_TexCoord[3].s = dot( posEye, gl_EyePlaneS[3]);\n"
> 	"gl_TexCoord[3].t = dot( posEye, gl_EyePlaneT[3]);\n"
> 	"gl_TexCoord[3].p = dot( posEye, gl_EyePlaneR[3]);\n"
> 	"gl_TexCoord[3].q = dot( posEye, gl_EyePlaneQ[3]);\n"
> 	"gl_Position = gl_ProjectionMatrix * posEye;\n"
> 	"}\n"
> };
>
> const char* FragmentShader = {
> 	"uniform sampler2D projectionMap;\n"
> 	"varying vec4 projCoord;\n"
>      "void main()\n"
> 	"{\n"
> 	"gl_FragColor = texture2DProj(projectionMap, gl_TexCoord[3]);\n"
> 	//"#if TEST_FOR_REVERSE_PROJECTION\n"
> 	//"if (gl_TexCoord[3].q > 0.0)\n"
> 	//"gl_FragColor = texture2DProj(projectionMap, gl_TexCoord[3]);\n"
> 	//"else\n"
> 	//"gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
>   //   "#endif\n"
> 	"}\n"
> };
>
>
> osg::ref_ptr<osg::Program> addShader()
> {
> 	osg::ref_ptr<osg::Program> projProg = new osg::Program;
> 	//osg::ref_ptr<osg::Shader> projvertexShader(osg::Shader::readShaderFile(
> 	//	osg::Shader::VERTEX, "surface.main.vert.glsl"));
> 	//osg::ref_ptr<osg::Shader> projfragShader(osg::Shader::readShaderFile(
> 	//	osg::Shader::FRAGMENT, "surface.main.frag.glsl"));
> 	//projProg->addShader(projvertexShader.get());
> 	//projProg->addShader(projfragShader.get());
>
> 	projProg->addShader(new osg::Shader(osg::Shader::VERTEX, VertexShader));
> 	projProg->addShader(new osg::Shader(osg::Shader::FRAGMENT, FragmentShader));
>
> 	return projProg;
> }
>
> void addProjectionInfoToState(osg::StateSet* stateset, string fn)
> {
>
> 	osg::Vec4 centerColour(1.0f, 1.0f, 1.0f, 1.0f);
> 	osg::Vec4 ambientColour(0.05f, 0.05f, 0.05f, 1.0f);
>
> 	/* 1. Load the texture that will be projected */
> 	osg::Texture2D* texture = new osg::Texture2D();
> 	texture->setImage(osgDB::readImageFile(fn));//VTB::createSpotLightImage(centerColour, ambientColour, 64, 1.0));
> 	texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_BORDER);
> 	texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_BORDER);
> 	texture->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_BORDER);
> 	stateset->setTextureAttributeAndModes((int)spotTUnit, texture, osg::StateAttribute::ON);
>
>
> 	// set up tex gens
> 	stateset->setTextureMode((int)spotTUnit, GL_TEXTURE_GEN_S, osg::StateAttribute::ON);
> 	stateset->setTextureMode((int)spotTUnit, GL_TEXTURE_GEN_T, osg::StateAttribute::ON);
> 	stateset->setTextureMode((int)spotTUnit, GL_TEXTURE_GEN_R, osg::StateAttribute::ON);
> 	stateset->setTextureMode((int)spotTUnit, GL_TEXTURE_GEN_Q, osg::StateAttribute::ON);
>
> 	/* 3. Handover the texture to the fragment shader via uniform */
> 	osg::Uniform* texUniform = new osg::Uniform(osg::Uniform::SAMPLER_2D,
> 		"projectionMap");
> 	texUniform->set((int)spotTUnit);
> 	stateset->addUniform(texUniform);
>
> 	/* 4. set Texture matrix*/
>
> 	//If you want to create the texture matrix by yourself you can do this like this way:
> 	//osg::Vec3 projectorPos = osg::Vec3(0.0f, 0.0f, 324.0f);
> 	//osg::Vec3 projectorDirection = osg::Vec3(osg::inDegrees(dirX),osg::inDegrees(dirY), osg::inDegrees(dirZ));
> 	//osg::Vec3 up(0.0f, 1.0f, 0.0f);
> 	//osg::Vec3 target = osg::Vec3(0.0f, 0.0f,0.0f);
> 	//float projectorAngle = 80.f; //FOV
> 	//mat = osg::Matrixd::lookAt(projectorPos, projectorPos*target ,up) * osg::Matrixd::perspective(projectorAngle, 1.0, 1.0, 10);
>
> 	osg::Matrix mat = viewA->getCamera()->getViewMatrix()
> 		* viewA->getCamera()->getProjectionMatrix();
>
> 	texMat->setMatrix(mat);
> 	stateset->setTextureAttributeAndModes((int)spotTUnit, texMat, osg::StateAttribute::ON);
>
>
> 	stateset->addUniform(ViewMatInv);
> }
>
> osg::StateSet* createProjectorState()
> {
> 	osg::StateSet* stateset = new osg::StateSet;
>
> 	osg::ref_ptr<osg::Program> prog = addShader();
>
> 	addProjectionInfoToState(stateset, "clockface.JPG");
>
> 	stateset->setAttribute(prog.get());
>
> 	return stateset;
> }
>
> /**
> * Load some model, scale it and apply the shader
> */
> osg::Node* createModel()
> {
> 	osg::Group* root = new osg::Group;
>
> 	/* Load the terrain which will be the receiver of out projection */
> 	osg::Node* terr = osgDB::readNodeFile("cessna.osg");
>
> 	root->addChild(terr);
>
> 	/* Enable projective texturing for all objects of this node */
> 	root->setStateSet(createProjectorState());
> 	return root;
> }
>
> int main(int argc, char* argv[])
> {
> 	// Set the output level
> 	osg::setNotifyLevel(osg::WARN);
>
> 	osg::ArgumentParser arguments(&argc, argv);
>
> 	osg::ref_ptr<osg::Group> sceneA = new osg::Group;
> 	osg::ref_ptr<osg::Group> sceneB = new osg::Group;
> 	osg::ref_ptr<osg::Group> sceneC = new osg::Group;
> 	sceneA->addChild(createModel());
>
> 	osgViewer::CompositeViewer viewer(arguments);
>
> 	viewer.addView(viewA);
> 	viewA->setUpViewInWindow(10, 10, 640, 480);
> 	viewA->setSceneData(sceneA.get());
>
> 	//Add this to move the projector by mouse - you need to disable the set
> 	//of the viewmatrix in the while loop below.
> 	osgGA::TrackballManipulator* aManipulator = new osgGA::TrackballManipulator;
> 	viewA->setCameraManipulator(aManipulator);
>
> 	// Create a TexGenNode to automatically update the
> 	// planes.
> 	osg::TexGenNode* texgenNode = new osg::TexGenNode;
> 	texgenNode->setTextureUnit((int)spotTUnit);
>
> 	osg::TexGen* texgen = texgenNode->getTexGen();
> 	texgen->setMode(osg::TexGen::EYE_LINEAR);
>
> 	osg::MatrixTransform* posTexGen = new osg::MatrixTransform;
> 	posTexGen->addChild(texgenNode);
>
> 	osg::Vec3 position(0.0f, 0.0f, 0.0f);
> 	osg::Vec3 direction(0.0f, 1.0f, 0.0f);
> 	osg::Vec3 up(0.0f, 0.0f, 1.0f);
> 	up = (direction ^ up) ^ direction;
> 	up.normalize();
>
> 	texgen->setPlanesFromMatrix(osg::Matrixd::lookAt(position, position + direction, up)*
> 		viewA->getCamera()->getProjectionMatrix());
> 	// osg::Matrixd::perspective(45.f,1.0,0.1,100));
>
> 	sceneA->addChild(posTexGen);
>
>
> 	while (!viewer.done())
> 	{
> 		osg::Matrixd viewMatInv(viewA->getCamera()->getInverseViewMatrix());
> 		ViewMatInv->set(viewMatInv);
>
> 		// Position the TexGenNode in the world with the camera;
> 		posTexGen->setMatrix(aManipulator->getInverseMatrix());
>
> 		viewer.frame();
> 	}
> 	return 0;
> }
>
> Thank you!
>
> Cheers,
> Ekaterina
>
> ------------------
> Read this topic online here:
> http://forum.openscenegraph.org/viewtopic.php?p=69752#69752
>
>
>
>
>
> _______________________________________________
> osg-users mailing list
> osg-users at lists.openscenegraph.org
> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org




More information about the osg-users mailing list