[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