Implemented the beginings of the osgProducer::GraphicsContexImplementation.

Added options into osgprerender for controlling how to do the pre rendering i.e.
--fbo, --pbuffer, --fb --window, and also added the option for controlling the
window size with --width and --height.
This commit is contained in:
Robert Osfield
2005-07-21 19:27:19 +00:00
parent 7776924407
commit 302c58fc93
10 changed files with 277 additions and 131 deletions

View File

@@ -49,8 +49,6 @@ class PBufferTexture2D : public osg::Texture2D
glTexImage2D( GL_TEXTURE_2D, 0,
format, width, height, 0, format, GL_UNSIGNED_BYTE, 0 );
textureObject->setAllocated(true);
std::cout<<"Created texture"<<std::endl;
}
else
{
@@ -58,15 +56,7 @@ class PBufferTexture2D : public osg::Texture2D
static unsigned int frameNum = 0;
if ((frameNum % 100)==0)
{
std::cout<<"binding texture"<<std::endl;
_pbuffer->bindPBufferToTexture( Producer::RenderSurface::FrontBuffer );
}
else
{
std::cout<<"..."<<std::endl;
}
_pbuffer->bindPBufferToTexture( Producer::RenderSurface::FrontBuffer );
++frameNum;
@@ -453,7 +443,7 @@ int main( int argc, char **argv )
}
}
printf( "PBuffer window: 0x%x\n", pbuffer->getWindow() );
printf( "PBuffer window: 0x%x\n", pbuffer->getWindow() );
viewer.getCamera(0)->setClearColor( 0.1f,0.9f,0.3f,1.0f );

View File

