2005-04-15 05:41:28 +08:00
|
|
|
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2005 Robert Osfield
|
2003-01-22 00:45:36 +08:00
|
|
|
*
|
|
|
|
* This library is open source and may be redistributed and/or modified under
|
|
|
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
|
|
|
* (at your option) any later version. The full license is in LICENSE file
|
|
|
|
* included with this distribution, and on the openscenegraph.org website.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* OpenSceneGraph Public License for more details.
|
|
|
|
*/
|
2002-04-04 01:42:12 +08:00
|
|
|
#include <stdio.h>
|
2005-08-17 18:12:49 +08:00
|
|
|
|
2001-09-22 10:42:08 +08:00
|
|
|
#include <osg/Notify>
|
2005-08-17 18:12:49 +08:00
|
|
|
#include <osg/Texture1D>
|
|
|
|
#include <osg/Texture2D>
|
|
|
|
#include <osg/Texture3D>
|
|
|
|
#include <osg/TextureRectangle>
|
|
|
|
#include <osg/TextureCubeMap>
|
2005-11-01 18:42:54 +08:00
|
|
|
#include <osg/GLExtensions>
|
2005-08-17 18:12:49 +08:00
|
|
|
|
2003-07-15 21:46:19 +08:00
|
|
|
#include <osgUtil/Statistics>
|
2001-09-22 10:42:08 +08:00
|
|
|
|
2001-09-20 05:19:47 +08:00
|
|
|
#include <osgUtil/RenderStage>
|
|
|
|
|
2002-07-18 22:20:01 +08:00
|
|
|
|
2001-09-20 05:19:47 +08:00
|
|
|
using namespace osg;
|
|
|
|
using namespace osgUtil;
|
|
|
|
|
|
|
|
// register a RenderStage prototype with the RenderBin prototype list.
|
|
|
|
//RegisterRenderBinProxy<RenderStage> s_registerRenderStageProxy;
|
|
|
|
|
2005-05-24 23:34:23 +08:00
|
|
|
RenderStage::RenderStage():
|
|
|
|
RenderBin(getDefaultRenderBinSortMode())
|
|
|
|
{
|
|
|
|
// point RenderBin's _stage to this to ensure that references to
|
|
|
|
// stage don't go tempted away to any other stage.
|
|
|
|
_stage = this;
|
|
|
|
_stageDrawnThisFrame = false;
|
|
|
|
|
2005-08-17 18:12:49 +08:00
|
|
|
_drawBuffer = GL_NONE;
|
|
|
|
_readBuffer = GL_NONE;
|
2005-05-24 23:34:23 +08:00
|
|
|
_clearMask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
|
|
|
|
_clearColor.set(0.0f,0.0f,0.0f,0.0f);
|
|
|
|
_clearAccum.set(0.0f,0.0f,0.0f,0.0f);
|
|
|
|
_clearDepth = 1.0;
|
|
|
|
_clearStencil = 0;
|
2005-08-17 18:12:49 +08:00
|
|
|
|
|
|
|
_camera = 0;
|
|
|
|
|
|
|
|
_level = 0;
|
|
|
|
_face = 0;
|
|
|
|
|
|
|
|
_imageReadPixelFormat = GL_RGBA;
|
|
|
|
_imageReadPixelDataType = GL_UNSIGNED_BYTE;
|
2005-05-24 23:34:23 +08:00
|
|
|
}
|
|
|
|
|
2002-09-17 23:47:23 +08:00
|
|
|
RenderStage::RenderStage(SortMode mode):
|
|
|
|
RenderBin(mode)
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
|
|
|
// point RenderBin's _stage to this to ensure that references to
|
|
|
|
// stage don't go tempted away to any other stage.
|
|
|
|
_stage = this;
|
|
|
|
_stageDrawnThisFrame = false;
|
|
|
|
|
2005-08-17 18:12:49 +08:00
|
|
|
_drawBuffer = GL_NONE;
|
|
|
|
_readBuffer = GL_NONE;
|
2001-09-20 05:19:47 +08:00
|
|
|
_clearMask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
|
|
|
|
_clearColor.set(0.0f,0.0f,0.0f,0.0f);
|
|
|
|
_clearAccum.set(0.0f,0.0f,0.0f,0.0f);
|
|
|
|
_clearDepth = 1.0;
|
|
|
|
_clearStencil = 0;
|
2005-08-17 18:12:49 +08:00
|
|
|
|
|
|
|
_camera = 0;
|
|
|
|
|
|
|
|
_level = 0;
|
|
|
|
_face = 0;
|
|
|
|
|
|
|
|
_imageReadPixelFormat = GL_RGBA;
|
|
|
|
_imageReadPixelDataType = GL_UNSIGNED_BYTE;
|
2001-09-20 05:19:47 +08:00
|
|
|
}
|
|
|
|
|
2002-09-17 23:47:23 +08:00
|
|
|
RenderStage::RenderStage(const RenderStage& rhs,const osg::CopyOp& copyop):
|
|
|
|
RenderBin(rhs,copyop),
|
|
|
|
_stageDrawnThisFrame(false),
|
2005-06-15 04:51:35 +08:00
|
|
|
_preRenderList(rhs._preRenderList),
|
|
|
|
_postRenderList(rhs._postRenderList),
|
2002-09-17 23:47:23 +08:00
|
|
|
_viewport(rhs._viewport),
|
2005-08-17 18:12:49 +08:00
|
|
|
_drawBuffer(rhs._drawBuffer),
|
|
|
|
_readBuffer(rhs._readBuffer),
|
2002-09-17 23:47:23 +08:00
|
|
|
_clearMask(rhs._clearMask),
|
|
|
|
_colorMask(rhs._colorMask),
|
|
|
|
_clearColor(rhs._clearColor),
|
|
|
|
_clearAccum(rhs._clearAccum),
|
|
|
|
_clearDepth(rhs._clearDepth),
|
|
|
|
_clearStencil(rhs._clearStencil),
|
2005-08-17 18:12:49 +08:00
|
|
|
_camera(rhs._camera),
|
|
|
|
_level(rhs._level),
|
|
|
|
_face(rhs._face),
|
|
|
|
_imageReadPixelFormat(rhs._imageReadPixelFormat),
|
|
|
|
_imageReadPixelDataType(rhs._imageReadPixelDataType),
|
2002-09-17 23:47:23 +08:00
|
|
|
_renderStageLighting(rhs._renderStageLighting)
|
|
|
|
{
|
2002-09-19 17:05:50 +08:00
|
|
|
_stage = this;
|
2002-09-17 23:47:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-09-20 05:19:47 +08:00
|
|
|
RenderStage::~RenderStage()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderStage::reset()
|
|
|
|
{
|
2005-06-15 04:51:35 +08:00
|
|
|
_preRenderList.clear();
|
2001-09-20 05:19:47 +08:00
|
|
|
_stageDrawnThisFrame = false;
|
|
|
|
|
|
|
|
if (_renderStageLighting.valid()) _renderStageLighting->reset();
|
|
|
|
|
|
|
|
RenderBin::reset();
|
|
|
|
}
|
|
|
|
|
2005-06-15 04:51:35 +08:00
|
|
|
void RenderStage::addPreRenderStage(RenderStage* rs)
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
2005-06-15 04:51:35 +08:00
|
|
|
if (rs) _preRenderList.push_back(rs);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderStage::addPostRenderStage(RenderStage* rs)
|
|
|
|
{
|
|
|
|
if (rs) _postRenderList.push_back(rs);
|
2001-09-20 05:19:47 +08:00
|
|
|
}
|
2002-04-22 17:37:17 +08:00
|
|
|
|
2002-09-19 17:52:50 +08:00
|
|
|
void RenderStage::drawPreRenderStages(osg::State& state,RenderLeaf*& previous)
|
|
|
|
{
|
2005-06-15 04:51:35 +08:00
|
|
|
if (_preRenderList.empty()) return;
|
2003-01-24 17:11:05 +08:00
|
|
|
|
|
|
|
//cout << "Drawing prerendering stages "<<this<< " "<<_viewport->x()<<","<< _viewport->y()<<","<< _viewport->width()<<","<< _viewport->height()<<std::endl;
|
2005-06-15 04:51:35 +08:00
|
|
|
for(RenderStageList::iterator itr=_preRenderList.begin();
|
|
|
|
itr!=_preRenderList.end();
|
2002-09-19 17:52:50 +08:00
|
|
|
++itr)
|
|
|
|
{
|
|
|
|
(*itr)->draw(state,previous);
|
|
|
|
}
|
2003-01-24 17:11:05 +08:00
|
|
|
//cout << "Done Drawing prerendering stages "<<this<< " "<<_viewport->x()<<","<< _viewport->y()<<","<< _viewport->width()<<","<< _viewport->height()<<std::endl;
|
2002-09-19 17:52:50 +08:00
|
|
|
}
|
|
|
|
|
2005-10-06 00:21:51 +08:00
|
|
|
|
|
|
|
void RenderStage::runCameraSetUp(osg::State& state)
|
|
|
|
{
|
|
|
|
_cameraRequiresSetUp = false;
|
|
|
|
|
|
|
|
if (!_camera) return;
|
|
|
|
|
|
|
|
osg::CameraNode::RenderTargetImplementation renderTargetImplemntation = _camera->getRenderTargetImplementation();
|
2005-11-01 18:42:54 +08:00
|
|
|
osg::CameraNode::RenderTargetImplementation renderTargetFallback = _camera->getRenderTargetFallback();
|
2005-10-06 00:21:51 +08:00
|
|
|
|
|
|
|
osg::CameraNode::BufferAttachmentMap& bufferAttachements = _camera->getBufferAttachmentMap();
|
2005-10-06 19:26:07 +08:00
|
|
|
|
|
|
|
// attach an images that need to be copied after the stage is drawn.
|
2005-10-06 00:21:51 +08:00
|
|
|
for(osg::CameraNode::BufferAttachmentMap::iterator itr = bufferAttachements.begin();
|
|
|
|
itr != bufferAttachements.end();
|
|
|
|
++itr)
|
|
|
|
{
|
2005-11-01 23:23:03 +08:00
|
|
|
// if one exist attach image to the RenderStage.
|
|
|
|
if (itr->second._image.valid())
|
|
|
|
{
|
|
|
|
osg::Image* image = itr->second._image.get();
|
|
|
|
GLenum pixelFormat = image->getPixelFormat();
|
|
|
|
GLenum dataType = image->getDataType();
|
|
|
|
|
|
|
|
if (image->data()==0)
|
|
|
|
{
|
|
|
|
if (pixelFormat==0) pixelFormat = itr->second._internalFormat;
|
|
|
|
if (pixelFormat==0) pixelFormat = _imageReadPixelFormat;
|
|
|
|
if (pixelFormat==0) pixelFormat = GL_RGBA;
|
|
|
|
|
|
|
|
if (dataType==0) dataType = _imageReadPixelDataType;
|
|
|
|
if (dataType==0) dataType = GL_UNSIGNED_BYTE;
|
|
|
|
|
|
|
|
image->allocateImage(_viewport->width(), _viewport->height(), 1, pixelFormat, dataType);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
_imageReadPixelFormat = pixelFormat;
|
|
|
|
_imageReadPixelDataType = dataType;
|
|
|
|
|
|
|
|
setImage(itr->second._image.get());
|
|
|
|
}
|
2005-10-06 00:21:51 +08:00
|
|
|
}
|
2005-10-06 19:26:07 +08:00
|
|
|
|
2005-10-06 00:21:51 +08:00
|
|
|
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)
|
|
|
|
{
|
2005-11-01 18:42:54 +08:00
|
|
|
if (renderTargetImplemntation<renderTargetFallback)
|
|
|
|
renderTargetImplemntation = renderTargetFallback;
|
|
|
|
else
|
2005-10-06 19:26:07 +08:00
|
|
|
renderTargetImplemntation = osg::CameraNode::PIXEL_BUFFER_RTT;
|
2005-10-06 00:21:51 +08:00
|
|
|
}
|
|
|
|
else if (!_fbo)
|
|
|
|
{
|
2005-11-01 18:42:54 +08:00
|
|
|
osg::notify(osg::INFO)<<"Setting up osg::CameraNode::FRAME_BUFFER_OBJECT"<<std::endl;
|
|
|
|
|
2005-10-06 00:21:51 +08:00
|
|
|
_fbo = new osg::FrameBufferObject;
|
2005-11-01 23:23:03 +08:00
|
|
|
|
2005-10-06 00:21:51 +08:00
|
|
|
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;
|
2005-11-01 23:23:03 +08:00
|
|
|
|
2005-10-06 00:21:51 +08:00
|
|
|
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)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-01 18:42:54 +08:00
|
|
|
// check whether PBuffer-RTT is supported or not
|
|
|
|
if (renderTargetImplemntation==osg::CameraNode::PIXEL_BUFFER_RTT &&
|
|
|
|
!osg::isGLExtensionSupported(state.getContextID(), "ARB_render_texture"))
|
|
|
|
{
|
|
|
|
if (renderTargetImplemntation<renderTargetFallback)
|
|
|
|
renderTargetImplemntation = renderTargetFallback;
|
|
|
|
else
|
|
|
|
renderTargetImplemntation = osg::CameraNode::PIXEL_BUFFER;
|
|
|
|
}
|
2005-10-06 19:26:07 +08:00
|
|
|
|
|
|
|
// if any of the renderTargetImplementations require a seperate graphics context such as with pbuffer try in turn to
|
|
|
|
// set up, but if each level fails then resort to the next level down.
|
|
|
|
while (!getGraphicsContext() &&
|
|
|
|
(renderTargetImplemntation==osg::CameraNode::PIXEL_BUFFER_RTT ||
|
|
|
|
renderTargetImplemntation==osg::CameraNode::PIXEL_BUFFER ||
|
|
|
|
renderTargetImplemntation==osg::CameraNode::SEPERATE_WINDOW) )
|
2005-10-06 00:21:51 +08:00
|
|
|
{
|
|
|
|
osg::ref_ptr<osg::GraphicsContext> context = 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 = (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);
|
|
|
|
|
2005-10-06 19:26:07 +08:00
|
|
|
osg::Texture* pBufferTexture = 0;
|
2005-10-06 00:21:51 +08:00
|
|
|
GLenum bufferFormat = GL_NONE;
|
2005-10-06 19:26:07 +08:00
|
|
|
unsigned int level = 0;
|
|
|
|
unsigned int face = 0;
|
2005-10-06 00:21:51 +08:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-10-06 19:26:07 +08:00
|
|
|
level = attachment._level;
|
|
|
|
face = attachment._face;
|
|
|
|
|
2005-10-06 00:21:51 +08:00
|
|
|
if (renderTargetImplemntation==osg::CameraNode::PIXEL_BUFFER_RTT)
|
|
|
|
{
|
|
|
|
traits->_target = bufferFormat;
|
2005-10-06 19:26:07 +08:00
|
|
|
traits->_level = level;
|
|
|
|
traits->_face = face;
|
2005-10-06 00:21:51 +08:00
|
|
|
traits->_mipMapGeneration = attachment._mipMapGeneration;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
if (renderTargetImplemntation==osg::CameraNode::SEPERATE_WINDOW)
|
2005-10-06 19:26:07 +08:00
|
|
|
osg::notify(osg::NOTICE)<<"Warning: RenderStage::runCameraSetUp(State&) Window ";
|
2005-10-06 00:21:51 +08:00
|
|
|
else
|
2005-10-06 19:26:07 +08:00
|
|
|
osg::notify(osg::NOTICE)<<"Warning: RenderStage::runCameraSetUp(State&) Pbuffer ";
|
2005-10-06 00:21:51 +08:00
|
|
|
|
|
|
|
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());
|
|
|
|
|
2005-10-06 23:41:47 +08:00
|
|
|
if (context.valid() && context->realize())
|
2005-10-06 00:21:51 +08:00
|
|
|
{
|
2005-10-06 23:41:47 +08:00
|
|
|
osg::notify(osg::INFO)<<"RenderStage::runCameraSetUp(State&) Context has been realized "<<std::endl;
|
|
|
|
|
2005-10-06 19:26:07 +08:00
|
|
|
// successfully set up graphics context as requested,
|
|
|
|
// will assign this graphics context to the RenderStage and
|
|
|
|
// associated parameters. Setting the graphics context will
|
|
|
|
// single this while loop to exit successful.
|
|
|
|
setGraphicsContext(context.get());
|
|
|
|
|
|
|
|
// how to do we detect that an attempt to set up RTT has failed??
|
|
|
|
|
|
|
|
setDrawBuffer(GL_FRONT);
|
|
|
|
setReadBuffer(GL_FRONT);
|
|
|
|
|
|
|
|
if (pBufferTexture && renderTargetImplemntation==osg::CameraNode::PIXEL_BUFFER_RTT)
|
|
|
|
{
|
|
|
|
osg::notify(osg::INFO)<<"RenderStage::runCameraSetUp(State&) Assign graphis context to Texture"<<std::endl;
|
|
|
|
pBufferTexture->setReadPBuffer(context.get());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
osg::notify(osg::INFO)<<"RenderStage::runCameraSetUp(State&) Assigning texture to RenderStage so that it does the copy"<<std::endl;
|
|
|
|
setTexture(pBufferTexture, level, face);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2005-10-06 00:21:51 +08:00
|
|
|
{
|
2005-10-06 19:26:07 +08:00
|
|
|
osg::notify(osg::INFO)<<"Failed to aquire Graphics Context"<<std::endl;
|
|
|
|
|
|
|
|
if (renderTargetImplemntation==osg::CameraNode::PIXEL_BUFFER_RTT)
|
|
|
|
{
|
|
|
|
// fallback to using standard PBuffer, this will allow this while loop to continue
|
2005-11-01 18:42:54 +08:00
|
|
|
if (renderTargetImplemntation<renderTargetFallback)
|
|
|
|
renderTargetImplemntation = renderTargetFallback;
|
|
|
|
else
|
|
|
|
renderTargetImplemntation = osg::CameraNode::PIXEL_BUFFER;
|
2005-10-06 19:26:07 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-11-01 18:42:54 +08:00
|
|
|
renderTargetImplemntation = osg::CameraNode::FRAME_BUFFER;
|
2005-10-06 19:26:07 +08:00
|
|
|
}
|
2005-10-06 00:21:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-10-06 19:26:07 +08:00
|
|
|
// finally if all else has failed, then the frame buffer fallback will come in to play.
|
|
|
|
if (renderTargetImplemntation==osg::CameraNode::FRAME_BUFFER)
|
|
|
|
{
|
|
|
|
osg::notify(osg::INFO)<<"Setting up osg::CameraNode::FRAME_BUFFER"<<std::endl;
|
|
|
|
|
|
|
|
for(osg::CameraNode::BufferAttachmentMap::iterator itr = bufferAttachements.begin();
|
|
|
|
itr != bufferAttachements.end();
|
|
|
|
++itr)
|
|
|
|
{
|
|
|
|
// assign the texture...
|
|
|
|
if (itr->second._texture.valid()) setTexture(itr->second._texture.get(), itr->second._level, itr->second._face);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-10-06 00:21:51 +08:00
|
|
|
}
|
|
|
|
|
2005-08-20 16:59:03 +08:00
|
|
|
void RenderStage::copyTexture(osg::State& state)
|
2002-10-17 21:48:46 +08:00
|
|
|
{
|
2005-08-20 16:59:03 +08:00
|
|
|
if (_readBuffer != GL_NONE)
|
|
|
|
{
|
|
|
|
glReadBuffer(_readBuffer);
|
|
|
|
}
|
2003-01-24 17:11:05 +08:00
|
|
|
|
2005-08-20 16:59:03 +08:00
|
|
|
// need to implement texture cube map etc...
|
|
|
|
osg::Texture1D* texture1D = 0;
|
|
|
|
osg::Texture2D* texture2D = 0;
|
|
|
|
osg::Texture3D* texture3D = 0;
|
|
|
|
osg::TextureRectangle* textureRec = 0;
|
|
|
|
osg::TextureCubeMap* textureCubeMap = 0;
|
2005-08-17 18:12:49 +08:00
|
|
|
|
2005-08-20 16:59:03 +08:00
|
|
|
if ((texture2D = dynamic_cast<osg::Texture2D*>(_texture.get())) != 0)
|
2005-08-17 18:12:49 +08:00
|
|
|
{
|
2005-08-20 16:59:03 +08:00
|
|
|
texture2D->copyTexImage2D(state,_viewport->x(),_viewport->y(),_viewport->width(),_viewport->height());
|
2005-08-17 18:12:49 +08:00
|
|
|
}
|
2005-08-20 16:59:03 +08:00
|
|
|
else if ((textureRec = dynamic_cast<osg::TextureRectangle*>(_texture.get())) != 0)
|
|
|
|
{
|
|
|
|
textureRec->copyTexImage2D(state,_viewport->x(),_viewport->y(),_viewport->width(),_viewport->height());
|
|
|
|
}
|
|
|
|
else if ((texture1D = dynamic_cast<osg::Texture1D*>(_texture.get())) != 0)
|
|
|
|
{
|
|
|
|
// need to implement
|
|
|
|
texture1D->copyTexImage1D(state,_viewport->x(),_viewport->y(),_viewport->width());
|
|
|
|
}
|
|
|
|
else if ((texture3D = dynamic_cast<osg::Texture3D*>(_texture.get())) != 0)
|
|
|
|
{
|
|
|
|
// need to implement
|
|
|
|
texture3D->copyTexSubImage3D(state, 0, 0, _face, _viewport->x(), _viewport->y(), _viewport->width(), _viewport->height());
|
|
|
|
}
|
|
|
|
else if ((textureCubeMap = dynamic_cast<osg::TextureCubeMap*>(_texture.get())) != 0)
|
|
|
|
{
|
|
|
|
// need to implement
|
|
|
|
textureCubeMap->copyTexSubImageCubeMap(state, _face, 0, 0, _viewport->x(),_viewport->y(),_viewport->width(),_viewport->height());
|
|
|
|
}
|
|
|
|
}
|
2005-08-17 18:12:49 +08:00
|
|
|
|
2005-08-20 16:59:03 +08:00
|
|
|
void RenderStage::drawInner(osg::State& state,RenderLeaf*& previous, bool& doCopyTexture)
|
|
|
|
{
|
2005-08-17 18:12:49 +08:00
|
|
|
if (_drawBuffer != GL_NONE)
|
|
|
|
{
|
|
|
|
glDrawBuffer(_drawBuffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_readBuffer != GL_NONE)
|
|
|
|
{
|
|
|
|
glReadBuffer(_readBuffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
osg::FBOExtensions* fbo_ext = _fbo.valid() ? osg::FBOExtensions::instance(state.getContextID()) : 0;
|
|
|
|
bool fbo_supported = fbo_ext && fbo_ext->isSupported();
|
|
|
|
|
|
|
|
if (fbo_supported)
|
|
|
|
{
|
2005-08-20 16:59:03 +08:00
|
|
|
_fbo->apply(state);
|
2005-08-17 18:12:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// do the drawing itself.
|
2002-10-17 21:48:46 +08:00
|
|
|
RenderBin::draw(state,previous);
|
2005-06-15 04:51:35 +08:00
|
|
|
|
2005-08-17 18:12:49 +08:00
|
|
|
|
|
|
|
// now copy the rendered image to attached texture.
|
2005-08-20 16:59:03 +08:00
|
|
|
if (doCopyTexture)
|
2005-08-17 18:12:49 +08:00
|
|
|
{
|
2005-08-20 16:59:03 +08:00
|
|
|
copyTexture(state);
|
2005-08-17 18:12:49 +08:00
|
|
|
}
|
|
|
|
|
2005-11-01 23:23:03 +08:00
|
|
|
state.checkGLErrors("before readPixel;");
|
|
|
|
|
2005-08-17 18:12:49 +08:00
|
|
|
if (_image.valid())
|
|
|
|
{
|
|
|
|
|
|
|
|
if (_readBuffer != GL_NONE)
|
|
|
|
{
|
|
|
|
glReadBuffer(_readBuffer);
|
|
|
|
}
|
|
|
|
|
2005-11-01 23:23:03 +08:00
|
|
|
GLenum pixelFormat = _image->getPixelFormat();
|
|
|
|
if (pixelFormat==0) pixelFormat = _imageReadPixelFormat;
|
|
|
|
if (pixelFormat==0) pixelFormat = GL_RGB;
|
|
|
|
|
|
|
|
GLenum dataType = _image->getDataType();
|
|
|
|
if (dataType==0) dataType = _imageReadPixelDataType;
|
|
|
|
if (dataType==0) dataType = GL_UNSIGNED_BYTE;
|
|
|
|
|
|
|
|
_image->readPixels(_viewport->x(), _viewport->y(),
|
|
|
|
_viewport->width(), _viewport->height(),
|
|
|
|
pixelFormat, dataType);
|
2005-08-17 18:12:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (_camera && _camera->getPostDrawCallback())
|
|
|
|
{
|
|
|
|
// if we have a camera with a post draw callback invoke it.
|
|
|
|
(*(_camera->getPostDrawCallback()))(*_camera);
|
|
|
|
}
|
|
|
|
|
2005-11-01 23:23:03 +08:00
|
|
|
state.checkGLErrors("before glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);");
|
|
|
|
|
2005-08-17 18:12:49 +08:00
|
|
|
if (fbo_supported)
|
|
|
|
{
|
|
|
|
// switch of the frame buffer object
|
|
|
|
fbo_ext->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
2005-08-20 16:59:03 +08:00
|
|
|
|
|
|
|
doCopyTexture = true;
|
2005-08-17 18:12:49 +08:00
|
|
|
}
|
|
|
|
|
2005-11-01 23:23:03 +08:00
|
|
|
state.checkGLErrors("after glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);");
|
|
|
|
|
|
|
|
|
2005-08-17 18:12:49 +08:00
|
|
|
if (fbo_supported && _camera)
|
|
|
|
{
|
|
|
|
// now generate mipmaps if they are required.
|
|
|
|
const osg::CameraNode::BufferAttachmentMap& bufferAttachements = _camera->getBufferAttachmentMap();
|
|
|
|
for(osg::CameraNode::BufferAttachmentMap::const_iterator itr = bufferAttachements.begin();
|
|
|
|
itr != bufferAttachements.end();
|
|
|
|
++itr)
|
|
|
|
{
|
|
|
|
if (itr->second._texture.valid() && itr->second._mipMapGeneration)
|
|
|
|
{
|
2005-08-20 16:59:03 +08:00
|
|
|
itr->second._texture->apply(state);
|
2005-08-17 18:12:49 +08:00
|
|
|
// fbo_ext->glGenerateMipmapEXT(itr->second._texture->getTextureTarget());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-08-20 16:59:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
struct DrawInnerOperation : public osg::GraphicsThread::Operation
|
|
|
|
{
|
2005-08-31 03:20:19 +08:00
|
|
|
DrawInnerOperation(RenderStage* stage) :
|
|
|
|
osg::GraphicsThread::Operation("DrawInnerStage",false),
|
|
|
|
_stage(stage) {}
|
2005-08-20 16:59:03 +08:00
|
|
|
|
|
|
|
virtual void operator() (osg::GraphicsContext* context)
|
|
|
|
{
|
|
|
|
// osg::notify(osg::NOTICE)<<"DrawInnerOperation operator"<<std::endl;
|
|
|
|
if (_stage && context)
|
|
|
|
{
|
|
|
|
RenderLeaf* previous = 0;
|
|
|
|
bool doCopyTexture = false;
|
|
|
|
_stage->drawInner(*(context->getState()), previous, doCopyTexture);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RenderStage* _stage;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
void RenderStage::draw(osg::State& state,RenderLeaf*& previous)
|
|
|
|
{
|
|
|
|
if (_stageDrawnThisFrame) return;
|
|
|
|
|
|
|
|
_stageDrawnThisFrame = true;
|
|
|
|
|
|
|
|
// note, SceneView does call to drawPreRenderStages explicitly
|
|
|
|
// so there is no need to call it here.
|
|
|
|
drawPreRenderStages(state,previous);
|
|
|
|
|
2005-10-06 00:21:51 +08:00
|
|
|
if (_cameraRequiresSetUp)
|
|
|
|
{
|
|
|
|
runCameraSetUp(state);
|
|
|
|
}
|
|
|
|
|
2005-08-20 16:59:03 +08:00
|
|
|
|
|
|
|
osg::State* useState = &state;
|
|
|
|
osg::GraphicsContext* callingContext = state.getGraphicsContext();
|
|
|
|
osg::GraphicsContext* useContext = callingContext;
|
|
|
|
osg::GraphicsThread* useThread = 0;
|
|
|
|
|
|
|
|
if (_graphicsContext.valid() && _graphicsContext != callingContext)
|
|
|
|
{
|
|
|
|
// show we release the context so that others can use it?? will do so right
|
|
|
|
// now as an experiment.
|
|
|
|
callingContext->releaseContext();
|
|
|
|
|
|
|
|
useState = _graphicsContext->getState();
|
|
|
|
useContext = _graphicsContext.get();
|
|
|
|
|
|
|
|
useThread = useContext->getGraphicsThread();
|
|
|
|
|
|
|
|
if (!useThread) useContext->makeCurrent();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool doCopyTexture = _texture.valid() ?
|
|
|
|
(callingContext != useContext) :
|
|
|
|
false;
|
|
|
|
|
|
|
|
if (useThread)
|
|
|
|
{
|
|
|
|
useThread->add(new DrawInnerOperation( this ), true);
|
|
|
|
|
|
|
|
doCopyTexture = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
drawInner( *useState, previous, doCopyTexture);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// now copy the rendered image to attached texture.
|
|
|
|
if (_texture.valid() && !doCopyTexture)
|
|
|
|
{
|
|
|
|
if (callingContext && useContext!= callingContext)
|
|
|
|
{
|
|
|
|
// make the calling context use the pbuffer context for reading.
|
|
|
|
callingContext->makeContextCurrent(useContext);
|
|
|
|
}
|
|
|
|
|
|
|
|
copyTexture(state);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_camera && _camera->getPostDrawCallback())
|
|
|
|
{
|
|
|
|
// if we have a camera with a post draw callback invoke it.
|
|
|
|
(*(_camera->getPostDrawCallback()))(*_camera);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_graphicsContext.valid() && _graphicsContext != callingContext)
|
|
|
|
{
|
|
|
|
if (!useThread) useContext->releaseContext();
|
|
|
|
}
|
2005-08-17 18:12:49 +08:00
|
|
|
|
|
|
|
if (callingContext && useContext != callingContext)
|
|
|
|
{
|
|
|
|
// restore the graphics context.
|
|
|
|
callingContext->makeCurrent();
|
|
|
|
}
|
|
|
|
|
2005-06-15 04:51:35 +08:00
|
|
|
// place the post draw here temprorarily while we figure out how
|
|
|
|
// best to do SceneView.
|
|
|
|
drawPostRenderStages(state,previous);
|
2002-10-17 21:48:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void RenderStage::drawImplementation(osg::State& state,RenderLeaf*& previous)
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
|
|
|
|
2001-09-22 10:42:08 +08:00
|
|
|
if (!_viewport)
|
|
|
|
{
|
2002-04-19 23:02:34 +08:00
|
|
|
notify(FATAL) << "Error: cannot draw stage due to undefined viewport."<< std::endl;
|
2001-09-22 10:42:08 +08:00
|
|
|
return;
|
|
|
|
}
|
2005-08-17 18:12:49 +08:00
|
|
|
|
2001-09-20 05:19:47 +08:00
|
|
|
// set up the back buffer.
|
2002-04-22 17:37:17 +08:00
|
|
|
state.applyAttribute(_viewport.get());
|
2002-04-16 23:31:46 +08:00
|
|
|
|
2001-09-20 05:19:47 +08:00
|
|
|
#define USE_SISSOR_TEST
|
|
|
|
#ifdef USE_SISSOR_TEST
|
2001-09-22 10:42:08 +08:00
|
|
|
glScissor( _viewport->x(), _viewport->y(), _viewport->width(), _viewport->height() );
|
2003-01-24 17:11:05 +08:00
|
|
|
//cout << " clearing "<<this<< " "<<_viewport->x()<<","<< _viewport->y()<<","<< _viewport->width()<<","<< _viewport->height()<<std::endl;
|
|
|
|
|
2001-09-20 05:19:47 +08:00
|
|
|
glEnable( GL_SCISSOR_TEST );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
// glEnable( GL_DEPTH_TEST );
|
|
|
|
|
2001-12-03 06:20:46 +08:00
|
|
|
// set which color planes to operate on.
|
|
|
|
if (_colorMask.valid()) _colorMask->apply(state);
|
|
|
|
else glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
|
|
|
|
|
2001-09-20 05:19:47 +08:00
|
|
|
if (_clearMask & GL_COLOR_BUFFER_BIT)
|
|
|
|
glClearColor( _clearColor[0], _clearColor[1], _clearColor[2], _clearColor[3]);
|
|
|
|
|
|
|
|
if (_clearMask & GL_DEPTH_BUFFER_BIT)
|
|
|
|
glClearDepth( _clearDepth);
|
|
|
|
|
|
|
|
if (_clearMask & GL_STENCIL_BUFFER_BIT)
|
|
|
|
glClearStencil( _clearStencil);
|
|
|
|
|
|
|
|
if (_clearMask & GL_ACCUM_BUFFER_BIT)
|
|
|
|
glClearAccum( _clearAccum[0], _clearAccum[1], _clearAccum[2], _clearAccum[3]);
|
|
|
|
|
|
|
|
|
|
|
|
glClear( _clearMask );
|
2003-12-16 07:23:45 +08:00
|
|
|
|
2001-09-20 05:19:47 +08:00
|
|
|
#ifdef USE_SISSOR_TEST
|
|
|
|
glDisable( GL_SCISSOR_TEST );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
glMatrixMode( GL_MODELVIEW );
|
|
|
|
glLoadIdentity();
|
|
|
|
|
2005-07-20 00:30:55 +08:00
|
|
|
// apply the positional state.
|
2005-09-02 18:35:38 +08:00
|
|
|
if (_inheritedPositionalStateContainer.valid())
|
2005-07-20 00:30:55 +08:00
|
|
|
{
|
2005-09-02 18:35:38 +08:00
|
|
|
_inheritedPositionalStateContainer->draw(state, previous, &_inheritedPositionalStateContainerMatrix);
|
2005-07-20 00:30:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// apply the positional state.
|
|
|
|
if (_renderStageLighting.valid())
|
|
|
|
{
|
|
|
|
_renderStageLighting->draw(state, previous, 0);
|
|
|
|
}
|
2001-09-20 05:19:47 +08:00
|
|
|
|
|
|
|
// draw the children and local.
|
2002-10-17 21:48:46 +08:00
|
|
|
RenderBin::drawImplementation(state,previous);
|
2001-09-20 05:19:47 +08:00
|
|
|
|
|
|
|
// now reset the state so its back in its default state.
|
|
|
|
if (previous)
|
|
|
|
{
|
2005-10-13 20:51:00 +08:00
|
|
|
StateGraph::moveToRootStateGraph(state,previous->_parent);
|
2001-09-20 05:19:47 +08:00
|
|
|
state.apply();
|
|
|
|
previous = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2005-06-15 04:51:35 +08:00
|
|
|
|
|
|
|
void RenderStage::drawPostRenderStages(osg::State& state,RenderLeaf*& previous)
|
|
|
|
{
|
|
|
|
if (_postRenderList.empty()) return;
|
|
|
|
|
|
|
|
//cout << "Drawing prerendering stages "<<this<< " "<<_viewport->x()<<","<< _viewport->y()<<","<< _viewport->width()<<","<< _viewport->height()<<std::endl;
|
|
|
|
for(RenderStageList::iterator itr=_postRenderList.begin();
|
|
|
|
itr!=_postRenderList.end();
|
|
|
|
++itr)
|
|
|
|
{
|
|
|
|
(*itr)->draw(state,previous);
|
|
|
|
}
|
|
|
|
//cout << "Done Drawing prerendering stages "<<this<< " "<<_viewport->x()<<","<< _viewport->y()<<","<< _viewport->width()<<","<< _viewport->height()<<std::endl;
|
|
|
|
}
|
|
|
|
|
2001-09-20 05:19:47 +08:00
|
|
|
// Statistics features
|
2001-11-05 03:29:20 +08:00
|
|
|
bool RenderStage::getStats(Statistics* primStats)
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
2002-05-02 08:14:40 +08:00
|
|
|
if (_renderStageLighting.valid())
|
|
|
|
{
|
|
|
|
// need to re-implement by checking for lights in the scene
|
|
|
|
// by downcasting the positioned attribute list. RO. May 2002.
|
|
|
|
//primStats->addLight(_renderStageLighting->_lightList.size());
|
|
|
|
}
|
2001-11-05 03:29:20 +08:00
|
|
|
return RenderBin::getStats(primStats);
|
2001-09-20 05:19:47 +08:00
|
|
|
}
|