Moved the testing and setting up of FBO/Pbuffer extension from CullVisitor to
support into RenderStage to allow better fallback implementations.
This commit is contained in:
@@ -119,9 +119,14 @@ class OSGUTIL_EXPORT RenderStage : public RenderBin
|
||||
/** Get the clear color.*/
|
||||
int getClearStencil() const { return _clearStencil; }
|
||||
|
||||
|
||||
void setCameraNode(const osg::CameraNode* camera) { _camera = camera; }
|
||||
void setCameraNode(osg::CameraNode* camera) { if (_camera!=camera) { _camera = camera; _cameraRequiresSetUp = true; } }
|
||||
osg::CameraNode* getCameraNode() { return _camera; }
|
||||
const osg::CameraNode* getCameraNode() const { return _camera; }
|
||||
|
||||
void setCameraRequiresSetUp(bool flag) { _cameraRequiresSetUp = true; }
|
||||
bool getCameraRequiresSetUp() const { return _cameraRequiresSetUp; }
|
||||
|
||||
void runCameraSetUp(osg::State& state);
|
||||
|
||||
void setTexture(osg::Texture* texture, unsigned int level = 0, unsigned int face=0) { _texture = texture; _level = level; _face = face; }
|
||||
osg::Texture* getTexture() { return _texture.get(); }
|
||||
@@ -216,7 +221,8 @@ class OSGUTIL_EXPORT RenderStage : public RenderBin
|
||||
double _clearDepth;
|
||||
int _clearStencil;
|
||||
|
||||
const osg::CameraNode* _camera;
|
||||
bool _cameraRequiresSetUp;
|
||||
osg::CameraNode* _camera;
|
||||
|
||||
osg::ref_ptr<osg::Texture> _texture;
|
||||
unsigned int _level;
|
||||
|
||||
@@ -1205,212 +1205,6 @@ void CullVisitor::apply(osg::CameraNode& camera)
|
||||
break;
|
||||
}
|
||||
|
||||
osg::CameraNode::BufferAttachmentMap& bufferAttachements = camera.getBufferAttachmentMap();
|
||||
for(osg::CameraNode::BufferAttachmentMap::iterator itr = bufferAttachements.begin();
|
||||
itr != bufferAttachements.end();
|
||||
++itr)
|
||||
{
|
||||
// assign the texture... pro
|
||||
if (itr->second._texture.valid()) rtts->setTexture(itr->second._texture.get(), itr->second._level, itr->second._face);
|
||||
|
||||
// if one exist attach image to the RenderToTextureStage.
|
||||
if (itr->second._image.valid()) rtts->setImage(itr->second._image.get());
|
||||
}
|
||||
|
||||
if (camera.getRenderTargetImplementation()==osg::CameraNode::FRAME_BUFFER_OBJECT)
|
||||
{
|
||||
osg::ref_ptr<osg::FrameBufferObject> fbo = rtts->getFrameBufferObject();
|
||||
|
||||
if (!fbo)
|
||||
{
|
||||
fbo = new osg::FrameBufferObject;
|
||||
rtts->setFrameBufferObject(fbo.get());
|
||||
|
||||
rtts->setDrawBuffer(GL_BACK);
|
||||
rtts->setReadBuffer(GL_BACK);
|
||||
|
||||
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):
|
||||
{
|
||||
fbo->setAttachment(GL_DEPTH_ATTACHMENT_EXT, osg::FrameBufferAttachment(attachment));
|
||||
depthAttached = true;
|
||||
break;
|
||||
}
|
||||
case(osg::CameraNode::STENCIL_BUFFER):
|
||||
{
|
||||
fbo->setAttachment(GL_STENCIL_ATTACHMENT_EXT, osg::FrameBufferAttachment(attachment));
|
||||
stencilAttached = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
fbo->setAttachment(GL_COLOR_ATTACHMENT0_EXT+(buffer-osg::CameraNode::COLOR_BUFFER0), osg::FrameBufferAttachment(attachment));
|
||||
colorAttached = true;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!depthAttached)
|
||||
{
|
||||
fbo->setAttachment(GL_DEPTH_ATTACHMENT_EXT, osg::FrameBufferAttachment(new osg::RenderBuffer(viewport->width(), viewport->height(), GL_DEPTH_COMPONENT24)));
|
||||
}
|
||||
|
||||
if (!colorAttached)
|
||||
{
|
||||
fbo->setAttachment(GL_COLOR_ATTACHMENT0_EXT, osg::FrameBufferAttachment(new osg::RenderBuffer(viewport->width(), viewport->height(), GL_RGB)));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (camera.getRenderTargetImplementation()==osg::CameraNode::PIXEL_BUFFER_RTT ||
|
||||
camera.getRenderTargetImplementation()==osg::CameraNode::PIXEL_BUFFER ||
|
||||
camera.getRenderTargetImplementation()==osg::CameraNode::SEPERATE_WINDOW )
|
||||
{
|
||||
osg::ref_ptr<osg::GraphicsContext> context = rtts->getGraphicsContext();
|
||||
if (!context)
|
||||
{
|
||||
osg::Texture* pBufferTexture = 0;
|
||||
|
||||
// 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.getRenderTargetImplementation()==osg::CameraNode::PIXEL_BUFFER || camera.getRenderTargetImplementation()==osg::CameraNode::PIXEL_BUFFER_RTT);
|
||||
traits->_windowDecoration = (camera.getRenderTargetImplementation()==osg::CameraNode::SEPERATE_WINDOW);
|
||||
traits->_doubleBuffer = (camera.getRenderTargetImplementation()==osg::CameraNode::SEPERATE_WINDOW);
|
||||
|
||||
rtts->setDrawBuffer(GL_FRONT);
|
||||
rtts->setReadBuffer(GL_FRONT);
|
||||
|
||||
GLenum bufferFormat = GL_NONE;
|
||||
|
||||
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;
|
||||
}
|
||||
case(osg::CameraNode::COLOR_BUFFER):
|
||||
{
|
||||
if (attachment._internalFormat!=GL_NONE)
|
||||
{
|
||||
bufferFormat = attachment._internalFormat;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (attachment._texture.valid())
|
||||
{
|
||||
pBufferTexture = attachment._texture.get();
|
||||
bufferFormat = attachment._texture->getInternalFormat();
|
||||
}
|
||||
else if (attachment._image.valid())
|
||||
{
|
||||
bufferFormat = attachment._image->getInternalTextureFormat();
|
||||
}
|
||||
else
|
||||
{
|
||||
bufferFormat = GL_RGBA;
|
||||
}
|
||||
}
|
||||
|
||||
if (camera.getRenderTargetImplementation()==osg::CameraNode::PIXEL_BUFFER_RTT)
|
||||
{
|
||||
traits->_target = bufferFormat;
|
||||
traits->_level = attachment._level;
|
||||
traits->_face = attachment._face;
|
||||
traits->_mipMapGeneration = attachment._mipMapGeneration;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
if (camera.getRenderTargetImplementation()==osg::CameraNode::SEPERATE_WINDOW)
|
||||
osg::notify(osg::NOTICE)<<"Warning: Window ";
|
||||
else
|
||||
osg::notify(osg::NOTICE)<<"Warning: Pbuffer ";
|
||||
|
||||
osg::notify(osg::NOTICE)<<"does not support multiple color outputs."<<std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!depthAttached)
|
||||
{
|
||||
traits->_depth = 24;
|
||||
}
|
||||
|
||||
if (!colorAttached)
|
||||
{
|
||||
if (bufferFormat == GL_NONE) bufferFormat = GL_RGB;
|
||||
|
||||
traits->_red = 8;
|
||||
traits->_green = 8;
|
||||
traits->_blue = 8;
|
||||
traits->_alpha = (bufferFormat==GL_RGBA) ? 8 : 0;
|
||||
}
|
||||
|
||||
// share OpenGL objects if possible...
|
||||
if (_state.valid() && _state->getGraphicsContext())
|
||||
{
|
||||
traits->_sharedContext = _state->getGraphicsContext();
|
||||
}
|
||||
|
||||
// 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());
|
||||
|
||||
if (pBufferTexture && camera.getRenderTargetImplementation()==osg::CameraNode::PIXEL_BUFFER_RTT)
|
||||
{
|
||||
pBufferTexture->setReadPBuffer(context.get());
|
||||
}
|
||||
#if 0
|
||||
context->createGraphicsThread();
|
||||
#else
|
||||
context->realize();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// restore the previous model view matrix.
|
||||
|
||||
@@ -143,6 +143,231 @@ void RenderStage::drawPreRenderStages(osg::State& state,RenderLeaf*& previous)
|
||||
//cout << "Done Drawing prerendering stages "<<this<< " "<<_viewport->x()<<","<< _viewport->y()<<","<< _viewport->width()<<","<< _viewport->height()<<std::endl;
|
||||
}
|
||||
|
||||
|
||||
void RenderStage::runCameraSetUp(osg::State& state)
|
||||
{
|
||||
_cameraRequiresSetUp = false;
|
||||
|
||||
if (!_camera) return;
|
||||
|
||||
osg::CameraNode::RenderTargetImplementation renderTargetImplemntation = _camera->getRenderTargetImplementation();
|
||||
|
||||
osg::CameraNode::BufferAttachmentMap& bufferAttachements = _camera->getBufferAttachmentMap();
|
||||
for(osg::CameraNode::BufferAttachmentMap::iterator itr = bufferAttachements.begin();
|
||||
itr != bufferAttachements.end();
|
||||
++itr)
|
||||
{
|
||||
// assign the texture... pro
|
||||
if (itr->second._texture.valid()) setTexture(itr->second._texture.get(), itr->second._level, itr->second._face);
|
||||
|
||||
// if one exist attach image to the RenderToTextureStage.
|
||||
if (itr->second._image.valid()) setImage(itr->second._image.get());
|
||||
}
|
||||
|
||||
if (renderTargetImplemntation==osg::CameraNode::FRAME_BUFFER_OBJECT)
|
||||
{
|
||||
osg::FBOExtensions* fbo_ext = osg::FBOExtensions::instance(state.getContextID());
|
||||
bool fbo_supported = fbo_ext && fbo_ext->isSupported();
|
||||
|
||||
if (!fbo_supported)
|
||||
{
|
||||
// fallback to using pbuffer
|
||||
osg::notify(osg::NOTICE)<<"Using fallback to Pbuffer"<<std::endl;
|
||||
renderTargetImplemntation = osg::CameraNode::PIXEL_BUFFER;
|
||||
}
|
||||
else if (!_fbo)
|
||||
{
|
||||
_fbo = new osg::FrameBufferObject;
|
||||
|
||||
setDrawBuffer(GL_BACK);
|
||||
setReadBuffer(GL_BACK);
|
||||
|
||||
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):
|
||||
{
|
||||
_fbo->setAttachment(GL_DEPTH_ATTACHMENT_EXT, osg::FrameBufferAttachment(attachment));
|
||||
depthAttached = true;
|
||||
break;
|
||||
}
|
||||
case(osg::CameraNode::STENCIL_BUFFER):
|
||||
{
|
||||
_fbo->setAttachment(GL_STENCIL_ATTACHMENT_EXT, osg::FrameBufferAttachment(attachment));
|
||||
stencilAttached = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
_fbo->setAttachment(GL_COLOR_ATTACHMENT0_EXT+(buffer-osg::CameraNode::COLOR_BUFFER0), osg::FrameBufferAttachment(attachment));
|
||||
colorAttached = true;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!depthAttached)
|
||||
{
|
||||
_fbo->setAttachment(GL_DEPTH_ATTACHMENT_EXT, osg::FrameBufferAttachment(new osg::RenderBuffer(_viewport->width(), _viewport->height(), GL_DEPTH_COMPONENT24)));
|
||||
}
|
||||
|
||||
if (!colorAttached)
|
||||
{
|
||||
_fbo->setAttachment(GL_COLOR_ATTACHMENT0_EXT, osg::FrameBufferAttachment(new osg::RenderBuffer(_viewport->width(), _viewport->height(), GL_RGB)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (renderTargetImplemntation==osg::CameraNode::PIXEL_BUFFER_RTT ||
|
||||
renderTargetImplemntation==osg::CameraNode::PIXEL_BUFFER ||
|
||||
renderTargetImplemntation==osg::CameraNode::SEPERATE_WINDOW )
|
||||
{
|
||||
osg::ref_ptr<osg::GraphicsContext> context = getGraphicsContext();
|
||||
if (!context)
|
||||
{
|
||||
osg::Texture* pBufferTexture = 0;
|
||||
|
||||
// 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 = (renderTargetImplemntation==osg::CameraNode::PIXEL_BUFFER || renderTargetImplemntation==osg::CameraNode::PIXEL_BUFFER_RTT);
|
||||
traits->_windowDecoration = (renderTargetImplemntation==osg::CameraNode::SEPERATE_WINDOW);
|
||||
traits->_doubleBuffer = (renderTargetImplemntation==osg::CameraNode::SEPERATE_WINDOW);
|
||||
|
||||
setDrawBuffer(GL_FRONT);
|
||||
setReadBuffer(GL_FRONT);
|
||||
|
||||
GLenum bufferFormat = GL_NONE;
|
||||
|
||||
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;
|
||||
}
|
||||
case(osg::CameraNode::COLOR_BUFFER):
|
||||
{
|
||||
if (attachment._internalFormat!=GL_NONE)
|
||||
{
|
||||
bufferFormat = attachment._internalFormat;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (attachment._texture.valid())
|
||||
{
|
||||
pBufferTexture = attachment._texture.get();
|
||||
bufferFormat = attachment._texture->getInternalFormat();
|
||||
}
|
||||
else if (attachment._image.valid())
|
||||
{
|
||||
bufferFormat = attachment._image->getInternalTextureFormat();
|
||||
}
|
||||
else
|
||||
{
|
||||
bufferFormat = GL_RGBA;
|
||||
}
|
||||
}
|
||||
|
||||
if (renderTargetImplemntation==osg::CameraNode::PIXEL_BUFFER_RTT)
|
||||
{
|
||||
traits->_target = bufferFormat;
|
||||
traits->_level = attachment._level;
|
||||
traits->_face = attachment._face;
|
||||
traits->_mipMapGeneration = attachment._mipMapGeneration;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
if (renderTargetImplemntation==osg::CameraNode::SEPERATE_WINDOW)
|
||||
osg::notify(osg::NOTICE)<<"Warning: Window ";
|
||||
else
|
||||
osg::notify(osg::NOTICE)<<"Warning: Pbuffer ";
|
||||
|
||||
osg::notify(osg::NOTICE)<<"does not support multiple color outputs."<<std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!depthAttached)
|
||||
{
|
||||
traits->_depth = 24;
|
||||
}
|
||||
|
||||
if (!colorAttached)
|
||||
{
|
||||
if (bufferFormat == GL_NONE) bufferFormat = GL_RGB;
|
||||
|
||||
traits->_red = 8;
|
||||
traits->_green = 8;
|
||||
traits->_blue = 8;
|
||||
traits->_alpha = (bufferFormat==GL_RGBA) ? 8 : 0;
|
||||
}
|
||||
|
||||
// share OpenGL objects if possible...
|
||||
if (state.getGraphicsContext())
|
||||
{
|
||||
traits->_sharedContext = state.getGraphicsContext();
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
setGraphicsContext(context.get());
|
||||
|
||||
if (pBufferTexture && renderTargetImplemntation==osg::CameraNode::PIXEL_BUFFER_RTT)
|
||||
{
|
||||
pBufferTexture->setReadPBuffer(context.get());
|
||||
}
|
||||
#if 0
|
||||
context->createGraphicsThread();
|
||||
#else
|
||||
bool result = context.valid() ? context->realize() : false;
|
||||
|
||||
osg::notify(osg::NOTICE)<<"Context has been realized "<<result<<std::endl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void RenderStage::copyTexture(osg::State& state)
|
||||
{
|
||||
if (_readBuffer != GL_NONE)
|
||||
@@ -286,6 +511,11 @@ void RenderStage::draw(osg::State& state,RenderLeaf*& previous)
|
||||
// so there is no need to call it here.
|
||||
drawPreRenderStages(state,previous);
|
||||
|
||||
if (_cameraRequiresSetUp)
|
||||
{
|
||||
runCameraSetUp(state);
|
||||
}
|
||||
|
||||
|
||||
osg::State* useState = &state;
|
||||
osg::GraphicsContext* callingContext = state.getGraphicsContext();
|
||||
|
||||
Reference in New Issue
Block a user