@@ -107,136 +107,139 @@ class MyGeometryCallback :
};
osg::Node* createPreRenderSubGraph(osg::Node* subgraph)
osg::Node* createPreRenderSubGraph(osg::Node* subgraph, unsigned tex_width, unsigned tex_height, osg::CameraNode::RenderTargetImplementation renderImplementation)
{
if (!subgraph) return 0;
// create the quad to visualize.
osg::Geometry* polyGeom = new osg::Geometry();
polyGeom->setSupportsDisplayList(false);
osg::Vec3 origin(0.0f,0.0f,0.0f);
osg::Vec3 xAxis(1.0f,0.0f,0.0f);
osg::Vec3 yAxis(0.0f,0.0f,1.0f);
osg::Vec3 zAxis(0.0f,-1.0f,0.0f);
float height = 100.0f;
float width = 200.0f;
int noSteps = 20;
osg::Vec3Array* vertices = new osg::Vec3Array;
osg::Vec3 bottom = origin;
osg::Vec3 top = origin; top.z()+= height;
osg::Vec3 dv = xAxis*(width/((float)(noSteps-1)));
osg::Vec2Array* texcoords = new osg::Vec2Array;
osg::Vec2 bottom_texcoord(0.0f,0.0f);
osg::Vec2 top_texcoord(0.0f,1.0f);
osg::Vec2 dv_texcoord(1.0f/(float)(noSteps-1),0.0f);
for(int i=0;i<noSteps;++i)
{
vertices->push_back(top);
vertices->push_back(bottom);
top+=dv;
bottom+=dv;
texcoords->push_back(top_texcoord);
texcoords->push_back(bottom_texcoord);
top_texcoord+=dv_texcoord;
bottom_texcoord+=dv_texcoord;
}
// pass the created vertex array to the points geometry object.
polyGeom->setVertexArray(vertices);
polyGeom->setTexCoordArray(0,texcoords);
osg::Vec4Array* colors = new osg::Vec4Array;
colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
polyGeom->setColorArray(colors);
polyGeom->setColorBinding(osg::Geometry::BIND_OVERALL);
polyGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP,0,vertices->size()));
unsigned int tex_width = 2048;
unsigned int tex_height = 2048;
// new we need to add the texture to the Drawable, we do so by creating a
// StateSet to contain the Texture StateAttribute.
osg::StateSet* stateset = new osg::StateSet;
// create a group to contain the flag and the pre rendering camera.
osg::Group* parent = new osg::Group;
// texture to render to and to use for rendering of flag.
osg::Texture2D* texture = new osg::Texture2D;
texture->setTextureSize(tex_width, tex_height);
texture->setInternalFormat(GL_RGBA);
texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
stateset->setTextureAttributeAndModes(0, texture,osg::StateAttribute::ON);
polyGeom->setStateSet(stateset);
// first create the geometry of the flag of which to view.
{
// create the to visualize.
osg::Geometry* polyGeom = new osg::Geometry();
polyGeom->setUpdateCallback(new MyGeometryCallback(origin,xAxis,yAxis,zAxis,1.0,1.0/width,0.2f));
polyGeom->setSupportsDisplayList(false);
osg::Geode* geode = new osg::Geode();
geode->addDrawable(polyGeom);
osg::Vec3 origin(0.0f,0.0f,0.0f);
osg::Vec3 xAxis(1.0f,0.0f,0.0f);
osg::Vec3 yAxis(0.0f,0.0f,1.0f);
osg::Vec3 zAxis(0.0f,-1.0f,0.0f);
float height = 100.0f;
float width = 200.0f;
int noSteps = 20;
osg::Vec3Array* vertices = new osg::Vec3Array;
osg::Vec3 bottom = origin;
osg::Vec3 top = origin; top.z()+= height;
osg::Vec3 dv = xAxis*(width/((float)(noSteps-1)));
osg::Vec2Array* texcoords = new osg::Vec2Array;
osg::Vec2 bottom_texcoord(0.0f,0.0f);
osg::Vec2 top_texcoord(0.0f,1.0f);
osg::Vec2 dv_texcoord(1.0f/(float)(noSteps-1),0.0f);
for(int i=0;i<noSteps;++i)
{
vertices->push_back(top);
vertices->push_back(bottom);
top+=dv;
bottom+=dv;
texcoords->push_back(top_texcoord);
texcoords->push_back(bottom_texcoord);
top_texcoord+=dv_texcoord;
bottom_texcoord+=dv_texcoord;
}
osg::CameraNode* camera = new osg::CameraNode;
// set up the background color and clear mask.
camera->setClearColor(osg::Vec4(0.1f,0.1f,0.3f,1.0f));
camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// pass the created vertex array to the points geometry object.
polyGeom->setVertexArray(vertices);
polyGeom->setTexCoordArray(0,texcoords);
osg::Vec4Array* colors = new osg::Vec4Array;
colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
polyGeom->setColorArray(colors);
polyGeom->setColorBinding(osg::Geometry::BIND_OVERALL);
polyGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP,0,vertices->size()));
// new we need to add the texture to the Drawable, we do so by creating a
// StateSet to contain the Texture StateAttribute.
osg::StateSet* stateset = new osg::StateSet;
stateset->setTextureAttributeAndModes(0, texture,osg::StateAttribute::ON);
polyGeom->setStateSet(stateset);
polyGeom->setUpdateCallback(new MyGeometryCallback(origin,xAxis,yAxis,zAxis,1.0,1.0/width,0.2f));
osg::Geode* geode = new osg::Geode();
geode->addDrawable(polyGeom);
parent->addChild(geode);
const osg::BoundingSphere& bs = subgraph->getBound();
if (!bs.valid())
{
return subgraph;
}
float znear = 1.0f*bs.radius();
float zfar = 3.0f*bs.radius();
// 2:1 aspect ratio as per flag geomtry below.
float proj_top = 0.25f*znear;
float proj_right = 0.5f*znear;
// then create the camera node to do the render to texture
{
osg::CameraNode* camera = new osg::CameraNode;
znear *= 0.9f;
zfar *= 1.1f;
// set up the background color and clear mask.
camera->setClearColor(osg::Vec4(0.1f,0.1f,0.3f,1.0f));
camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// set up projection.
camera->setProjectionMatrixAsFrustum(-proj_right,proj_right,-proj_top,proj_top,znear,zfar);
const osg::BoundingSphere& bs = subgraph->getBound();
if (!bs.valid())
{
return subgraph;
}
// set view
camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
camera->setViewMatrixAsLookAt(bs.center()-osg::Vec3(0.0f,2.0f,0.0f)*bs.radius(),bs.center(),osg::Vec3(0.0f,0.0f,1.0f));
float znear = 1.0f*bs.radius();
float zfar = 3.0f*bs.radius();
// set viewport
camera->setViewport(0,0,tex_width,tex_height);
// set the camera to render before the main camera.
camera->setRenderOrder(osg::CameraNode::PRE_RENDER);
// tell the camera to use OpenGL frame buffer object where supported.
camera->setRenderTargetImplmentation(osg::CameraNode::FRAME_BUFFER_OBJECT);
// attach the texture and use it as the color buffer.
camera->attach(osg::CameraNode::COLOR_BUFFER, texture);
// 2:1 aspect ratio as per flag geomtry below.
float proj_top = 0.25f*znear;
float proj_right = 0.5f*znear;
// add subgraph to render
camera->addChild(subgraph);
// create a group to contain the flag and the pre rendering camera.
osg::Group* parent = new osg::Group;
parent->addChild(camera);
parent->addChild(geode);
znear *= 0.9f;
zfar *= 1.1f;
// set up projection.
camera->setProjectionMatrixAsFrustum(-proj_right,proj_right,-proj_top,proj_top,znear,zfar);
// set view
camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
camera->setViewMatrixAsLookAt(bs.center()-osg::Vec3(0.0f,2.0f,0.0f)*bs.radius(),bs.center(),osg::Vec3(0.0f,0.0f,1.0f));
// set viewport
camera->setViewport(0,0,tex_width,tex_height);
// set the camera to render before the main camera.
camera->setRenderOrder(osg::CameraNode::PRE_RENDER);
// tell the camera to use OpenGL frame buffer object where supported.
camera->setRenderTargetImplmentation(renderImplementation);
// attach the texture and use it as the color buffer.
camera->attach(osg::CameraNode::COLOR_BUFFER, texture);
// add subgraph to render
camera->addChild(subgraph);
parent->addChild(camera);
}
return parent;
}
@@ -267,6 +270,19 @@ int main( int argc, char **argv )
return 1;
}
unsigned tex_width = 1024;
unsigned tex_height = 512;
while (arguments.read("--width", tex_width)) {}
while (arguments.read("--height", tex_height)) {}
osg::CameraNode::RenderTargetImplementation renderImplementation = osg::CameraNode::FRAME_BUFFER_OBJECT;
while (arguments.read("--fbo")) { renderImplementation = osg::CameraNode::FRAME_BUFFER_OBJECT; }
while (arguments.read("--pbuffer")) { renderImplementation = osg::CameraNode::PIXEL_BUFFER; }
while (arguments.read("--fb")) { renderImplementation = osg::CameraNode::FRAME_BUFFER; }
while (arguments.read("--window")) { renderImplementation = osg::CameraNode::SEPERATE_WINDOW; }
// any option left unread are converted into errors to write out later.
arguments.reportRemainingOptionsAsUnrecognized();
@@ -288,7 +304,6 @@ int main( int argc, char **argv )
osg::Node* loadedModel = osgDB::readNodeFiles(arguments);
if (!loadedModel)
{
// write_usage(osg::notify(osg::NOTICE),argv[0]);
return 1;
}
@@ -300,8 +315,7 @@ int main( int argc, char **argv )
loadedModelTransform->setUpdateCallback(nc);
osg::Group* rootNode = new osg::Group();
// rootNode->addChild(loadedModelTransform);
rootNode->addChild(createPreRenderSubGraph(loadedModelTransform));
rootNode->addChild(createPreRenderSubGraph(loadedModelTransform,tex_width,tex_height, renderImplementation));
// add model to the viewer.

