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

Ekaterina Fokina ekaterina.fokina at tum.de
Fri Dec 23 05:10:05 PST 2016


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?

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








More information about the osg-users mailing list