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

179 views
Skip to first unread message

Ekaterina Fokina

unread,
Dec 21, 2016, 9:56:54 AM12/21/16
to osg-...@lists.openscenegraph.org
Hello,

I am trying to understand how to project a texture on a specific part of the terrain. There are many examples how to project a texture on a whole object, but not to a part of the oblect. That means the question is how to specify texture coordinates (using the shader) on order to project a texture on a right place?

I have found an examle in internet:
http://jotschi.de/2009/05/31/projective-textures-with-openscenegraph/

But unfortunatelly, It is not working properly and I can see my projection on the terrain, but the rest of it is black.

One more question, does anybody can explain to me what is the difference between the numbers in gl_TextureMatrix[0...7]?


Thank you!

Cheers,
Ekaterina

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=69726#69726





_______________________________________________
osg-users mailing list
osg-...@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Voerman, L.

unread,
Dec 21, 2016, 10:16:32 AM12/21/16
to OpenSceneGraph Users
Hi Ekaterina,
seems to me it is working properly, although it does not give you the result you want. 
The black surrounding is just a combination of the texture coordinates going out of range combined with a CLAMP_TO_BORDER wrapping.

the numbers in gl_TextureMatrix[1] are the texture units - the same number passed setTextureAttibutesAndModes

Regards, Laurens.

On Wed, Dec 21, 2016 at 3:57 PM, Ekaterina Fokina <ekaterin...@tum.de> wrote:
Hello,

I am trying to understand how to project a texture on a specific part of the terrain. There are many examples how to project a texture on a whole object, but not to a part of the oblect. That means the question is how to specify texture coordinates (using the shader) on order to project a texture on a right place?

I have found an examle in internet:
http://jotschi.de/2009/05/31/projective-textures-with-openscenegraph/

But unfortunatelly, It is not working properly and I can see my projection on the terrain, but the rest of it is black.

One more question, does anybody can explain to me what is the difference between the numbers in gl_TextureMatrix[0...7]?


Thank you!

Cheers,
Ekaterina

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=69726#69726





_______________________________________________
osg-users mailing list

Glenn Waldron

unread,
Dec 21, 2016, 10:17:09 AM12/21/16
to OpenSceneGraph Users
Ekaterina,
You might try setting your texture border color to transparent.

texture->setBorderColor(osg::Vec4(0,0,0,0));

The index in gl_TextureMatrix[1] is the texture image unit; it should match the slot you specified in your call to

stateset->setTextureAttributeAndModes(1, texMat, osg::StateAttribute::ON);


Glenn Waldron

On Wed, Dec 21, 2016 at 9:57 AM, Ekaterina Fokina <ekaterin...@tum.de> wrote:
Hello,

I am trying to understand how to project a texture on a specific part of the terrain. There are many examples how to project a texture on a whole object, but not to a part of the oblect. That means the question is how to specify texture coordinates (using the shader) on order to project a texture on a right place?

I have found an examle in internet:
http://jotschi.de/2009/05/31/projective-textures-with-openscenegraph/

But unfortunatelly, It is not working properly and I can see my projection on the terrain, but the rest of it is black.

One more question, does anybody can explain to me what is the difference between the numbers in gl_TextureMatrix[0...7]?


Thank you!

Cheers,
Ekaterina

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=69726#69726





_______________________________________________
osg-users mailing list

Ekaterina Fokina

unread,
Dec 22, 2016, 10:02:32 AM12/22/16
to osg-...@lists.openscenegraph.org
Thank you your answers!

Attached there is a printscreen what I get.
For the terrain I am using lz.osgt and the image for the texture file is osg128.png.

I set the border to transparent, but unfortunatelly it didn´t help...

Guys, could you please give me a hint how is it possible to relocate the projected image on the terrain to a specific location on that terrain?
I am still confused how to set the texture coordinats uning shaders.

Thank you!

Cheers,
Ekaterina

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=69738#69738



textureMapping.jpg

Christian Buchner

unread,
Dec 22, 2016, 10:27:42 AM12/22/16
to OpenSceneGraph Users
Just some wild guesses:

You might have to enable blending in the state set, and set an appropriate blend function as (depending on whether your projective texturing is done in a 2nd render pass or not)

On hardware that does not support opengl border colors (ARB_texture_border_clamp) in hardware, you might have to explicitly set the texture's border pixels to a transparent color, turning a 512x512 image into effectively a 510x510 one.

Christian


Trajce Nikolov NICK

unread,
Dec 22, 2016, 10:57:21 AM12/22/16
to OpenSceneGraph Users
Hi Ekaterina,

post your code ... We can fix it when time permits ;-)

_______________________________________________
osg-users mailing list
osg-...@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org



_______________________________________________
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org




--
trajce nikolov nick

Glenn Waldron

unread,
Dec 22, 2016, 10:57:36 AM12/22/16
to OpenSceneGraph Users
Ekaterina,

The model you are loading has a lot of state in it, like blending, textures, etc. When you use a shader to render it, your shader needs to support all the things that OSG would otherwise render using the GL fixed-function pipeline. For example, the texture does not show up because your shader does not sample it anywhere.

So you will need to build a shader program that combines the features in the model with your projective texturing. You might start by looking at the osgUtil::ShaderGen class for some hints, or by running that visitor on your model and then dumping out the source and editing it.

Good luck.

Glenn Waldron

Ekaterina Fokina

unread,
Dec 23, 2016, 8:09:28 AM12/23/16
to osg-...@lists.openscenegraph.org
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

Sebastian Messerschmidt

unread,
Dec 23, 2016, 8:53:56 AM12/23/16
to osg-...@lists.openscenegraph.org


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
Reply all
Reply to author
Forward
0 new messages