View File

@@ -184,7 +184,8 @@ class OSG_EXPORT CameraNode : public Transform, public CullSettings
{
FRAME_BUFFER_OBJECT,
PIXEL_BUFFER,
FRAME_BUFFER
FRAME_BUFFER,
SEPERATE_WINDOW
};
void setRenderTargetImplmentation(RenderTargetImplementation impl) { _renderTargetImplementation = impl; }

View File

@@ -120,18 +120,21 @@ class OSG_EXPORT GraphicsContext : public Referenced
/** Return true if the current thread has this OpenGL graphics context.*/
inline bool isCurrent() const { return _threadOfLastMakeCurrent == OpenThreads::Thread::CurrentThread(); }
/** Release the graphics context.*/
virtual void release() = 0;
/** Make this graphics context current.*/
virtual void makeCurrent() = 0;
/** Make this graphics context current with specified read context.*/
virtual void makeCurrentContext(GraphicsContext* readContext) = 0;
/** Release the graphics context.*/
virtual void release() = 0;
virtual void makeContextCurrent(GraphicsContext* readContext) = 0;
/** Bind the graphics context to associated texture.*/
virtual void bindPBufferToTexture(GLenum buffer) = 0;
/** swap the front and back buffers.*/
virtual void swapBuffers() = 0;
protected:
GraphicsContext();

