Thanks again Robert! I really appreciate it.
I've build a small example which should help to demonstrate the problem.
I removed the post processing since it is not reallly helpful nor the
problem. I hope this helps
Greetings
Mathias
Am 05.08.09 14:49, schrieb Robert Osfield:
Hi Mathias,
I can't really give you any recommendation as you are already doing
custom code w.r.t FBO which means there is too many unknowns for me to
guess at.
Robert.
On Wed, Aug 5, 2009 at 1:31 PM, Mathias Buhr<[email protected]> wrote:
Yes, thats exactly the plan but I need the images back in the FB to get the
3rd party stuff working. This means I have to call
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0) before the call to
distortion-code or the function won't work. This assumes the image in
GL_BACK and GL_BACK has to be stored to the FBO afterwards.
How to do this?
Greetings
MAthias
Am 05.08.09 14:08, schrieb Robert Osfield:
HI Mathias,
Given your setup it's pretty clear that you'd need to not use the OSG
in built stereo support (that is implemented internally using
osgUtil::SceneView), and instead setup up two slave camera sets that
do the render to texture/post render for each eye and in the final
step do the checkboard stereo at the same time
Robert.
On Wed, Aug 5, 2009 at 12:34 PM, Mathias Buhr<[email protected]> wrote:
Hi Robert,
thank you for your answer.
I'll try to give some more details on the current setup:
- multiple physical displays/projectors which overlap to produce a single
(flat-)screen
- alignment and blending of the displays is done with the 3rd-party stuff
- the displays support checkerboard-stereo
In mono-mode my integration of OSG and the 3rd party stuff works
perfectly
and all display do what they are supposed to do. The post-processing is
done
in the camera's postDrawCallback without any magic :) The problem starts
when I enable OSGs checkerboard-stereo because the image-distortion in
the
postDrawCallback will result in an unusable checkerboard-frame. So
basically
I'm trying to get checkerboard-stereo to work.
Due to the described problem, I need access to the left and right frames
to
distort them individually. Normally they are "blend together" via
stenciling
in osg::RenderStage::draw(). As far as I know, there is no direct access
to
these frames. I could either implement some kind of callback into OSG or
implement a variant of checkerboard-stereo myself.
Currently I'm trying to render both frames individually to an FBO and
putting them together afterwards. In this case I would have control of
both
frames and I would be able to manipulate them with the help of the
3rd-party
code. osg::Camera::RenderTargetImplementation::FRAME_BUFFER_OBJECT
wasn't
able to do the trick since I've found no way to access the FBO OSG
utilizes.
Therefore I've tried my own implementation (currently on a single
display)
with the following setup and the given result in the post before (take a
look at the attached picture).
The current implementation is very similiar to the osgprerender example
(stereo is not enabled) except that I'm creating my own FBO in a
preDrawCallback of the PRE_RENDER cam. This FBO has an attached texture
and
is used as the rendertarget for the first (left) (RTT-)camera.
RenderTargetImplementation for this camera has not been explicitly set.
The
texture is attached to a rectangular geometry, which is itself a child of
the osgViewers camera. Unfortunately the result of the RTT looks like the
attached image. The image was saved in the postDrawCallback. I'm pretty
sure
I've messed something up or missed something. RTT with OSGs FBO works
fine
and I've looked at the code but I didn't find anything.
Does someone have an idea? Or maybe another way to implement
checkerboard-stereo? It looks like some faces get culled away. If its
useful
I'll post some code.
@Robert: I'm not using osgUtils low level stereo right now but I guess
some
of the code would later be useful to get the correct left and right
camera-position-setup.
Nice greetings and thanks for any help or hint!
Mathias Buhr
P.S.: I was already able to do the distortion with that implementation
(with
blitting the FBO-image back to the window-system provided FB to get the
3rd
party stuff working).
Am 04.08.09 19:14, schrieb Robert Osfield:
Hi Mathias,
You don't really provide enough info about your overall viewer setup
to give a direct answer. It sounds like you are using the OSG's low
level stereo support in osgUtil and combining this with a 3rd party
code that does distortion correction or similar. Doing low level
stereo and distortion correction is really going to work visually even
if you got it to work code wise, as the low level stereo support in
osgUtil assumes a flat display.
Have a bash at explaining what your system is trying to do at a high
level and then others will have a better chance of suggesting how to
go about it.
Robert.
On Tue, Aug 4, 2009 at 4:10 PM, Mathias Buhr<[email protected]>
wrote:
Hi,
before going into the details of the problem, I'd like to explain what
I'm
trying to do and what I have done until now.
I have a 3rd-party function/method which is out of my scope. It seems
to
read and write the window-system provided framebuffer and
manipulates/distorts the image. The first implementation was through
calling
this function in a postdraw-callback. Everything works fine this way.
Unfortunately this is not possible if the CHECKBOARD flag is set
because
the
postdraw-callback is called after the complete frame (including the
stenceling for the checkerboard) is rendered. The function would
distort
the
checkerboard. Hence, I have to apply this function for each "eye"
separately.
This seems possible with some changes to OSG itself but it also would
break
the possibilty to upgrade later. So I decided to take another
approach:
I've tried rendering to an FBO (RTT, similar to osgprerender) but I
can't
apply the function anymore in the postdraw-callback (gives GL errors).
Since
there is no access to the OSG-managed FBO (for bliting from FBO to FB)
I
have implemented my own and rendered to that instead. I'll give you a
brief
overview for that:
MainCamera
- addChild(QUAD_STRIP) //an osg:Geode with an
osg::Texture2D
- addChild(LeftCamera)
- PreDrawCallback:
- if (!fbo) glGenFramebufferEXT
- glBindFramebufferEXT
- glFramebufferTexture2DEXT //attach the
osg::Texture2D
- PostDrawCallback:
- glBindFramebufferEXT(0) //bind window-system fb
LeftCamera is set to PRE_RENDER
This approach gives me the result which is shown in this picture:
http://www.apparatus.de/test1.png
Does someone have an idea what is going wrong or what I've missed? I've
looked at the RenderStage code (and much more :-) ) but I haven't found
something that might be the problem.
Or maybe there is another (better) approach to this problem. Any hints
for
that?
I would appreciate any help! Thank you very much for reading :-)
Greetings
Mathias
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
#include "WarpingTest.h"
#include <osg/FrameBufferObject>
/**
* rotates the cessna
*/
class ModelUpdateCallback : public osg::NodeCallback
{
friend class WarpingTest;
ModelUpdateCallback()
{
_quat.makeRotate(0.01f, osg::Z_AXIS);
}
virtual void operator() (osg::Node *node, osg::NodeVisitor *nv)
{
//that may be dangerous so don't try that at home :-)
osg::PositionAttitudeTransform *pat =
node->asTransform()->asPositionAttitudeTransform();
osg::Quat quat = pat->getAttitude() * _quat;
pat->setAttitude(quat);
traverse(node, nv);
}
osg::Quat _quat;
};
/**
* generates FBO and binds it
*/
class FBOPreDrawCallback : public osg::Camera::DrawCallback
{
friend class WarpingTest;
friend class FBOPostDrawCallback;
FBOPreDrawCallback(osg::Texture* tex) :
_tex(tex)
{
_fbo = 0;
}
virtual void operator() (osg::RenderInfo& renderInfo) const
{
osg::FBOExtensions *ext =
osg::FBOExtensions::instance(renderInfo.getContextID(),true);
if (!_fbo) {
ext->glGenFramebuffersEXT(1,&_fbo);
ext->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,_fbo);
GLuint id =
_tex->getTextureObject(renderInfo.getContextID())->_id;
ext->glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, id, 0);
GLenum status;
status =
ext->glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
switch(status)
{
case GL_FRAMEBUFFER_COMPLETE_EXT:
std::cerr << "framebuffer complete" <<
std::endl;
break;
default:
std::cerr << "framebuffer incomplete!!"
<< std::endl;
}
}
else {
ext->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,_fbo);
}
}
GLuint getFBO() const {return _fbo;}
mutable GLuint _fbo;
osg::Texture *_tex;
};
/**
* holds the FBO for blitting it
* the post-processing happens here (blending/distortion)
*/
class FBOPostDrawCallback : public osg::Camera::DrawCallback
{
friend class WarpingTest;
FBOPostDrawCallback(FBOPreDrawCallback *cb, osg::Texture *tex) :
_tex(tex), _preCB(cb)
{
_fbo = 0;
}
virtual void operator() (osg::RenderInfo& renderInfo) const
{
osg::FBOExtensions *ext =
osg::FBOExtensions::instance(renderInfo.getContextID(),true);
if (!_fbo) {
_fbo = _preCB->getFBO();
}
//DO BLENDING AND DISTORTION HERE
//a handle to the FBO is needed here
//I've removed the code since this mostly works and to keep the
example simple
//I could say I'd like to change the color of some pixels here
//unbind FBO
ext->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0);
}
mutable GLuint _fbo;
osg::Texture *_tex;
FBOPreDrawCallback *_preCB;
};
WarpingTest::WarpingTest()
{
_viewer.addEventHandler(new osgViewer::StatsHandler());
_viewer.addEventHandler(new osgViewer::ThreadingHandler());
_root = new osg::Group;
_leftcam = 0;
_rightcam = 0;
_viewer.setUpViewInWindow(100,100,640,480);
_maincam = _viewer.getCamera();
osg::Vec3d eye(0,0,0);
osg::Vec3d lookat(0,0,0);
_maincam->setViewport(0,0,640,480);
_lefttex = new osg::Texture2D;
_righttex = new osg::Texture2D;
createWorld(_root.get());
}
WarpingTest::~WarpingTest()
{
}
/**
* create the graph
*/
void WarpingTest::createWorld(osg::Group* root)
{
osg::Node* cessna = osgDB::readNodeFile("cessna.osg");
osg::PositionAttitudeTransform *pat = new
osg::PositionAttitudeTransform;
pat->setUpdateCallback(new ModelUpdateCallback);
pat->addChild(cessna);
//TODO
//get BS of node and use its center + radius for cam transformation
osg::Vec3d eye(0,50,0);
osg::Vec3d lookat(0,0,0);
//both cams render the same subgraph but with different positions
//create the left cam and attach it to the root node
osg::Camera* cam = createRTTCam(eye, lookat, _lefttex);
if (cam) {
_leftcam = cam;
_leftcam->addChild(pat);
root->addChild(_leftcam);
}
//create the right cam and attach it to the root node
//cam = createRTTCam(eye, lookat, _righttex);
//if (cam) {
// _rightcam = cam;
// _rightcam->addChild(pat);
// root->addChild(_rightcam);
//}
//similar to osgprerender
//just done for the left camera
osg::Vec3Array* verts = new osg::Vec3Array;
verts->push_back(osg::Vec3(-32,0,-24));
verts->push_back(osg::Vec3(-32,0,24));
verts->push_back(osg::Vec3(32,0,-24));
verts->push_back(osg::Vec3(32,0,24));
osg::Vec2Array* texcoords = new osg::Vec2Array;
texcoords->push_back(osg::Vec2(0.0f, 0.0f));
texcoords->push_back(osg::Vec2(1.0f,0.0f));
texcoords->push_back(osg::Vec2(0.0f,1.0f));
texcoords->push_back(osg::Vec2(1.0f,1.0f));
osg::Geometry* screen = new osg::Geometry();
screen->setDataVariance(osg::Object::DYNAMIC);
screen->setSupportsDisplayList(false);
screen->setVertexArray(verts);
screen->setTexCoordArray(0, texcoords);
screen->addPrimitiveSet(new
osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP,0,verts->size()));
osg::StateSet* stateset= new osg::StateSet;
stateset->setTextureAttributeAndModes(0, _lefttex,
osg::StateAttribute::ON);
screen->setStateSet(stateset);
osg::Geode* geodeleft = new osg::Geode();
geodeleft->getOrCreateStateSet()->setMode(GL_LIGHTING,
osg::StateAttribute::OFF);
geodeleft->addDrawable(screen);
_root->addChild(geodeleft);
}
/**
* creates a cam with given attitude (not really right now)
*/
osg::Camera* WarpingTest::createRTTCam(osg::Vec3d eye, osg::Vec3d lookAt,
osg::Texture2D *texture2d)
{
osg::Camera *cam = new osg::Camera;
texture2d->setTextureSize(640,480);
texture2d->setInternalFormat(GL_RGBA);
texture2d->setFilter(osg::Texture2D::MIN_FILTER,
osg::Texture2D::LINEAR);
texture2d->setFilter(osg::Texture2D::MAG_FILTER,
osg::Texture2D::LINEAR);
cam->setClearColor(osg::Vec4(1.0f,0.0f,0.0f,1.0f));
cam->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
cam->setProjectionMatrixAsPerspective(45,1,10,1000);
cam->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
cam->setViewMatrixAsLookAt(eye, lookAt, osg::Z_AXIS);
cam->setViewport(0,0,640,480);
cam->setRenderOrder(osg::Camera::PRE_RENDER);
//not needed?
// osg::Camera::RenderTargetImplementation renderImpl =
osg::Camera::FRAME_BUFFER_OBJECT;
// cam->setRenderTargetImplementation(renderImplementation);
// cam->attach(osg::Camera::COLOR_BUFFER,_lefttex);
//DEBUG
//_image = new osg::Image;
//_image->allocateImage(640,480,1, GL_RGB, GL_BYTE);
//cam->attach(osg::Camera::COLOR_BUFFER, _image, 0,0);
//cam->setFinalDrawCallback(new ImageFinalDrawCallback(true,_image));
FBOPreDrawCallback *cb = new FBOPreDrawCallback(_lefttex);
cam->setPreDrawCallback(cb);
cam->setPostDrawCallback(new FBOPostDrawCallback(cb,_lefttex));
return cam;
}
void WarpingTest::run()
{
_viewer.setSceneData(_root);
_viewer.run();
}
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org