Hi,

when i'm using shaders instead of fixed functionality to create projective 
textures the resulting texture mapping is a tiny spot in the center of the 
terrain model.

[Image: http://www.jotschi.de/download/osg/projection_shader.jpg ]

If i disable the shaders by removing the follwing line i get a correct 
projection as you can see in the image below.

Code:

/* 4. Enable this to see that the shader is not working :\ */
stateset->setAttribute(projProg.get());



[Image: http://www.jotschi.de/download/osg/projection_fixedfunctionality.jpg ]


I belive i do something wrong about the texture matrix generation.


My vertex shader just calculates the texture coordinate for the given vertex by 
using the texture matrix 1:

Code:

varying vec4 projCord;
void main()
{
projCord= gl_TextureMatrix[1] * gl_Vertex;
gl_Position = ftransform();
gl_FrontColor = gl_Color;
}




My fragment shader uses the given projCord texture coordinate to load the color 
data from the given projectionMap texture:

Code:

uniform sampler2D projectionMap;
varying vec4 projCord;
void main()
{
vec4 shadowCoordinateWdivide = projCord / projCord.w ;
shadowCoordinateWdivide.z += 0.0015;
vec4 color = texture2D(projectionMap,shadowCoordinateWdivide.st);
gl_FragColor = color * gl_Color;
}







Code:

#include <iostream>
#include <osg/Notify>
#include <osg/MatrixTransform>
#include <osg/ShapeDrawable>
#include <osg/PositionAttitudeTransform>
#include <osg/Geometry>
#include <osg/Texture2D>
#include <osg/Geode>
#include <osg/LightSource>
#include <osg/TexGenNode>
#include <osgUtil/Optimizer>
#include <osgDB/Registry>
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>

osg::StateSet* createProjectorState() {
osg::StateSet* stateset = new osg::StateSet;

/* 1. Load the texture that will be projected */
osg::Texture2D* texture = new osg::Texture2D();
texture->setImage(osgDB::readImageFile("foo.jpg"));
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(1, texture, osg::StateAttribute::ON);

// set up tex gens
stateset->setTextureMode(1, GL_TEXTURE_GEN_S,
osg::StateAttribute::ON);
stateset->setTextureMode(1, GL_TEXTURE_GEN_T,
osg::StateAttribute::ON);
stateset->setTextureMode(1, GL_TEXTURE_GEN_R,
osg::StateAttribute::ON);
stateset->setTextureMode(1, GL_TEXTURE_GEN_Q,
osg::StateAttribute::ON);

/* 2. Load the Shaders */
osg::ref_ptr<osg::Program> projProg(new osg::Program);
osg::ref_ptr<osg::Shader> projvertexShader(osg::Shader::readShaderFile(
osg::Shader::VERTEX, "VertexShader.glsl"));
osg::ref_ptr<osg::Shader> projfragShader(osg::Shader::readShaderFile(
osg::Shader::FRAGMENT, "FragmentShader.glsl"));
projProg->addShader(projvertexShader.get());
projProg->addShader(projfragShader.get());

/* 3. Handover the texture to the fragment shader via uniform */
osg::Uniform* texUniform = new osg::Uniform(osg::Uniform::SAMPLER_2D,
"projectionMap");
texUniform->set(1);
stateset->addUniform(texUniform);

/* 4. Enable this to see that the shader is not working :\ */
stateset->setAttribute(projProg.get());

return stateset;
}

osg::Node* createModel() {

/* 1. Setup projector parameters */
osg::Group* root = new osg::Group;
osg::Vec3 projectorPos = osg::Vec3(0.0f, 0.0f, 324.0f);
osg::Vec3 projectorDirection = osg::Vec3(osg::inDegrees(0.0f),
osg::inDegrees(280.0f), osg::inDegrees(-460.0f));
float projectorAngle = 110;

/* 2. create tex gen. for the texture unit 1*/
osg::Vec3 up(0.0f, 0.0f, 1.0f);
//up = (projectorDirection ^ up) ^ projectorDirection;
//up.normalize();

osg::TexGenNode* texgenNode = new osg::TexGenNode;
/* As you can see texture unit 1 is assigned the texgenNode. Does this mean the 
texture matrix will be stored in: gl_TextureMatrix[1] ?*/
texgenNode->setTextureUnit(1);
osg::TexGen* texgen = texgenNode->getTexGen();
texgen->setMode(osg::TexGen::EYE_LINEAR);
texgen->setPlanesFromMatrix(osg::Matrixd::lookAt(projectorPos, projectorPos
+ projectorDirection, up) * osg::Matrixd::perspective(
projectorAngle, 1.0, 0.1, 100));


root->addChild(texgenNode);

/* 3. Load the terrain which will be the receiver of out projection */
osg::Node* terr = osgDB::readNodeFile("Terrain2.3ds");

osg::Matrix m;
osg::ref_ptr<osg::MatrixTransform> mt =new osg::MatrixTransform;
m.makeTranslate( 112.f, 410.f, -2.f );
m.makeScale(2.f,2.f,2.f);
mt->setMatrix( m );
root->addChild( mt.get() );
mt->addChild( terr );

//root->addChild(terr);

root->setStateSet(createProjectorState());

return root;
}

int main(int, char **) {
osgViewer::Viewer viewer;
viewer.setSceneData(createModel());
viewer.setUpViewInWindow(0, 0, 1024, 768);
return viewer.run();
}




The complete project can be downloaded here:
http://www.jotschi.de/download/osg/OSG_ProjectiveTexturesExample.tgz

Perhaps you have any tips according to my problem? Maybe i have missed a step 
according to the texture matrix generation? 

Thank you!

Cheers,
Johannes

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





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

Reply via email to