View File

@@ -28,6 +28,7 @@
#include <osg/Matrixd>
#include <osgProducer/OsgSceneHandler>
#include <osgProducer/GraphicsContextImplementation>
namespace osgProducer {
@@ -55,6 +56,15 @@ class OSGPRODUCER_EXPORT OsgCameraGroup : public Producer::CameraGroup
const osg::ApplicationUsage* getApplicationUsage() const { return _applicationUsage; }
typedef std::vector< osg::ref_ptr<GraphicsContextImplementation> > GraphicsContextList;
void setGraphicsContextList(GraphicsContextList& gcList) { _gcList = gcList; }
GraphicsContextList& getGraphicsContextList() { return _gcList;}
const GraphicsContextList& getGraphicsContextList() const { return _gcList;}
typedef std::vector < osg::ref_ptr<osgProducer::OsgSceneHandler> > SceneHandlerList;
SceneHandlerList& getSceneHandlerList() { return _shvec;}
@@ -212,6 +222,7 @@ class OSGPRODUCER_EXPORT OsgCameraGroup : public Producer::CameraGroup
unsigned int _realizeSceneViewOptions;
GraphicsContextList _gcList;
SceneHandlerList _shvec;
osg::ref_ptr<RealizeCallback> _realizeCallback;

View File

@@ -16,6 +16,7 @@
#include <osg/Texture2D>
#include <osg/FrameBufferObject>
#include <osg/GraphicsContext>
#include <osgUtil/RenderStage>
@@ -56,6 +57,10 @@ class OSGUTIL_EXPORT RenderToTextureStage : public RenderStage
void setFrameBufferObject(osg::FrameBufferObject* fbo) { _fbo = fbo; }
osg::FrameBufferObject* getFrameBufferObject() { return _fbo.get(); }
const osg::FrameBufferObject* getFrameBufferObject() const { return _fbo.get(); }
void setGraphicsContext(osg::GraphicsContext* context) { _graphicsContext = context; }
osg::GraphicsContext* getGraphicsContext() { return _graphicsContext.get(); }
const osg::GraphicsContext* getGraphicsContext() const { return _graphicsContext.get(); }
virtual void draw(osg::State& state,RenderLeaf*& previous);
@@ -72,6 +77,7 @@ class OSGUTIL_EXPORT RenderToTextureStage : public RenderStage
GLenum _imageReadPixelDataType;
osg::ref_ptr<osg::FrameBufferObject> _fbo;
osg::ref_ptr<osg::GraphicsContext> _graphicsContext;
};

View File

@@ -4,6 +4,7 @@ include $(TOPDIR)/Make/makedefs
CXXFILES =\
EventAdapter.cpp\
KeyboardMouseCallback.cpp\
GraphicsContextImplementation.cpp\
OsgCameraGroup.cpp\
OsgSceneHandler.cpp\
ViewerEventHandler.cpp\

View File

