Hi Sebastian, tahnk you for your suggestions. I have taken some days to study your solutions and to apply them to my osg application. It seem that something is going on, but i still get some doubts and some errors. In the following code, i simulate the use of two shader on the same 3D object (cessna.osg) using two PRE_RENDER camera : the first shader (test_Pass_0) change the object's color, the second shader (test_Pass_1) should apply a twist deformation on the same 3D Object. Finally, i use the HUD camera to visualize the final effect ( a twisted and colored cessna).
So, briefly :
I use the PRE_RENDER CAMERA (first Camera) to fill the frame buffer with a
texture (first texture) coming from the first shader.
A second PRE_RENDER CAMERA (second Camera), applies on the same object a twist
deformation (with the vertex shader) and this second camera uses the first
texture to get the color for the second shader (fragment shader). The
second camera fills the FBO for the next camera (HUD camera).
My doubt is : Is this approach correct?
The error is : "Warning: detected OpenGL error 'invalid value' at After
Renderer::compile"
I get this error after the test_Pass_1.frag. What i see is the cessna.osg
twisted, but completely black (it seems that the test_pass_1.frag doesn't see
the correct sampler2D input (previousTexture) coming from the first shader
(test_Pass_0.frag). (I report a snapshot about the this result).
First i report the osg code.
Code for HUD CAMERA : the image input means the result of the test_Pass_0 shader
Code:
// this code coming from openscenegraph 3 cookbook
osg::Camera* createHUDCamera( double left, double right, double bottom, double
top )
{
osg::ref_ptr<osg::Camera> camera = new osg::Camera;
camera->setReferenceFrame( osg::Transform::ABSOLUTE_RF );
camera->setClearMask( GL_DEPTH_BUFFER_BIT );
camera->setRenderOrder( osg::Camera::POST_RENDER );
camera->setAllowEventFocus( false );
camera->setProjectionMatrix( osg::Matrix::ortho2D(left, right, bottom,
top) );
camera->getOrCreateStateSet()->setMode( GL_LIGHTING,
osg::StateAttribute::OFF );
return camera.release();
}
// this code coming from openscenegraph 3 cookbook
osg::Geode* createScreenQuad( float width, float height, float scale )
{
osg::Geometry* geom = osg::createTexturedQuadGeometry(
osg::Vec3(), osg::Vec3(width,0.0f,0.0f),
osg::Vec3(0.0f,height,0.0f),
0.0f, 0.0f, width*scale, height*scale );
osg::ref_ptr<osg::Geode> quad = new osg::Geode;
quad->addDrawable( geom );
int values = osg::StateAttribute::OFF|osg::StateAttribute::PROTECTED;
quad->getOrCreateStateSet()->setAttribute(
new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK,
osg::PolygonMode::FILL), values );
quad->getOrCreateStateSet()->setMode( GL_LIGHTING, values );
return quad.release();
}
void ApplyHUDCamera(osg::Texture2D *image, osg::Group* root)
{
std::cout << "APPLY HUD" << std::endl;
{
osg::ref_ptr<osg::Camera> mHudCamera;
mHudCamera = createHUDCamera(0.0, 1.0, 0.0, 1.0);
mHudCamera->addChild( createScreenQuad(1.0f, 1.0f));
osg::ref_ptr<osg::StateSet> mStateset =
mHudCamera->getOrCreateStateSet();
mStateset->setTextureAttributeAndModes( 0, image );
root->addChild(mHudCamera.get());
}
return;
}
The following code, applies the first shader effect : simply, change object's
color
Code:
osg::Texture2D* SingleTexturePass(osg::Group* root,osg::Node*
viewnode,osg::Vec4 clearColor, int windowWidth, int windowHeight)
{
std::cout << "FIRST PASS" << std::endl;
osg::ref_ptr<osg::Texture2D> firstTexture = new osg::Texture2D;
firstTexture->setTextureSize(windowWidth, windowHeight);
firstTexture->setInternalFormat(GL_RGBA);
firstTexture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
firstTexture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
firstTexture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_BORDER);
firstTexture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_BORDER);
//firstTexture->setBorderColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
// set up the render to color texture camera.
{
osg::ref_ptr<osg::Camera> firstCamera = new osg::Camera;
firstCamera->setName("FirstCamera");
// firstCamera->setClearColor(clearColor);
firstCamera->setViewport(0,0,windowWidth,windowHeight);
//firstCamera->setClearStencil(0);
//firstCamera->setClearDepth(0.0);
//firstCamera->setClearAccum(osg::Vec4(1.0,1.0,1.0,1.0));
//firstCamera->setClearMask(GL_COLOR_BUFFER_BIT); // |
GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
//firstCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
//firstCamera->setCullingMode(osg::Camera::VIEW_FRUSTUM_SIDES_CULLING);
//colorCamera->setViewport(the_viewport.get());
//colorCamera->setProjectionMatrix(proj_matrix);
//colorCamera->setViewMatrix(view_matrix);
firstCamera->setRenderOrder(osg::Camera::PRE_RENDER,0);
firstCamera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
firstCamera->attach(osg::Camera::COLOR_BUFFER,firstTexture.get());
firstCamera->addChild(viewnode);
osg::ref_ptr<osg::StateSet> firstStateset =
firstCamera->getOrCreateStateSet();
firstStateset->addUniform(new
osg::Uniform("fVal",0.5f),osg::StateAttribute::ON);
osg::Shader* vertexShader = osgDB::readShaderFile(osg::Shader::VERTEX,
"\\shaders\\shaders\\testMultipass\\test_Pass_0.vert");
osg::Program* firstProgram=new osg::Program();
if (!vertexShader)
{
std::cout << " No vertex Shader Loaded." << std::endl;
return 0;
}
else
{
std::cout << " Vertex Shader Loaded : test_Pass_0.vert " <<
std::endl;
}
osg::Shader* fragShader = osgDB::readShaderFile(osg::Shader::FRAGMENT,
"shaders\\shaders\\testMultipass\\test_Pass_0.frag");
if (!fragShader)
{
std::cout << " No fragment Shader Loaded." << std::endl;
return 0;
}
else
{
std::cout << " fragment Shader Loaded : test_Pass_0.frag " <<
std::endl;
}
firstProgram->addShader(vertexShader);
firstProgram->addShader(fragShader);
firstStateset->setAttributeAndModes(firstProgram);
root->addChild(firstCamera.get());
}
return firstTexture.get();
}
SingleTexturePass returns a texture that can be used by another shader.
The DoubleTexturePass, calls the singleTexturePass first, and then uses the
result as input for the second shader :
Code:
osg::Texture2D* DoubleTexturePass(osg::Group* root,osg::Node*
viewnode,osg::Vec4 clearColor, int windowWidth, int windowHeight)
{
osg::Texture2D* previousTexture=SingleTexturePass(root,viewnode,clearColor,
windowWidth, windowHeight);
std::cout << "Second PASS" << std::endl;
osg::ref_ptr<osg::Texture2D> secondTexture = new osg::Texture2D;
secondTexture->setTextureSize(windowWidth, windowHeight);
secondTexture->setInternalFormat(GL_RGBA);
secondTexture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
secondTexture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
secondTexture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_BORDER);
secondTexture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_BORDER);
// set up the render to normal and depth texture camera.
{
osg::ref_ptr<osg::Camera> secondCamera = new osg::Camera;
secondCamera->setName("SecondCamera");
//secondCamera->setClearColor(clearColor);
secondCamera->setViewport(0,0,windowWidth,windowHeight);
secondCamera->setRenderOrder(osg::Camera::PRE_RENDER,1);
secondCamera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
secondCamera->attach(osg::Camera::COLOR_BUFFER,secondTexture.get());
secondCamera->addChild(viewnode);
osg::ref_ptr<osg::StateSet> secondStateset =
secondCamera->getOrCreateStateSet(); //viewnode
osg::Timer_t startTick = osg::Timer::instance()->tick();
float fTime = 0.5; //(float) osg::Timer::instance()->getSecondsPerTick();
float angle_deg_max = 15.0;
float height = 5.0;
secondStateset->addUniform(new osg::Uniform("height",height));
secondStateset->addUniform(new osg::Uniform("time",fTime));
secondStateset->addUniform(new
osg::Uniform("angle_deg_max",angle_deg_max));
secondStateset->addUniform(new
osg::Uniform("previousTexture",osg::Uniform::SAMPLER_2D));
secondStateset->setTextureAttributeAndModes(0,previousTexture,
osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
osg::Shader* vertexShader2 = osgDB::readShaderFile(osg::Shader::VERTEX,
"\\shaders\\shaders\\testMultipass\\test_Pass_1.vert");
osg::Program* secondProgram=new osg::Program();
if (!vertexShader2)
{
std::cout << " No vertex Shader Loaded." << std::endl;
return 0;
}
else
{
std::cout << " Vertex Shader Loaded : test_Pass_1.vert " <<
std::endl;
}
osg::Shader* fragShader2 = osgDB::readShaderFile(osg::Shader::FRAGMENT,
"shaders\\shaders\\testMultipass\\test_Pass_1.frag");
if (!fragShader2)
{
std::cout << " No fragment Shader Loaded." << std::endl;
return 0;
}
else
{
std::cout << " fragment Shader Loaded : test_Pass_1.frag " <<
std::endl;
}
secondProgram->addShader(vertexShader2);
secondProgram->addShader(fragShader2);
secondStateset->setAttributeAndModes(secondProgram);
root->addChild(secondCamera.get());
}
return secondTexture.get();
}
In the main, i use :
Code:
int main( int argc, char** argv )
{
....
osg::Texture2D*
finalTexture=DoubleTexturePass(main_root.get(),myNode,osg::Vec4(0.3,0.4,0.5,1.0),
1024, 512);
ApplyHUDCamera(finalTexture,main_root.get());
...
}
About the shaders, i use the following code :
PASS0: vertex and shader : only color
Code:
// test_pass_0.vert
varying vec4 COLOR;
void main()
{
COLOR = gl_Color;
gl_Position = ftransform();
}
// test_pass_0.frag
varying vec4 COLOR;
void main()
{
vec4 newcolor = COLOR;
COLOR.r = newcolor.b/2;
COLOR.g = newcolor.r/3;
COLOR.b = newcolor.g;
gl_FragColor = COLOR;
}
PASS1: vertex and shader : Twist
Code:
//test_Pass_1.vert
uniform float time;
uniform float height;
uniform float angle_deg_max;
varying vec2 texture_coordinate;
varying vec4 normal, lightDir[3], eyeVec;
vec4 DoTwist( vec4 pos, float t )
{
float st = sin(t);
float ct = cos(t);
vec4 new_pos;
new_pos.x = pos.x*ct - pos.z*st;
new_pos.z = pos.x*st + pos.z*ct;
new_pos.y = pos.y;
new_pos.w = pos.w;
return( new_pos );
}
void main()
{
float angle_deg = angle_deg_max*sin(time);
float angle_rad = angle_deg * 3.14159 / 180.0;
float ang = (height*0.5 + gl_Vertex.y)/height * angle_rad;
vec4 twistedPosition = DoTwist(gl_Vertex, ang);
// vec4 twistedNormal = DoTwist(vec4(gl_Normal, ang);
gl_Position = gl_ModelViewProjectionMatrix * twistedPosition;
vec3 vVertex = vec3(gl_ModelViewMatrix * twistedPosition);
// lightDir[0] = vec3(gl_LightSource[0].position.xyz - vVertex);
// lightDir[1] = vec3(gl_LightSource[1].position.xyz - vVertex);
// lightDir[2] = vec3(gl_LightSource[2].position.xyz - vVertex);
// eyeVec = -vVertex;
// normal = gl_NormalMatrix * twistedNormal.xyz;
//gl_TexCoord[0] = gl_MultiTexCoord0;
texture_coordinate = vec2(gl_MultiTexCoord0);
//gl_Position = ftransform();
}
//test_Pass_1.frag
uniform sampler2D previousTexture;
varying vec2 texture_coordinate;
void main()
{
vec4 somecolor = texture2D(previousTexture, gl_TexCoord[0].xy);
gl_FragColor = somecolor;
}
Thank you!
Cheers,
Andrea
------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=53717#53717
<<attachment: Multipass_black.jpg>>
_______________________________________________ osg-users mailing list [email protected] http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