@@ -511,6 +511,19 @@ bool OsgCameraGroup::realize()
}
}
// now set up GraphicsContext wrappers for each of the render surfaces
// to all core OSG classes to keep track of the graphics context.
for(RenderSurfaceStateMap::iterator ritr = _renderSurfaceStateMap.begin();
ritr != _renderSurfaceStateMap.end();
++ritr)
{
Producer::RenderSurface* rs = ritr->first;
osg::State* state = ritr->second;
GraphicsContextImplementation* gc = new GraphicsContextImplementation(rs);
gc->setState(state);
state->setGraphicsContext(gc);
_gcList.push_back(gc);
}
if( _global_stateset == NULL && _shvec.size() > 0 )
{

View File

@@ -1217,6 +1217,84 @@ void CullVisitor::apply(osg::CameraNode& camera)
}
}
}
else if (camera.getRenderTargetImplmentation()==osg::CameraNode::PIXEL_BUFFER ||
camera.getRenderTargetImplmentation()==osg::CameraNode::SEPERATE_WINDOW )
{
osg::ref_ptr<osg::GraphicsContext> context = rtts->getGraphicsContext();
if (!context)
{
// set up the traits of the graphics context that we want
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
traits->_width = viewport->width();
traits->_height = viewport->height();
traits->_pbuffer = (camera.getRenderTargetImplmentation()==osg::CameraNode::PIXEL_BUFFER);
traits->_windowDecoration = (camera.getRenderTargetImplmentation()==osg::CameraNode::SEPERATE_WINDOW);
bool colorAttached = false;
bool depthAttached = false;
bool stencilAttached = false;
for(osg::CameraNode::BufferAttachmentMap::iterator itr = bufferAttachements.begin();
itr != bufferAttachements.end();
++itr)
{
osg::CameraNode::BufferComponent buffer = itr->first;
osg::CameraNode::Attachment& attachment = itr->second;
switch(buffer)
{
case(osg::CameraNode::DEPTH_BUFFER):
{
traits->_depth = 24;
depthAttached = true;
break;
}
case(osg::CameraNode::STENCIL_BUFFER):
{
traits->_stencil = 8;
stencilAttached = true;
break;
}
default:
{
traits->_red = 8;
traits->_green = 8;
traits->_blue = 8;
traits->_alpha = 0; // ??? need to look at attachment, just do quick and dirty right now.
colorAttached = true;
break;
}
}
}
if (!depthAttached)
{
traits->_depth = 24;
}
if (!colorAttached)
{
traits->_red = 8;
traits->_green = 8;
traits->_blue = 8;
traits->_alpha = 0; // ???
}
// create the graphics context according to these traits.
context = osg::GraphicsContext::createGraphicsContext(traits.get());
if (!context)
{
osg::notify(osg::NOTICE)<<"Failed to aquire Graphics Context"<<std::endl;
}
rtts->setGraphicsContext(context.get());
}
}
}

View File

@@ -40,35 +40,64 @@ void RenderToTextureStage::draw(osg::State& state,RenderLeaf*& previous)
//cout << "begining RTTS draw "<<this<< " "<<_viewport->x()<<","<< _viewport->y()<<","<< _viewport->width()<<","<< _viewport->height()<<std::endl;
osg::State* useState = &state;
osg::GraphicsContext* callingContext = state.getGraphicsContext();
osg::GraphicsContext* useContext = callingContext;
if (_graphicsContext.valid() && _graphicsContext != callingContext)
{
useState = _graphicsContext->getState();
useContext = _graphicsContext.get();
useContext->makeCurrent();
glDrawBuffer(GL_FRONT);
glReadBuffer(GL_FRONT);
}
osg::FBOExtensions* fbo_ext = _fbo.valid() ? osg::FBOExtensions::instance(state.getContextID()) : 0;
bool fbo_supported = fbo_ext && fbo_ext->isSupported();
if (fbo_supported)
{
_fbo->apply(state);
_fbo->apply(*useState);
}
RenderStage::draw(state,previous);
// do the actual rendering of the scene.
RenderStage::draw(*useState,previous);
// now copy the rendered image to attached texture.
if (_texture.valid() && !fbo_supported)
{
//cout << " reading "<<this<< " "<<_viewport->x()<<","<< _viewport->y()<<","<< _viewport->width()<<","<< _viewport->height()<<std::endl;
if (callingContext && useContext!= callingContext)
{
// make the calling context use the pbuffer context for reading.
callingContext->makeContextCurrent(useContext);
glReadBuffer(GL_FRONT);
}
// need to implement texture cube map etc...
_texture->copyTexImage2D(state,_viewport->x(),_viewport->y(),_viewport->width(),_viewport->height());
}
if (_image.valid())
{
_image->readPixels(_viewport->x(),_viewport->y(),_viewport->width(),_viewport->height(),_imageReadPixelFormat,_imageReadPixelDataType);
}
if (fbo_supported)
{
// switch of the frame buffer object
fbo_ext->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
if (callingContext && useContext != callingContext)
{
// restore the graphics context.
callingContext->makeCurrent();
glReadBuffer(GL_BACK);
}
}