2012-03-22 01:36:20 +08:00
|
|
|
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
|
2003-01-22 00:45:36 +08:00
|
|
|
*
|
2012-03-22 01:36:20 +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
|
2003-01-22 00:45:36 +08:00
|
|
|
* (at your option) any later version. The full license is in LICENSE file
|
|
|
|
* included with this distribution, and on the openscenegraph.org website.
|
2012-03-22 01:36:20 +08:00
|
|
|
*
|
2003-01-22 00:45:36 +08:00
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2012-03-22 01:36:20 +08:00
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2003-01-22 00:45:36 +08:00
|
|
|
* 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>
|
2010-04-23 01:02:22 +08:00
|
|
|
#include <osg/Texture2DMultisample>
|
2005-08-17 18:12:49 +08:00
|
|
|
#include <osg/Texture3D>
|
|
|
|
#include <osg/TextureRectangle>
|
|
|
|
#include <osg/TextureCubeMap>
|
2005-11-01 18:42:54 +08:00
|
|
|
#include <osg/GLExtensions>
|
2006-05-23 03:30:07 +08:00
|
|
|
#include <osg/GLU>
|
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>
|
|
|
|
|
|
|
|
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():
|
2008-06-18 22:09:11 +08:00
|
|
|
RenderBin(getDefaultRenderBinSortMode()),
|
|
|
|
_disableFboAfterRender(true)
|
2005-05-24 23:34:23 +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;
|
2009-08-21 17:34:48 +08:00
|
|
|
_drawBufferApplyMask = false;
|
2005-08-17 18:12:49 +08:00
|
|
|
_readBuffer = GL_NONE;
|
2009-08-21 17:34:48 +08:00
|
|
|
_readBufferApplyMask = false;
|
|
|
|
|
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
|
|
|
|
2005-12-09 17:38:46 +08:00
|
|
|
_cameraRequiresSetUp = false;
|
2015-03-31 18:36:38 +08:00
|
|
|
_cameraAttachmentMapModifiedCount = 0;
|
2005-08-17 18:12:49 +08:00
|
|
|
_camera = 0;
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2005-08-17 18:12:49 +08:00
|
|
|
_level = 0;
|
|
|
|
_face = 0;
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2005-08-17 18:12:49 +08:00
|
|
|
_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):
|
2008-06-18 22:09:11 +08:00
|
|
|
RenderBin(mode),
|
|
|
|
_disableFboAfterRender(true)
|
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;
|
2009-08-21 17:34:48 +08:00
|
|
|
_drawBufferApplyMask = false;
|
2005-08-17 18:12:49 +08:00
|
|
|
_readBuffer = GL_NONE;
|
2009-08-21 17:34:48 +08:00
|
|
|
_readBufferApplyMask = false;
|
|
|
|
|
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
|
|
|
|
2005-12-09 17:38:46 +08:00
|
|
|
_cameraRequiresSetUp = false;
|
2015-03-31 18:36:38 +08:00
|
|
|
_cameraAttachmentMapModifiedCount = 0;
|
2005-08-17 18:12:49 +08:00
|
|
|
_camera = 0;
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2005-08-17 18:12:49 +08:00
|
|
|
_level = 0;
|
|
|
|
_face = 0;
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2005-08-17 18:12:49 +08:00
|
|
|
_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),
|
2009-08-21 17:34:48 +08:00
|
|
|
_drawBufferApplyMask(rhs._drawBufferApplyMask),
|
2005-08-17 18:12:49 +08:00
|
|
|
_readBuffer(rhs._readBuffer),
|
2009-08-21 17:34:48 +08:00
|
|
|
_readBufferApplyMask(rhs._readBufferApplyMask),
|
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-12-09 17:38:46 +08:00
|
|
|
_cameraRequiresSetUp(rhs._cameraRequiresSetUp),
|
2015-03-31 18:36:38 +08:00
|
|
|
_cameraAttachmentMapModifiedCount(rhs._cameraAttachmentMapModifiedCount),
|
2005-08-17 18:12:49 +08:00
|
|
|
_camera(rhs._camera),
|
|
|
|
_level(rhs._level),
|
|
|
|
_face(rhs._face),
|
|
|
|
_imageReadPixelFormat(rhs._imageReadPixelFormat),
|
|
|
|
_imageReadPixelDataType(rhs._imageReadPixelDataType),
|
2008-10-27 21:09:43 +08:00
|
|
|
_disableFboAfterRender(rhs._disableFboAfterRender),
|
|
|
|
_renderStageLighting(rhs._renderStageLighting)
|
2002-09-17 23:47:23 +08:00
|
|
|
{
|
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()
|
|
|
|
{
|
|
|
|
_stageDrawnThisFrame = false;
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2001-09-20 05:19:47 +08:00
|
|
|
if (_renderStageLighting.valid()) _renderStageLighting->reset();
|
|
|
|
|
2005-11-08 19:46:52 +08:00
|
|
|
for(RenderStageList::iterator pre_itr = _preRenderList.begin();
|
|
|
|
pre_itr != _preRenderList.end();
|
|
|
|
++pre_itr)
|
|
|
|
{
|
2006-09-04 21:15:08 +08:00
|
|
|
pre_itr->second->reset();
|
2005-11-08 19:46:52 +08:00
|
|
|
}
|
|
|
|
|
2001-09-20 05:19:47 +08:00
|
|
|
RenderBin::reset();
|
2005-11-08 19:46:52 +08:00
|
|
|
|
|
|
|
for(RenderStageList::iterator post_itr = _postRenderList.begin();
|
|
|
|
post_itr != _postRenderList.end();
|
|
|
|
++post_itr)
|
|
|
|
{
|
2006-09-04 21:15:08 +08:00
|
|
|
post_itr->second->reset();
|
2005-11-08 19:46:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
_preRenderList.clear();
|
|
|
|
_postRenderList.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderStage::sort()
|
|
|
|
{
|
|
|
|
for(RenderStageList::iterator pre_itr = _preRenderList.begin();
|
|
|
|
pre_itr != _preRenderList.end();
|
|
|
|
++pre_itr)
|
|
|
|
{
|
2006-09-04 21:15:08 +08:00
|
|
|
pre_itr->second->sort();
|
2005-11-08 19:46:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
RenderBin::sort();
|
|
|
|
|
|
|
|
for(RenderStageList::iterator post_itr = _postRenderList.begin();
|
|
|
|
post_itr != _postRenderList.end();
|
|
|
|
++post_itr)
|
|
|
|
{
|
2006-09-04 21:15:08 +08:00
|
|
|
post_itr->second->sort();
|
2005-11-08 19:46:52 +08:00
|
|
|
}
|
2001-09-20 05:19:47 +08:00
|
|
|
}
|
|
|
|
|
2006-09-04 21:15:08 +08:00
|
|
|
void RenderStage::addPreRenderStage(RenderStage* rs, int order)
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
2006-09-04 21:15:08 +08:00
|
|
|
if (rs)
|
|
|
|
{
|
|
|
|
RenderStageList::iterator itr;
|
|
|
|
for(itr = _preRenderList.begin(); itr != _preRenderList.end(); ++itr) {
|
|
|
|
if(order < itr->first) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(itr == _preRenderList.end()) {
|
|
|
|
_preRenderList.push_back(RenderStageOrderPair(order,rs));
|
|
|
|
} else {
|
|
|
|
_preRenderList.insert(itr,RenderStageOrderPair(order,rs));
|
|
|
|
}
|
|
|
|
}
|
2005-06-15 04:51:35 +08:00
|
|
|
}
|
|
|
|
|
2006-09-04 21:15:08 +08:00
|
|
|
void RenderStage::addPostRenderStage(RenderStage* rs, int order)
|
2005-06-15 04:51:35 +08:00
|
|
|
{
|
2006-09-04 21:15:08 +08:00
|
|
|
if (rs)
|
|
|
|
{
|
|
|
|
RenderStageList::iterator itr;
|
|
|
|
for(itr = _postRenderList.begin(); itr != _postRenderList.end(); ++itr) {
|
|
|
|
if(order < itr->first) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(itr == _postRenderList.end()) {
|
|
|
|
_postRenderList.push_back(RenderStageOrderPair(order,rs));
|
|
|
|
} else {
|
|
|
|
_postRenderList.insert(itr,RenderStageOrderPair(order,rs));
|
|
|
|
}
|
|
|
|
}
|
2001-09-20 05:19:47 +08:00
|
|
|
}
|
2002-04-22 17:37:17 +08:00
|
|
|
|
2006-09-19 04:54:48 +08:00
|
|
|
void RenderStage::drawPreRenderStages(osg::RenderInfo& renderInfo,RenderLeaf*& previous)
|
2002-09-19 17:52:50 +08:00
|
|
|
{
|
2005-06-15 04:51:35 +08:00
|
|
|
if (_preRenderList.empty()) return;
|
2012-03-22 01:36:20 +08:00
|
|
|
|
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)
|
|
|
|
{
|
2006-09-19 04:54:48 +08:00
|
|
|
itr->second->draw(renderInfo,previous);
|
2002-09-19 17:52:50 +08:00
|
|
|
}
|
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
|
|
|
|
2006-09-19 04:54:48 +08:00
|
|
|
void RenderStage::runCameraSetUp(osg::RenderInfo& renderInfo)
|
2005-10-06 00:21:51 +08:00
|
|
|
{
|
|
|
|
_cameraRequiresSetUp = false;
|
|
|
|
|
|
|
|
if (!_camera) return;
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2015-03-31 18:36:38 +08:00
|
|
|
OSG_INFO<<"RenderStage::runCameraSetUp(osg::RenderInfo& renderInfo) "<<this<<std::endl;
|
|
|
|
|
|
|
|
_cameraAttachmentMapModifiedCount = _camera->getAttachmentMapModifiedCount();
|
|
|
|
|
2008-04-02 19:28:10 +08:00
|
|
|
osg::State& state = *renderInfo.getState();
|
2006-09-19 04:54:48 +08:00
|
|
|
|
2008-04-02 19:28:10 +08:00
|
|
|
osg::Camera::RenderTargetImplementation renderTargetImplementation = _camera->getRenderTargetImplementation();
|
2006-11-27 22:52:07 +08:00
|
|
|
osg::Camera::RenderTargetImplementation renderTargetFallback = _camera->getRenderTargetFallback();
|
2005-10-06 00:21:51 +08:00
|
|
|
|
2007-12-11 01:30:18 +08:00
|
|
|
osg::Camera::BufferAttachmentMap& bufferAttachments = _camera->getBufferAttachmentMap();
|
2005-10-06 19:26:07 +08:00
|
|
|
|
2011-03-09 19:22:20 +08:00
|
|
|
_bufferAttachmentMap.clear();
|
2009-08-21 17:34:48 +08:00
|
|
|
|
2006-08-03 23:57:39 +08:00
|
|
|
// compute the required dimensions
|
2007-01-05 00:48:23 +08:00
|
|
|
int width = static_cast<int>(_viewport->x() + _viewport->width());
|
|
|
|
int height = static_cast<int>(_viewport->y() + _viewport->height());
|
2006-08-03 23:57:39 +08:00
|
|
|
int depth = 1;
|
2006-11-27 22:52:07 +08:00
|
|
|
osg::Camera::BufferAttachmentMap::iterator itr;
|
2007-12-11 01:30:18 +08:00
|
|
|
for(itr = bufferAttachments.begin();
|
|
|
|
itr != bufferAttachments.end();
|
2006-08-03 23:57:39 +08:00
|
|
|
++itr)
|
|
|
|
{
|
|
|
|
width = osg::maximum(width,itr->second.width());
|
|
|
|
height = osg::maximum(height,itr->second.height());
|
|
|
|
depth = osg::maximum(depth,itr->second.depth());
|
|
|
|
}
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2010-05-28 23:51:00 +08:00
|
|
|
// OSG_NOTICE<<"RenderStage::runCameraSetUp viewport "<<_viewport->x()<<" "<<_viewport->y()<<" "<<_viewport->width()<<" "<<_viewport->height()<<std::endl;
|
|
|
|
// OSG_NOTICE<<"RenderStage::runCameraSetUp computed "<<width<<" "<<height<<" "<<depth<<std::endl;
|
2006-08-03 23:57:39 +08:00
|
|
|
|
2008-04-03 01:08:40 +08:00
|
|
|
// attach images that need to be copied after the stage is drawn.
|
2007-12-11 01:30:18 +08:00
|
|
|
for(itr = bufferAttachments.begin();
|
|
|
|
itr != bufferAttachments.end();
|
2005-10-06 00:21:51 +08:00
|
|
|
++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;
|
|
|
|
}
|
|
|
|
|
2006-11-27 19:25:40 +08:00
|
|
|
_bufferAttachmentMap[itr->first]._imageReadPixelFormat = pixelFormat;
|
|
|
|
_bufferAttachmentMap[itr->first]._imageReadPixelDataType = dataType;
|
|
|
|
_bufferAttachmentMap[itr->first]._image = image;
|
2005-11-04 20:08:16 +08:00
|
|
|
}
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2005-11-04 20:08:16 +08:00
|
|
|
if (itr->second._texture.valid())
|
|
|
|
{
|
|
|
|
osg::Texture* texture = itr->second._texture.get();
|
|
|
|
osg::Texture1D* texture1D = 0;
|
|
|
|
osg::Texture2D* texture2D = 0;
|
2010-04-23 01:02:22 +08:00
|
|
|
osg::Texture2DMultisample* texture2DMS = 0;
|
2005-11-04 20:08:16 +08:00
|
|
|
osg::Texture3D* texture3D = 0;
|
|
|
|
osg::TextureCubeMap* textureCubeMap = 0;
|
|
|
|
osg::TextureRectangle* textureRectangle = 0;
|
|
|
|
if (0 != (texture1D=dynamic_cast<osg::Texture1D*>(texture)))
|
|
|
|
{
|
|
|
|
if (texture1D->getTextureWidth()==0)
|
|
|
|
{
|
2006-08-03 23:57:39 +08:00
|
|
|
texture1D->setTextureWidth(width);
|
2005-11-04 20:08:16 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (0 != (texture2D = dynamic_cast<osg::Texture2D*>(texture)))
|
|
|
|
{
|
|
|
|
if (texture2D->getTextureWidth()==0 || texture2D->getTextureHeight()==0)
|
|
|
|
{
|
2006-08-03 23:57:39 +08:00
|
|
|
texture2D->setTextureSize(width,height);
|
2005-11-04 20:08:16 +08:00
|
|
|
}
|
|
|
|
}
|
2010-04-23 01:02:22 +08:00
|
|
|
else if (0 != (texture2DMS = dynamic_cast<osg::Texture2DMultisample*>(texture)))
|
|
|
|
{
|
|
|
|
if (texture2DMS->getTextureWidth()==0 || texture2DMS->getTextureHeight()==0)
|
|
|
|
{
|
|
|
|
texture2DMS->setTextureSize(width,height);
|
|
|
|
}
|
|
|
|
}
|
2005-11-04 20:08:16 +08:00
|
|
|
else if (0 != (texture3D = dynamic_cast<osg::Texture3D*>(texture)))
|
|
|
|
{
|
|
|
|
if (texture3D->getTextureWidth()==0 || texture3D->getTextureHeight()==0 || texture3D->getTextureDepth()==0 )
|
|
|
|
{
|
|
|
|
// note we dont' have the depth here, so we'll heave to assume that height and depth are the same..
|
2006-08-03 23:57:39 +08:00
|
|
|
texture3D->setTextureSize(width,height,height);
|
2005-11-04 20:08:16 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (0 != (textureCubeMap = dynamic_cast<osg::TextureCubeMap*>(texture)))
|
|
|
|
{
|
|
|
|
if (textureCubeMap->getTextureWidth()==0 || textureCubeMap->getTextureHeight()==0)
|
|
|
|
{
|
2006-08-03 23:57:39 +08:00
|
|
|
textureCubeMap->setTextureSize(width,height);
|
2005-11-04 20:08:16 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (0 != (textureRectangle = dynamic_cast<osg::TextureRectangle*>(texture)))
|
|
|
|
{
|
|
|
|
if (textureRectangle->getTextureWidth()==0 || textureRectangle->getTextureHeight()==0)
|
|
|
|
{
|
2006-08-03 23:57:39 +08:00
|
|
|
textureRectangle->setTextureSize(width,height);
|
2005-11-04 20:08:16 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-01 23:23:03 +08:00
|
|
|
}
|
2005-10-06 00:21:51 +08:00
|
|
|
}
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2008-04-02 19:28:10 +08:00
|
|
|
if (renderTargetImplementation==osg::Camera::FRAME_BUFFER_OBJECT)
|
2005-10-06 00:21:51 +08:00
|
|
|
{
|
2014-12-10 18:38:12 +08:00
|
|
|
osg::GLExtensions* ext = state.get<osg::GLExtensions>();
|
2014-12-10 02:30:28 +08:00
|
|
|
bool fbo_supported = ext->isFrameBufferObjectSupported;
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2010-04-19 19:43:06 +08:00
|
|
|
if (fbo_supported)
|
2005-10-06 00:21:51 +08:00
|
|
|
{
|
2010-05-28 23:51:00 +08:00
|
|
|
OSG_INFO<<"Setting up osg::Camera::FRAME_BUFFER_OBJECT"<<std::endl;
|
2005-11-01 18:42:54 +08:00
|
|
|
|
2005-11-24 00:32:55 +08:00
|
|
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(*(_camera->getDataChangeMutex()));
|
2005-11-23 21:44:27 +08:00
|
|
|
|
2005-11-24 23:18:12 +08:00
|
|
|
osg::ref_ptr<osg::FrameBufferObject> fbo = new osg::FrameBufferObject;
|
2008-06-18 22:09:11 +08:00
|
|
|
osg::ref_ptr<osg::FrameBufferObject> fbo_multisample;
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2005-10-06 00:21:51 +08:00
|
|
|
bool colorAttached = false;
|
|
|
|
bool depthAttached = false;
|
|
|
|
bool stencilAttached = false;
|
2008-06-18 22:09:11 +08:00
|
|
|
unsigned samples = 0;
|
|
|
|
unsigned colorSamples = 0;
|
|
|
|
|
2009-11-20 00:39:03 +08:00
|
|
|
// This is not a cut and paste error. Set BOTH local masks
|
|
|
|
// to the value of the Camera's use render buffers mask.
|
|
|
|
// We'll change this if and only if we decide we're doing MSFBO.
|
|
|
|
unsigned int renderBuffersMask = _camera->getImplicitBufferAttachmentRenderMask(true);
|
|
|
|
unsigned int resolveBuffersMask = _camera->getImplicitBufferAttachmentRenderMask(true);
|
|
|
|
|
2014-12-10 02:30:28 +08:00
|
|
|
if (ext->isRenderbufferMultisampleSupported())
|
2008-06-18 22:09:11 +08:00
|
|
|
{
|
|
|
|
for(osg::Camera::BufferAttachmentMap::iterator itr = bufferAttachments.begin();
|
|
|
|
itr != bufferAttachments.end();
|
|
|
|
++itr)
|
|
|
|
{
|
|
|
|
osg::Camera::Attachment& attachment = itr->second;
|
|
|
|
samples = maximum(samples, attachment._multisampleSamples);
|
2008-08-16 01:35:04 +08:00
|
|
|
colorSamples = maximum(colorSamples, attachment._multisampleColorSamples);
|
2008-06-18 22:09:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (colorSamples > samples)
|
|
|
|
{
|
2010-02-10 20:44:59 +08:00
|
|
|
OSG_NOTIFY(WARN) << "Multisample color samples must be less than or "
|
2008-06-18 22:09:11 +08:00
|
|
|
"equal to samples. Setting color samples equal to samples." << std::endl;
|
|
|
|
colorSamples = samples;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (samples)
|
|
|
|
{
|
|
|
|
fbo_multisample = new osg::FrameBufferObject;
|
2009-11-20 00:39:03 +08:00
|
|
|
|
|
|
|
// Use the value of the Camera's use resolve buffers mask as the
|
|
|
|
// resolve mask.
|
|
|
|
resolveBuffersMask = _camera->getImplicitBufferAttachmentResolveMask(true);
|
2008-06-18 22:09:11 +08:00
|
|
|
}
|
|
|
|
}
|
2009-11-20 00:39:03 +08:00
|
|
|
|
2007-12-11 01:30:18 +08:00
|
|
|
for(osg::Camera::BufferAttachmentMap::iterator itr = bufferAttachments.begin();
|
|
|
|
itr != bufferAttachments.end();
|
2005-10-06 00:21:51 +08:00
|
|
|
++itr)
|
|
|
|
{
|
|
|
|
|
2006-11-27 22:52:07 +08:00
|
|
|
osg::Camera::BufferComponent buffer = itr->first;
|
|
|
|
osg::Camera::Attachment& attachment = itr->second;
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2008-05-12 19:39:02 +08:00
|
|
|
if (attachment._texture.valid() || attachment._image.valid())
|
|
|
|
fbo->setAttachment(buffer, osg::FrameBufferAttachment(attachment));
|
|
|
|
else
|
|
|
|
fbo->setAttachment(buffer, osg::FrameBufferAttachment(new osg::RenderBuffer(width, height, attachment._internalFormat)));
|
2008-06-18 22:09:11 +08:00
|
|
|
|
|
|
|
if (fbo_multisample.valid())
|
|
|
|
{
|
|
|
|
GLenum internalFormat = attachment._internalFormat;
|
|
|
|
if (!internalFormat)
|
|
|
|
{
|
|
|
|
switch (buffer)
|
|
|
|
{
|
|
|
|
case Camera::DEPTH_BUFFER:
|
|
|
|
internalFormat = GL_DEPTH_COMPONENT24;
|
|
|
|
break;
|
|
|
|
case Camera::STENCIL_BUFFER:
|
|
|
|
internalFormat = GL_STENCIL_INDEX8_EXT;
|
|
|
|
break;
|
2008-11-25 18:57:14 +08:00
|
|
|
case Camera::PACKED_DEPTH_STENCIL_BUFFER:
|
|
|
|
internalFormat = GL_DEPTH_STENCIL_EXT;
|
|
|
|
break;
|
2009-02-27 18:47:33 +08:00
|
|
|
|
|
|
|
// all other buffers are color buffers
|
2008-06-18 22:09:11 +08:00
|
|
|
default:
|
2009-02-27 18:47:33 +08:00
|
|
|
// setup the internal format based on attached texture if such exists, otherwise just default format
|
|
|
|
if (attachment._texture)
|
|
|
|
internalFormat = attachment._texture->getInternalFormat();
|
|
|
|
else
|
|
|
|
internalFormat = GL_RGBA;
|
2008-06-18 22:09:11 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fbo_multisample->setAttachment(buffer,
|
|
|
|
osg::FrameBufferAttachment(new osg::RenderBuffer(
|
|
|
|
width, height, internalFormat,
|
|
|
|
samples, colorSamples)));
|
|
|
|
}
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2008-04-18 21:25:14 +08:00
|
|
|
if (buffer==osg::Camera::DEPTH_BUFFER) depthAttached = true;
|
|
|
|
else if (buffer==osg::Camera::STENCIL_BUFFER) stencilAttached = true;
|
2008-11-25 18:57:14 +08:00
|
|
|
else if (buffer==osg::Camera::PACKED_DEPTH_STENCIL_BUFFER)
|
|
|
|
{
|
|
|
|
depthAttached = true;
|
|
|
|
stencilAttached = true;
|
|
|
|
}
|
2008-04-18 22:33:14 +08:00
|
|
|
else if (buffer>=osg::Camera::COLOR_BUFFER) colorAttached = true;
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2005-10-06 00:21:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!depthAttached)
|
2009-11-20 00:39:03 +08:00
|
|
|
{
|
2012-03-22 01:36:20 +08:00
|
|
|
// If doing MSFBO (and therefore need two FBOs, one for multisampled rendering and one for
|
|
|
|
// final resolve), then configure "fbo" as the resolve FBO, and When done
|
|
|
|
// configuring, swap it into "_resolveFbo" (see line 554). But, if not
|
2009-11-20 00:39:03 +08:00
|
|
|
// using MSFBO, then "fbo" is just the render fbo.
|
2012-03-22 01:36:20 +08:00
|
|
|
// If using MSFBO, then resolveBuffersMask
|
|
|
|
// is the value set by the app for the resolve buffers. But if not using
|
|
|
|
// MSFBO, then resolveBuffersMask is the value set by the app for render
|
2009-11-20 00:39:03 +08:00
|
|
|
// buffers. In both cases, resolveBuffersMask is used to configure "fbo".
|
|
|
|
if( resolveBuffersMask & osg::Camera::IMPLICIT_DEPTH_BUFFER_ATTACHMENT )
|
|
|
|
{
|
|
|
|
fbo->setAttachment(osg::Camera::DEPTH_BUFFER, osg::FrameBufferAttachment(new osg::RenderBuffer(width, height, GL_DEPTH_COMPONENT24)));
|
|
|
|
depthAttached = true;
|
|
|
|
}
|
|
|
|
if (fbo_multisample.valid() &&
|
|
|
|
( renderBuffersMask & osg::Camera::IMPLICIT_DEPTH_BUFFER_ATTACHMENT ) )
|
2008-06-18 22:09:11 +08:00
|
|
|
{
|
|
|
|
fbo_multisample->setAttachment(osg::Camera::DEPTH_BUFFER,
|
|
|
|
osg::FrameBufferAttachment(new osg::RenderBuffer(width,
|
|
|
|
height, GL_DEPTH_COMPONENT24, samples, colorSamples)));
|
|
|
|
}
|
2005-10-06 00:21:51 +08:00
|
|
|
}
|
2009-11-20 00:39:03 +08:00
|
|
|
if (!stencilAttached)
|
|
|
|
{
|
|
|
|
if( resolveBuffersMask & osg::Camera::IMPLICIT_STENCIL_BUFFER_ATTACHMENT )
|
|
|
|
{
|
|
|
|
fbo->setAttachment(osg::Camera::STENCIL_BUFFER, osg::FrameBufferAttachment(new osg::RenderBuffer(width, height, GL_STENCIL_INDEX8_EXT)));
|
|
|
|
stencilAttached = true;
|
|
|
|
}
|
|
|
|
if (fbo_multisample.valid() &&
|
|
|
|
( renderBuffersMask & osg::Camera::IMPLICIT_STENCIL_BUFFER_ATTACHMENT ) )
|
|
|
|
{
|
|
|
|
fbo_multisample->setAttachment(osg::Camera::STENCIL_BUFFER,
|
|
|
|
osg::FrameBufferAttachment(new osg::RenderBuffer(width,
|
|
|
|
height, GL_STENCIL_INDEX8_EXT, samples, colorSamples)));
|
|
|
|
}
|
|
|
|
}
|
2005-10-06 00:21:51 +08:00
|
|
|
|
|
|
|
if (!colorAttached)
|
2009-08-21 17:34:48 +08:00
|
|
|
{
|
2009-11-20 00:39:03 +08:00
|
|
|
if( resolveBuffersMask & osg::Camera::IMPLICIT_COLOR_BUFFER_ATTACHMENT )
|
|
|
|
{
|
|
|
|
fbo->setAttachment(osg::Camera::COLOR_BUFFER, osg::FrameBufferAttachment(new osg::RenderBuffer(width, height, GL_RGB)));
|
|
|
|
colorAttached = true;
|
|
|
|
}
|
|
|
|
if (fbo_multisample.valid() &&
|
|
|
|
( renderBuffersMask & osg::Camera::IMPLICIT_COLOR_BUFFER_ATTACHMENT ) )
|
2008-06-18 22:09:11 +08:00
|
|
|
{
|
|
|
|
fbo_multisample->setAttachment(osg::Camera::COLOR_BUFFER,
|
|
|
|
osg::FrameBufferAttachment(new osg::RenderBuffer(width,
|
|
|
|
height, GL_RGB, samples, colorSamples)));
|
|
|
|
}
|
2005-11-24 23:18:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
fbo->apply(state);
|
2009-08-21 17:34:48 +08:00
|
|
|
|
2012-03-22 01:36:20 +08:00
|
|
|
// If no color attachment make sure to set glDrawBuffer/glReadBuffer to none
|
2009-11-11 01:01:08 +08:00
|
|
|
// otherwise glCheckFramebufferStatus will fail
|
2012-03-22 01:36:20 +08:00
|
|
|
// It has to be done after call to glBindFramebuffer (fbo->apply)
|
2009-08-21 17:34:48 +08:00
|
|
|
// and before call to glCheckFramebufferStatus
|
|
|
|
if ( !colorAttached )
|
|
|
|
{
|
2009-10-29 04:31:57 +08:00
|
|
|
setDrawBuffer( GL_NONE, true );
|
|
|
|
setReadBuffer( GL_NONE, true );
|
|
|
|
#if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE)
|
|
|
|
glDrawBuffer( GL_NONE );
|
|
|
|
glReadBuffer( GL_NONE );
|
|
|
|
#endif
|
2009-08-21 17:34:48 +08:00
|
|
|
}
|
|
|
|
|
2014-12-10 02:30:28 +08:00
|
|
|
GLenum status = ext->glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
|
2009-08-21 17:34:48 +08:00
|
|
|
|
2005-11-24 23:18:12 +08:00
|
|
|
if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
|
|
|
|
{
|
2010-05-28 23:51:00 +08:00
|
|
|
OSG_NOTICE<<"RenderStage::runCameraSetUp(), FBO setup failed, FBO status= 0x"<<std::hex<<status<<std::dec<<std::endl;
|
2005-11-24 23:18:12 +08:00
|
|
|
|
|
|
|
fbo_supported = false;
|
2010-11-26 00:06:04 +08:00
|
|
|
GLuint fboId = state.getGraphicsContext() ? state.getGraphicsContext()->getDefaultFboId() : 0;
|
2014-12-10 02:30:28 +08:00
|
|
|
ext->glBindFramebuffer(GL_FRAMEBUFFER_EXT, fboId);
|
2005-11-24 23:18:12 +08:00
|
|
|
fbo = 0;
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2005-11-24 23:18:12 +08:00
|
|
|
// clean up.
|
|
|
|
double availableTime = 100.0f;
|
|
|
|
double currentTime = state.getFrameStamp()?state.getFrameStamp()->getReferenceTime():0.0;
|
|
|
|
osg::RenderBuffer::flushDeletedRenderBuffers(state.getContextID(),currentTime,availableTime);
|
|
|
|
osg::FrameBufferObject::flushDeletedFrameBufferObjects(state.getContextID(),currentTime,availableTime);
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2005-11-24 23:18:12 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-08-21 17:34:48 +08:00
|
|
|
setDrawBuffer(GL_NONE, false );
|
|
|
|
setReadBuffer(GL_NONE, false );
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2005-11-24 23:18:12 +08:00
|
|
|
_fbo = fbo;
|
2008-06-18 22:09:11 +08:00
|
|
|
|
|
|
|
if (fbo_multisample.valid())
|
|
|
|
{
|
|
|
|
fbo_multisample->apply(state);
|
|
|
|
|
2014-12-10 02:30:28 +08:00
|
|
|
GLenum status = ext->glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
|
2008-06-18 22:09:11 +08:00
|
|
|
|
|
|
|
if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
|
|
|
|
{
|
2010-05-28 23:51:00 +08:00
|
|
|
OSG_NOTICE << "RenderStage::runCameraSetUp(), "
|
2008-06-18 22:09:11 +08:00
|
|
|
"multisample FBO setup failed, FBO status = 0x"
|
2009-02-06 18:35:21 +08:00
|
|
|
<< std::hex << status << std::dec << std::endl;
|
2008-06-18 22:09:11 +08:00
|
|
|
|
|
|
|
fbo->apply(state);
|
|
|
|
fbo_multisample = 0;
|
|
|
|
_resolveFbo = 0;
|
|
|
|
|
|
|
|
// clean up.
|
|
|
|
double availableTime = 100.0f;
|
|
|
|
double currentTime = state.getFrameStamp()?state.getFrameStamp()->getReferenceTime():0.0;
|
|
|
|
osg::RenderBuffer::flushDeletedRenderBuffers(state.getContextID(),currentTime,availableTime);
|
|
|
|
osg::FrameBufferObject::flushDeletedFrameBufferObjects(state.getContextID(),currentTime,availableTime);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_resolveFbo.swap(_fbo);
|
|
|
|
_fbo = fbo_multisample;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_resolveFbo = 0;
|
|
|
|
}
|
2005-10-06 00:21:51 +08:00
|
|
|
}
|
2005-11-24 23:18:12 +08:00
|
|
|
}
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2005-11-24 23:18:12 +08:00
|
|
|
if (!fbo_supported)
|
|
|
|
{
|
2008-04-02 19:28:10 +08:00
|
|
|
if (renderTargetImplementation<renderTargetFallback)
|
|
|
|
renderTargetImplementation = renderTargetFallback;
|
2005-11-24 23:18:12 +08:00
|
|
|
else
|
2008-04-02 19:28:10 +08:00
|
|
|
renderTargetImplementation = osg::Camera::PIXEL_BUFFER_RTT;
|
2005-10-06 00:21:51 +08:00
|
|
|
}
|
|
|
|
}
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2005-11-01 18:42:54 +08:00
|
|
|
// check whether PBuffer-RTT is supported or not
|
2012-03-22 01:36:20 +08:00
|
|
|
if (renderTargetImplementation==osg::Camera::PIXEL_BUFFER_RTT &&
|
2006-01-18 19:45:58 +08:00
|
|
|
!osg::isGLExtensionSupported(state.getContextID(), "WGL_ARB_render_texture"))
|
2012-03-22 01:36:20 +08:00
|
|
|
{
|
2008-04-02 19:28:10 +08:00
|
|
|
if (renderTargetImplementation<renderTargetFallback)
|
|
|
|
renderTargetImplementation = renderTargetFallback;
|
2005-11-01 18:42:54 +08:00
|
|
|
else
|
2008-04-02 19:28:10 +08:00
|
|
|
renderTargetImplementation = osg::Camera::PIXEL_BUFFER;
|
2005-11-01 18:42:54 +08:00
|
|
|
}
|
2005-10-06 19:26:07 +08:00
|
|
|
|
2007-12-11 01:30:18 +08:00
|
|
|
// if any of the renderTargetImplementations require a separate graphics context such as with pbuffer try in turn to
|
2012-03-22 01:36:20 +08:00
|
|
|
// set up, but if each level fails then resort to the next level down.
|
2005-10-06 19:26:07 +08:00
|
|
|
while (!getGraphicsContext() &&
|
2008-04-02 19:28:10 +08:00
|
|
|
(renderTargetImplementation==osg::Camera::PIXEL_BUFFER_RTT ||
|
|
|
|
renderTargetImplementation==osg::Camera::PIXEL_BUFFER ||
|
2015-04-13 19:48:28 +08:00
|
|
|
renderTargetImplementation==osg::Camera::SEPARATE_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;
|
|
|
|
|
2006-12-23 05:53:44 +08:00
|
|
|
traits->width = width;
|
|
|
|
traits->height = height;
|
2006-08-03 23:57:39 +08:00
|
|
|
|
2010-05-28 23:51:00 +08:00
|
|
|
// OSG_NOTICE<<"traits = "<<traits->width<<" "<<traits->height<<std::endl;
|
2006-08-03 23:57:39 +08:00
|
|
|
|
2008-04-02 19:28:10 +08:00
|
|
|
traits->pbuffer = (renderTargetImplementation==osg::Camera::PIXEL_BUFFER || renderTargetImplementation==osg::Camera::PIXEL_BUFFER_RTT);
|
2015-04-13 19:48:28 +08:00
|
|
|
traits->windowDecoration = (renderTargetImplementation==osg::Camera::SEPARATE_WINDOW);
|
|
|
|
traits->doubleBuffer = (renderTargetImplementation==osg::Camera::SEPARATE_WINDOW);
|
2005-10-06 00:21:51 +08:00
|
|
|
|
2005-10-06 19:26:07 +08:00
|
|
|
osg::Texture* pBufferTexture = 0;
|
2005-10-06 00:21:51 +08:00
|
|
|
GLenum bufferFormat = GL_NONE;
|
2012-03-22 01:36:20 +08:00
|
|
|
unsigned int level = 0;
|
|
|
|
unsigned int face = 0;
|
2005-10-06 00:21:51 +08:00
|
|
|
|
|
|
|
bool colorAttached = false;
|
|
|
|
bool depthAttached = false;
|
2007-12-11 01:30:18 +08:00
|
|
|
for(osg::Camera::BufferAttachmentMap::iterator itr = bufferAttachments.begin();
|
|
|
|
itr != bufferAttachments.end();
|
2005-10-06 00:21:51 +08:00
|
|
|
++itr)
|
|
|
|
{
|
|
|
|
|
2006-11-27 22:52:07 +08:00
|
|
|
osg::Camera::BufferComponent buffer = itr->first;
|
|
|
|
osg::Camera::Attachment& attachment = itr->second;
|
2005-10-06 00:21:51 +08:00
|
|
|
switch(buffer)
|
|
|
|
{
|
2006-11-27 22:52:07 +08:00
|
|
|
case(osg::Camera::DEPTH_BUFFER):
|
2005-10-06 00:21:51 +08:00
|
|
|
{
|
2006-12-23 05:53:44 +08:00
|
|
|
traits->depth = 24;
|
2005-10-06 00:21:51 +08:00
|
|
|
depthAttached = true;
|
|
|
|
break;
|
|
|
|
}
|
2006-11-27 22:52:07 +08:00
|
|
|
case(osg::Camera::STENCIL_BUFFER):
|
2005-10-06 00:21:51 +08:00
|
|
|
{
|
2006-12-23 05:53:44 +08:00
|
|
|
traits->stencil = 8;
|
2005-10-06 00:21:51 +08:00
|
|
|
break;
|
|
|
|
}
|
2008-11-25 18:57:14 +08:00
|
|
|
case(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER):
|
|
|
|
{
|
|
|
|
traits->depth = 24;
|
|
|
|
depthAttached = true;
|
|
|
|
traits->stencil = 8;
|
|
|
|
}
|
2006-11-27 22:52:07 +08:00
|
|
|
case(osg::Camera::COLOR_BUFFER):
|
2005-10-06 00:21:51 +08:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
2008-04-02 19:28:10 +08:00
|
|
|
if (renderTargetImplementation==osg::Camera::PIXEL_BUFFER_RTT)
|
2005-10-06 00:21:51 +08:00
|
|
|
{
|
2007-06-27 17:44:35 +08:00
|
|
|
traits->target = attachment._texture.valid() ? attachment._texture->getTextureTarget() : 0;
|
2007-06-27 18:12:10 +08:00
|
|
|
traits->format = bufferFormat;
|
2006-12-23 05:53:44 +08:00
|
|
|
traits->level = level;
|
|
|
|
traits->face = face;
|
|
|
|
traits->mipMapGeneration = attachment._mipMapGeneration;
|
2005-10-06 00:21:51 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
{
|
2015-04-13 19:48:28 +08:00
|
|
|
if (renderTargetImplementation==osg::Camera::SEPARATE_WINDOW)
|
2010-02-10 02:24:37 +08:00
|
|
|
{
|
2010-05-28 23:51:00 +08:00
|
|
|
OSG_NOTICE<<"Warning: RenderStage::runCameraSetUp(State&) Window ";
|
2010-02-10 02:24:37 +08:00
|
|
|
}
|
2005-10-06 00:21:51 +08:00
|
|
|
else
|
2010-02-10 02:24:37 +08:00
|
|
|
{
|
2010-05-28 23:51:00 +08:00
|
|
|
OSG_NOTICE<<"Warning: RenderStage::runCameraSetUp(State&) Pbuffer ";
|
2010-02-10 02:24:37 +08:00
|
|
|
}
|
2005-10-06 00:21:51 +08:00
|
|
|
|
2010-05-28 23:51:00 +08:00
|
|
|
OSG_NOTICE<<"does not support multiple color outputs."<<std::endl;
|
2005-10-06 00:21:51 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!depthAttached)
|
2012-03-22 01:36:20 +08:00
|
|
|
{
|
2006-12-23 05:53:44 +08:00
|
|
|
traits->depth = 24;
|
2005-10-06 00:21:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!colorAttached)
|
2012-03-22 01:36:20 +08:00
|
|
|
{
|
2005-10-06 00:21:51 +08:00
|
|
|
if (bufferFormat == GL_NONE) bufferFormat = GL_RGB;
|
|
|
|
|
2006-12-23 05:53:44 +08:00
|
|
|
traits->red = 8;
|
|
|
|
traits->green = 8;
|
|
|
|
traits->blue = 8;
|
|
|
|
traits->alpha = (bufferFormat==GL_RGBA) ? 8 : 0;
|
2005-10-06 00:21:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// share OpenGL objects if possible...
|
|
|
|
if (state.getGraphicsContext())
|
|
|
|
{
|
2006-12-23 05:53:44 +08:00
|
|
|
traits->sharedContext = state.getGraphicsContext();
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2006-12-23 05:53:44 +08:00
|
|
|
const osg::GraphicsContext::Traits* sharedTraits = traits->sharedContext->getTraits();
|
2006-08-11 19:05:09 +08:00
|
|
|
if (sharedTraits)
|
|
|
|
{
|
2006-12-23 05:53:44 +08:00
|
|
|
traits->hostName = sharedTraits->hostName;
|
|
|
|
traits->displayNum = sharedTraits->displayNum;
|
|
|
|
traits->screenNum = sharedTraits->screenNum;
|
2006-08-11 19:05:09 +08:00
|
|
|
}
|
2005-10-06 00:21:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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
|
|
|
{
|
2010-05-28 23:51:00 +08:00
|
|
|
OSG_INFO<<"RenderStage::runCameraSetUp(State&) Context has been realized "<<std::endl;
|
2005-10-06 23:41:47 +08:00
|
|
|
|
2005-10-06 19:26:07 +08:00
|
|
|
// successfully set up graphics context as requested,
|
2012-03-22 01:36:20 +08:00
|
|
|
// will assign this graphics context to the RenderStage and
|
2005-10-06 19:26:07 +08:00
|
|
|
// associated parameters. Setting the graphics context will
|
|
|
|
// single this while loop to exit successful.
|
|
|
|
setGraphicsContext(context.get());
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2005-10-06 19:26:07 +08:00
|
|
|
// how to do we detect that an attempt to set up RTT has failed??
|
|
|
|
|
|
|
|
setDrawBuffer(GL_FRONT);
|
|
|
|
setReadBuffer(GL_FRONT);
|
|
|
|
|
2008-04-02 19:28:10 +08:00
|
|
|
if (pBufferTexture && renderTargetImplementation==osg::Camera::PIXEL_BUFFER_RTT)
|
2005-10-06 19:26:07 +08:00
|
|
|
{
|
2010-05-28 23:51:00 +08:00
|
|
|
OSG_INFO<<"RenderStage::runCameraSetUp(State&) Assign graphis context to Texture"<<std::endl;
|
2005-10-06 19:26:07 +08:00
|
|
|
pBufferTexture->setReadPBuffer(context.get());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-05-28 23:51:00 +08:00
|
|
|
OSG_INFO<<"RenderStage::runCameraSetUp(State&) Assigning texture to RenderStage so that it does the copy"<<std::endl;
|
2005-10-06 19:26:07 +08:00
|
|
|
setTexture(pBufferTexture, level, face);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2005-10-06 00:21:51 +08:00
|
|
|
{
|
2010-05-28 23:51:00 +08:00
|
|
|
OSG_INFO<<"Failed to acquire Graphics Context"<<std::endl;
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2008-04-02 19:28:10 +08:00
|
|
|
if (renderTargetImplementation==osg::Camera::PIXEL_BUFFER_RTT)
|
2005-10-06 19:26:07 +08:00
|
|
|
{
|
|
|
|
// fallback to using standard PBuffer, this will allow this while loop to continue
|
2008-04-02 19:28:10 +08:00
|
|
|
if (renderTargetImplementation<renderTargetFallback)
|
|
|
|
renderTargetImplementation = renderTargetFallback;
|
2005-11-01 18:42:54 +08:00
|
|
|
else
|
2008-04-02 19:28:10 +08:00
|
|
|
renderTargetImplementation = osg::Camera::PIXEL_BUFFER;
|
2005-10-06 19:26:07 +08:00
|
|
|
}
|
2012-03-22 01:36:20 +08:00
|
|
|
else
|
2005-10-06 19:26:07 +08:00
|
|
|
{
|
2008-04-02 19:28:10 +08:00
|
|
|
renderTargetImplementation = osg::Camera::FRAME_BUFFER;
|
2005-10-06 19:26:07 +08:00
|
|
|
}
|
2005-10-06 00:21:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
2012-03-22 01:36:20 +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.
|
2008-04-02 19:28:10 +08:00
|
|
|
if (renderTargetImplementation==osg::Camera::FRAME_BUFFER)
|
2005-10-06 19:26:07 +08:00
|
|
|
{
|
2010-05-28 23:51:00 +08:00
|
|
|
OSG_INFO<<"Setting up osg::Camera::FRAME_BUFFER"<<std::endl;
|
2005-10-06 19:26:07 +08:00
|
|
|
|
2007-12-11 01:30:18 +08:00
|
|
|
for(osg::Camera::BufferAttachmentMap::iterator itr = bufferAttachments.begin();
|
|
|
|
itr != bufferAttachments.end();
|
2005-10-06 19:26:07 +08:00
|
|
|
++itr)
|
|
|
|
{
|
2012-03-22 01:36:20 +08:00
|
|
|
// assign the texture...
|
2005-10-06 19:26:07 +08:00
|
|
|
if (itr->second._texture.valid()) setTexture(itr->second._texture.get(), itr->second._level, itr->second._face);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-10-06 00:21:51 +08:00
|
|
|
}
|
|
|
|
|
2006-09-19 04:54:48 +08:00
|
|
|
void RenderStage::copyTexture(osg::RenderInfo& renderInfo)
|
2002-10-17 21:48:46 +08:00
|
|
|
{
|
2006-09-19 04:54:48 +08:00
|
|
|
osg::State& state = *renderInfo.getState();
|
|
|
|
|
2009-08-21 17:34:48 +08:00
|
|
|
if ( _readBufferApplyMask )
|
2005-08-20 16:59:03 +08:00
|
|
|
{
|
2009-10-29 04:31:57 +08:00
|
|
|
#if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE)
|
|
|
|
glReadBuffer(_readBuffer);
|
|
|
|
#endif
|
2005-08-20 16:59:03 +08:00
|
|
|
}
|
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
|
|
|
|
2006-08-03 23:57:39 +08:00
|
|
|
// use TexCopySubImage with the offset of the viewport into the texture
|
|
|
|
// note, this path mirrors the pbuffer and fbo means for updating the texture.
|
|
|
|
// Robert Osfield, 3rd August 2006.
|
|
|
|
if ((texture2D = dynamic_cast<osg::Texture2D*>(_texture.get())) != 0)
|
|
|
|
{
|
2007-01-05 00:48:23 +08:00
|
|
|
texture2D->copyTexSubImage2D(state,
|
|
|
|
static_cast<int>(_viewport->x()),
|
|
|
|
static_cast<int>(_viewport->y()),
|
|
|
|
static_cast<int>(_viewport->x()),
|
|
|
|
static_cast<int>(_viewport->y()),
|
|
|
|
static_cast<int>(_viewport->width()),
|
|
|
|
static_cast<int>(_viewport->height()));
|
2006-08-03 23:57:39 +08:00
|
|
|
}
|
|
|
|
else if ((textureRec = dynamic_cast<osg::TextureRectangle*>(_texture.get())) != 0)
|
|
|
|
{
|
2007-01-05 00:48:23 +08:00
|
|
|
textureRec->copyTexSubImage2D(state,
|
|
|
|
static_cast<int>(_viewport->x()),
|
|
|
|
static_cast<int>(_viewport->y()),
|
|
|
|
static_cast<int>(_viewport->x()),
|
|
|
|
static_cast<int>(_viewport->y()),
|
|
|
|
static_cast<int>(_viewport->width()),
|
|
|
|
static_cast<int>(_viewport->height()));
|
2006-08-03 23:57:39 +08:00
|
|
|
}
|
|
|
|
else if ((texture1D = dynamic_cast<osg::Texture1D*>(_texture.get())) != 0)
|
|
|
|
{
|
|
|
|
// need to implement
|
2007-01-05 00:48:23 +08:00
|
|
|
texture1D->copyTexSubImage1D(state,
|
|
|
|
static_cast<int>(_viewport->x()),
|
|
|
|
static_cast<int>(_viewport->x()),
|
|
|
|
static_cast<int>(_viewport->y()),
|
|
|
|
static_cast<int>(_viewport->width()));
|
2006-08-03 23:57:39 +08:00
|
|
|
}
|
|
|
|
else if ((texture3D = dynamic_cast<osg::Texture3D*>(_texture.get())) != 0)
|
|
|
|
{
|
|
|
|
// need to implement
|
2012-03-22 01:36:20 +08:00
|
|
|
texture3D->copyTexSubImage3D(state,
|
2007-01-05 00:48:23 +08:00
|
|
|
static_cast<int>(_viewport->x()),
|
|
|
|
static_cast<int>(_viewport->y()),
|
|
|
|
_face,
|
|
|
|
static_cast<int>(_viewport->x()),
|
|
|
|
static_cast<int>(_viewport->y()),
|
|
|
|
static_cast<int>(_viewport->width()),
|
|
|
|
static_cast<int>(_viewport->height()));
|
2006-08-03 23:57:39 +08:00
|
|
|
}
|
|
|
|
else if ((textureCubeMap = dynamic_cast<osg::TextureCubeMap*>(_texture.get())) != 0)
|
|
|
|
{
|
|
|
|
// need to implement
|
2012-03-22 01:36:20 +08:00
|
|
|
textureCubeMap->copyTexSubImageCubeMap(state, _face,
|
2007-01-05 00:48:23 +08:00
|
|
|
static_cast<int>(_viewport->x()),
|
|
|
|
static_cast<int>(_viewport->y()),
|
|
|
|
static_cast<int>(_viewport->x()),
|
|
|
|
static_cast<int>(_viewport->y()),
|
|
|
|
static_cast<int>(_viewport->width()),
|
|
|
|
static_cast<int>(_viewport->height()));
|
2006-08-03 23:57:39 +08:00
|
|
|
}
|
2005-08-20 16:59:03 +08:00
|
|
|
}
|
2005-08-17 18:12:49 +08:00
|
|
|
|
2006-09-19 04:54:48 +08:00
|
|
|
void RenderStage::drawInner(osg::RenderInfo& renderInfo,RenderLeaf*& previous, bool& doCopyTexture)
|
2005-08-20 16:59:03 +08:00
|
|
|
{
|
2008-06-18 22:09:11 +08:00
|
|
|
struct SubFunc
|
|
|
|
{
|
|
|
|
static void applyReadFBO(bool& apply_read_fbo,
|
|
|
|
const FrameBufferObject* read_fbo, osg::State& state)
|
|
|
|
{
|
|
|
|
if (read_fbo->isMultisample())
|
|
|
|
{
|
2010-05-28 23:51:00 +08:00
|
|
|
OSG_WARN << "Attempting to read from a"
|
2008-06-18 22:09:11 +08:00
|
|
|
" multisampled framebuffer object. Set a resolve"
|
|
|
|
" framebuffer on the RenderStage to fix this." << std::endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (apply_read_fbo)
|
|
|
|
{
|
|
|
|
// Bind the monosampled FBO to read from
|
|
|
|
read_fbo->apply(state, FrameBufferObject::READ_FRAMEBUFFER);
|
|
|
|
apply_read_fbo = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2006-09-19 04:54:48 +08:00
|
|
|
osg::State& state = *renderInfo.getState();
|
|
|
|
|
2014-12-10 18:38:12 +08:00
|
|
|
osg::GLExtensions* ext = _fbo.valid() ? state.get<osg::GLExtensions>() : 0;
|
2014-12-10 02:30:28 +08:00
|
|
|
bool fbo_supported = ext && ext->isFrameBufferObjectSupported;
|
2008-04-16 03:36:40 +08:00
|
|
|
|
|
|
|
bool using_multiple_render_targets = fbo_supported && _fbo->hasMultipleRenderingTargets();
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2008-04-03 01:08:40 +08:00
|
|
|
if (!using_multiple_render_targets)
|
2005-08-17 18:12:49 +08:00
|
|
|
{
|
2009-10-29 04:31:57 +08:00
|
|
|
#if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE)
|
2012-03-22 01:36:20 +08:00
|
|
|
|
|
|
|
if( getDrawBufferApplyMask() )
|
2009-10-29 04:31:57 +08:00
|
|
|
glDrawBuffer(_drawBuffer);
|
2008-04-03 01:08:40 +08:00
|
|
|
|
2012-03-22 01:36:20 +08:00
|
|
|
if( getReadBufferApplyMask() )
|
2009-10-29 04:31:57 +08:00
|
|
|
glReadBuffer(_readBuffer);
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2009-10-29 04:31:57 +08:00
|
|
|
#endif
|
2005-08-17 18:12:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (fbo_supported)
|
|
|
|
{
|
2005-08-20 16:59:03 +08:00
|
|
|
_fbo->apply(state);
|
2005-08-17 18:12:49 +08:00
|
|
|
}
|
|
|
|
|
2012-03-22 01:36:20 +08:00
|
|
|
// do the drawing itself.
|
2006-09-19 04:54:48 +08:00
|
|
|
RenderBin::draw(renderInfo,previous);
|
2005-06-15 04:51:35 +08:00
|
|
|
|
2005-08-17 18:12:49 +08:00
|
|
|
|
2006-05-09 17:47:26 +08:00
|
|
|
if(state.getCheckForGLErrors()!=osg::State::NEVER_CHECK_GL_ERRORS)
|
2005-11-05 03:00:49 +08:00
|
|
|
{
|
2009-11-09 19:36:54 +08:00
|
|
|
if (state.checkGLErrors("after RenderBin::draw(..)"))
|
2006-05-09 17:47:26 +08:00
|
|
|
{
|
2014-12-10 02:30:28 +08:00
|
|
|
if ( ext )
|
2009-02-20 03:05:39 +08:00
|
|
|
{
|
2014-12-10 02:30:28 +08:00
|
|
|
GLenum fbstatus = ext->glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
|
2009-02-20 03:05:39 +08:00
|
|
|
if ( fbstatus != GL_FRAMEBUFFER_COMPLETE_EXT )
|
|
|
|
{
|
2010-05-28 23:51:00 +08:00
|
|
|
OSG_NOTICE<<"RenderStage::drawInner(,) FBO status = 0x"<<std::hex<<fbstatus<<std::dec<<std::endl;
|
2009-02-20 03:05:39 +08:00
|
|
|
}
|
|
|
|
}
|
2006-05-09 17:47:26 +08:00
|
|
|
}
|
2005-11-05 03:00:49 +08:00
|
|
|
}
|
|
|
|
|
2008-07-01 00:53:06 +08:00
|
|
|
const FrameBufferObject* read_fbo = fbo_supported ? _fbo.get() : 0;
|
2008-06-18 22:09:11 +08:00
|
|
|
bool apply_read_fbo = false;
|
|
|
|
|
2014-12-10 02:30:28 +08:00
|
|
|
if (fbo_supported && _resolveFbo.valid() && ext->glBlitFramebuffer)
|
2008-06-18 22:09:11 +08:00
|
|
|
{
|
|
|
|
GLbitfield blitMask = 0;
|
2011-06-15 17:36:34 +08:00
|
|
|
bool needToBlitColorBuffers = false;
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2008-06-18 22:09:11 +08:00
|
|
|
//find which buffer types should be copied
|
|
|
|
for (FrameBufferObject::AttachmentMap::const_iterator
|
|
|
|
it = _resolveFbo->getAttachmentMap().begin(),
|
|
|
|
end =_resolveFbo->getAttachmentMap().end(); it != end; ++it)
|
|
|
|
{
|
|
|
|
switch (it->first)
|
|
|
|
{
|
|
|
|
case Camera::DEPTH_BUFFER:
|
|
|
|
blitMask |= GL_DEPTH_BUFFER_BIT;
|
|
|
|
break;
|
|
|
|
case Camera::STENCIL_BUFFER:
|
|
|
|
blitMask |= GL_STENCIL_BUFFER_BIT;
|
|
|
|
break;
|
2008-11-25 18:57:14 +08:00
|
|
|
case Camera::PACKED_DEPTH_STENCIL_BUFFER:
|
|
|
|
blitMask |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
|
2011-06-15 17:36:34 +08:00
|
|
|
break;
|
|
|
|
case Camera::COLOR_BUFFER:
|
2008-06-18 22:09:11 +08:00
|
|
|
blitMask |= GL_COLOR_BUFFER_BIT;
|
|
|
|
break;
|
2011-06-15 17:36:34 +08:00
|
|
|
default:
|
|
|
|
needToBlitColorBuffers = true;
|
|
|
|
break;
|
2008-06-18 22:09:11 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Bind the resolve framebuffer to blit into.
|
2009-02-27 18:47:33 +08:00
|
|
|
_fbo->apply(state, FrameBufferObject::READ_FRAMEBUFFER);
|
2008-06-18 22:09:11 +08:00
|
|
|
_resolveFbo->apply(state, FrameBufferObject::DRAW_FRAMEBUFFER);
|
|
|
|
|
2011-06-15 17:36:34 +08:00
|
|
|
if (blitMask)
|
|
|
|
{
|
|
|
|
// Blit to the resolve framebuffer.
|
|
|
|
// Note that (with nvidia 175.16 windows drivers at least) if the read
|
|
|
|
// framebuffer is multisampled then the dimension arguments are ignored
|
|
|
|
// and the whole framebuffer is always copied.
|
2014-12-10 02:30:28 +08:00
|
|
|
ext->glBlitFramebuffer(
|
From Tim George, "Currently there is a problem with using a camera with a viewport with a non 0 offset and also using an FBO. The problem is that only area made up of the viewports width and height is drawn based on an offset of 0,0 instead of using the viewports offset.
It is caused by line 991 in RenderStage.cpp:
Code:
fbo_ext->glBlitFramebuffer(
0, 0, static_cast<GLint>(_viewport->width()), static_cast<GLint>(_viewport->height()),
0, 0, static_cast<GLint>(_viewport->width()), static_cast<GLint>(_viewport->height()),
blitMask, GL_NEAREST);
which is not taking into account the viewport x and y when performing the blit. It probably should be:
Code:
fbo_ext->glBlitFramebuffer(
static_cast<GLint>(_viewport->x()), static_cast<GLint>(_viewport->y()),
static_cast<GLint>(_viewport->width()) + static_cast<GLint>(_viewport->x()), static_cast<GLint>(_viewport->height()) + static_cast<GLint>(_viewport->y()),
static_cast<GLint>(_viewport->x()), static_cast<GLint>(_viewport->y()),
static_cast<GLint>(_viewport->width()) + static_cast<GLint>(_viewport->x()), static_cast<GLint>(_viewport->height()) + static_cast<GLint>(_viewport->y()),
blitMask, GL_NEAREST);
"
Note from Robert Osfield, made small tweak to above on merge, changing the width+x to x+width to make it read more naturally.
git-svn-id: http://svn.openscenegraph.org/osg/OpenSceneGraph/trunk@14405 16af8721-9629-0410-8352-f15c8da7e697
2014-08-09 00:34:12 +08:00
|
|
|
static_cast<GLint>(_viewport->x()), static_cast<GLint>(_viewport->y()),
|
|
|
|
static_cast<GLint>(_viewport->x() + _viewport->width()), static_cast<GLint>(_viewport->y() + _viewport->height()),
|
|
|
|
static_cast<GLint>(_viewport->x()), static_cast<GLint>(_viewport->y()),
|
|
|
|
static_cast<GLint>(_viewport->x() + _viewport->width()), static_cast<GLint>(_viewport->y() + _viewport->height()),
|
2011-06-15 17:36:34 +08:00
|
|
|
blitMask, GL_NEAREST);
|
|
|
|
}
|
2008-06-18 22:09:11 +08:00
|
|
|
|
2011-06-17 16:47:36 +08:00
|
|
|
#if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE)
|
2011-06-15 17:36:34 +08:00
|
|
|
if (needToBlitColorBuffers)
|
|
|
|
{
|
|
|
|
for (FrameBufferObject::AttachmentMap::const_iterator
|
|
|
|
it = _resolveFbo->getAttachmentMap().begin(),
|
|
|
|
end =_resolveFbo->getAttachmentMap().end(); it != end; ++it)
|
|
|
|
{
|
|
|
|
osg::Camera::BufferComponent attachment = it->first;
|
|
|
|
if (attachment >=osg::Camera::COLOR_BUFFER0)
|
|
|
|
{
|
|
|
|
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + (attachment - osg::Camera::COLOR_BUFFER0));
|
|
|
|
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + (attachment - osg::Camera::COLOR_BUFFER0));
|
|
|
|
|
2014-12-10 02:30:28 +08:00
|
|
|
ext->glBlitFramebuffer(
|
From Tim George, "Currently there is a problem with using a camera with a viewport with a non 0 offset and also using an FBO. The problem is that only area made up of the viewports width and height is drawn based on an offset of 0,0 instead of using the viewports offset.
It is caused by line 991 in RenderStage.cpp:
Code:
fbo_ext->glBlitFramebuffer(
0, 0, static_cast<GLint>(_viewport->width()), static_cast<GLint>(_viewport->height()),
0, 0, static_cast<GLint>(_viewport->width()), static_cast<GLint>(_viewport->height()),
blitMask, GL_NEAREST);
which is not taking into account the viewport x and y when performing the blit. It probably should be:
Code:
fbo_ext->glBlitFramebuffer(
static_cast<GLint>(_viewport->x()), static_cast<GLint>(_viewport->y()),
static_cast<GLint>(_viewport->width()) + static_cast<GLint>(_viewport->x()), static_cast<GLint>(_viewport->height()) + static_cast<GLint>(_viewport->y()),
static_cast<GLint>(_viewport->x()), static_cast<GLint>(_viewport->y()),
static_cast<GLint>(_viewport->width()) + static_cast<GLint>(_viewport->x()), static_cast<GLint>(_viewport->height()) + static_cast<GLint>(_viewport->y()),
blitMask, GL_NEAREST);
"
Note from Robert Osfield, made small tweak to above on merge, changing the width+x to x+width to make it read more naturally.
git-svn-id: http://svn.openscenegraph.org/osg/OpenSceneGraph/trunk@14405 16af8721-9629-0410-8352-f15c8da7e697
2014-08-09 00:34:12 +08:00
|
|
|
static_cast<GLint>(_viewport->x()), static_cast<GLint>(_viewport->y()),
|
|
|
|
static_cast<GLint>(_viewport->x() + _viewport->width()), static_cast<GLint>(_viewport->y() + _viewport->height()),
|
|
|
|
static_cast<GLint>(_viewport->x()), static_cast<GLint>(_viewport->y()),
|
|
|
|
static_cast<GLint>(_viewport->x() + _viewport->width()), static_cast<GLint>(_viewport->y() + _viewport->height()),
|
2011-06-15 17:36:34 +08:00
|
|
|
GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
|
|
|
}
|
|
|
|
}
|
2011-06-17 16:47:36 +08:00
|
|
|
// reset the read and draw buffers? will comment out for now with the assumption that
|
2015-06-01 21:40:20 +08:00
|
|
|
// the buffers will be set explicitly when needed elsewhere.
|
2011-06-15 17:36:34 +08:00
|
|
|
// glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
|
|
|
// glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
|
|
|
}
|
2011-06-17 16:47:36 +08:00
|
|
|
#endif
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2008-06-18 22:09:11 +08:00
|
|
|
apply_read_fbo = true;
|
|
|
|
read_fbo = _resolveFbo.get();
|
|
|
|
|
|
|
|
using_multiple_render_targets = read_fbo->hasMultipleRenderingTargets();
|
|
|
|
}
|
|
|
|
|
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
|
|
|
{
|
2008-07-01 00:53:06 +08:00
|
|
|
if (read_fbo) SubFunc::applyReadFBO(apply_read_fbo, read_fbo, state);
|
2006-09-19 04:54:48 +08:00
|
|
|
copyTexture(renderInfo);
|
2005-08-17 18:12:49 +08:00
|
|
|
}
|
2008-06-18 22:09:11 +08:00
|
|
|
|
2006-11-27 22:52:07 +08:00
|
|
|
std::map< osg::Camera::BufferComponent, Attachment>::const_iterator itr;
|
2007-02-16 23:14:16 +08:00
|
|
|
for(itr = _bufferAttachmentMap.begin();
|
|
|
|
itr != _bufferAttachmentMap.end();
|
|
|
|
++itr)
|
|
|
|
{
|
2008-06-18 22:09:11 +08:00
|
|
|
if (itr->second._image.valid())
|
|
|
|
{
|
2008-07-01 00:53:06 +08:00
|
|
|
if (read_fbo) SubFunc::applyReadFBO(apply_read_fbo, read_fbo, state);
|
2008-06-18 22:09:11 +08:00
|
|
|
|
2009-10-29 04:31:57 +08:00
|
|
|
#if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE)
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2009-10-29 04:31:57 +08:00
|
|
|
if (using_multiple_render_targets)
|
2008-06-18 22:09:11 +08:00
|
|
|
{
|
2009-10-29 04:31:57 +08:00
|
|
|
int attachment=itr->first;
|
|
|
|
if (attachment==osg::Camera::DEPTH_BUFFER || attachment==osg::Camera::STENCIL_BUFFER) {
|
|
|
|
// assume first buffer rendered to is the one we want
|
|
|
|
glReadBuffer(read_fbo->getMultipleRenderingTargets()[0]);
|
|
|
|
} else {
|
|
|
|
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + (attachment - osg::Camera::COLOR_BUFFER0));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (_readBuffer != GL_NONE)
|
|
|
|
{
|
|
|
|
glReadBuffer(_readBuffer);
|
|
|
|
}
|
2008-06-18 22:09:11 +08:00
|
|
|
}
|
2009-10-29 04:31:57 +08:00
|
|
|
|
|
|
|
#endif
|
2008-06-18 22:09:11 +08:00
|
|
|
|
|
|
|
GLenum pixelFormat = itr->second._image->getPixelFormat();
|
|
|
|
if (pixelFormat==0) pixelFormat = _imageReadPixelFormat;
|
|
|
|
if (pixelFormat==0) pixelFormat = GL_RGB;
|
|
|
|
|
|
|
|
GLenum dataType = itr->second._image->getDataType();
|
|
|
|
if (dataType==0) dataType = _imageReadPixelDataType;
|
2012-03-22 01:36:20 +08:00
|
|
|
if (dataType==0) dataType = GL_UNSIGNED_BYTE;
|
2008-06-18 22:09:11 +08:00
|
|
|
|
|
|
|
itr->second._image->readPixels(static_cast<int>(_viewport->x()),
|
|
|
|
static_cast<int>(_viewport->y()),
|
|
|
|
static_cast<int>(_viewport->width()),
|
2012-03-22 01:36:20 +08:00
|
|
|
static_cast<int>(_viewport->height()),
|
2008-06-18 22:09:11 +08:00
|
|
|
pixelFormat, dataType);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-08-17 18:12:49 +08:00
|
|
|
if (fbo_supported)
|
|
|
|
{
|
2008-06-18 22:09:11 +08:00
|
|
|
if (getDisableFboAfterRender())
|
|
|
|
{
|
|
|
|
// switch off the frame buffer object
|
2010-11-26 00:06:04 +08:00
|
|
|
GLuint fboId = state.getGraphicsContext() ? state.getGraphicsContext()->getDefaultFboId() : 0;
|
2014-12-10 02:30:28 +08:00
|
|
|
ext->glBindFramebuffer(GL_FRAMEBUFFER_EXT, fboId);
|
2008-06-18 22:09:11 +08:00
|
|
|
}
|
2005-08-20 16:59:03 +08:00
|
|
|
|
|
|
|
doCopyTexture = true;
|
2005-08-17 18:12:49 +08:00
|
|
|
}
|
2008-06-18 22:09:11 +08:00
|
|
|
|
2013-06-21 21:59:18 +08:00
|
|
|
if (fbo_supported && _camera.valid())
|
2005-08-17 18:12:49 +08:00
|
|
|
{
|
|
|
|
// now generate mipmaps if they are required.
|
2008-06-18 22:09:11 +08:00
|
|
|
const osg::Camera::BufferAttachmentMap& bufferAttachments = _camera->getBufferAttachmentMap();
|
|
|
|
for(osg::Camera::BufferAttachmentMap::const_iterator itr = bufferAttachments.begin();
|
|
|
|
itr != bufferAttachments.end();
|
2005-08-17 18:12:49 +08:00
|
|
|
++itr)
|
|
|
|
{
|
2012-03-22 01:36:20 +08:00
|
|
|
if (itr->second._texture.valid() && itr->second._mipMapGeneration)
|
2005-08-17 18:12:49 +08:00
|
|
|
{
|
2006-02-05 05:20:25 +08:00
|
|
|
state.setActiveTextureUnit(0);
|
|
|
|
state.applyTextureAttribute(0, itr->second._texture.get());
|
2014-12-10 02:30:28 +08:00
|
|
|
ext->glGenerateMipmap(itr->second._texture->getTextureTarget());
|
2005-08-17 18:12:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-08-20 16:59:03 +08:00
|
|
|
}
|
|
|
|
|
2007-02-03 06:30:36 +08:00
|
|
|
struct DrawInnerOperation : public osg::Operation
|
2005-08-20 16:59:03 +08:00
|
|
|
{
|
2012-03-22 01:36:20 +08:00
|
|
|
DrawInnerOperation(RenderStage* stage, osg::RenderInfo& renderInfo) :
|
2015-07-23 23:46:39 +08:00
|
|
|
osg::Referenced(true),
|
2007-02-03 06:30:36 +08:00
|
|
|
osg::Operation("DrawInnerStage",false),
|
2006-09-19 04:54:48 +08:00
|
|
|
_stage(stage),
|
|
|
|
_renderInfo(renderInfo) {}
|
2005-08-20 16:59:03 +08:00
|
|
|
|
2007-02-03 06:30:36 +08:00
|
|
|
virtual void operator () (osg::Object* object)
|
2005-08-20 16:59:03 +08:00
|
|
|
{
|
2007-02-03 06:30:36 +08:00
|
|
|
osg::GraphicsContext* context = dynamic_cast<osg::GraphicsContext*>(object);
|
|
|
|
if (!context) return;
|
|
|
|
|
2010-05-28 23:51:00 +08:00
|
|
|
// OSG_NOTICE<<"DrawInnerOperation operator"<<std::endl;
|
2005-08-20 16:59:03 +08:00
|
|
|
if (_stage && context)
|
|
|
|
{
|
|
|
|
RenderLeaf* previous = 0;
|
|
|
|
bool doCopyTexture = false;
|
2006-09-19 04:54:48 +08:00
|
|
|
_renderInfo.setState(context->getState());
|
|
|
|
_stage->drawInner(_renderInfo, previous, doCopyTexture);
|
2005-08-20 16:59:03 +08:00
|
|
|
}
|
|
|
|
}
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2005-08-20 16:59:03 +08:00
|
|
|
RenderStage* _stage;
|
2006-09-19 04:54:48 +08:00
|
|
|
RenderInfo _renderInfo;
|
2005-08-20 16:59:03 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2006-09-19 04:54:48 +08:00
|
|
|
void RenderStage::draw(osg::RenderInfo& renderInfo,RenderLeaf*& previous)
|
2005-08-20 16:59:03 +08:00
|
|
|
{
|
|
|
|
if (_stageDrawnThisFrame) return;
|
|
|
|
|
2010-04-19 22:49:42 +08:00
|
|
|
if(_initialViewMatrix.valid()) renderInfo.getState()->setInitialViewMatrix(_initialViewMatrix.get());
|
|
|
|
|
2012-03-22 01:36:20 +08:00
|
|
|
// push the stages camera so that drawing code can query it
|
2013-06-21 21:59:18 +08:00
|
|
|
if (_camera.valid()) renderInfo.pushCamera(_camera.get());
|
2008-02-29 23:25:57 +08:00
|
|
|
|
2005-08-20 16:59:03 +08:00
|
|
|
_stageDrawnThisFrame = true;
|
|
|
|
|
2013-06-21 21:59:18 +08:00
|
|
|
if (_camera.valid() && _camera->getInitialDrawCallback())
|
2008-02-29 23:25:57 +08:00
|
|
|
{
|
2015-06-01 21:40:20 +08:00
|
|
|
// if we have a camera with a initial draw callback invoke it.
|
2008-02-29 23:25:57 +08:00
|
|
|
(*(_camera->getInitialDrawCallback()))(renderInfo);
|
|
|
|
}
|
|
|
|
|
2005-08-20 16:59:03 +08:00
|
|
|
// note, SceneView does call to drawPreRenderStages explicitly
|
|
|
|
// so there is no need to call it here.
|
2006-09-19 04:54:48 +08:00
|
|
|
drawPreRenderStages(renderInfo,previous);
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2015-05-27 01:12:05 +08:00
|
|
|
if (_cameraRequiresSetUp || (_camera.valid() && _cameraAttachmentMapModifiedCount!=_camera->getAttachmentMapModifiedCount()))
|
2005-10-06 00:21:51 +08:00
|
|
|
{
|
2006-09-19 04:54:48 +08:00
|
|
|
runCameraSetUp(renderInfo);
|
2005-10-06 00:21:51 +08:00
|
|
|
}
|
|
|
|
|
2006-09-19 04:54:48 +08:00
|
|
|
osg::State& state = *renderInfo.getState();
|
2005-08-20 16:59:03 +08:00
|
|
|
|
|
|
|
osg::State* useState = &state;
|
|
|
|
osg::GraphicsContext* callingContext = state.getGraphicsContext();
|
|
|
|
osg::GraphicsContext* useContext = callingContext;
|
2007-07-12 23:54:45 +08:00
|
|
|
osg::OperationThread* useThread = 0;
|
2006-09-19 04:54:48 +08:00
|
|
|
osg::RenderInfo useRenderInfo(renderInfo);
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2007-06-28 04:34:29 +08:00
|
|
|
RenderLeaf* saved_previous = previous;
|
2005-08-20 16:59:03 +08:00
|
|
|
|
|
|
|
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();
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2010-05-28 23:51:00 +08:00
|
|
|
// OSG_NOTICE<<" enclosing state before - "<<state.getStateSetStackSize()<<std::endl;
|
2007-06-30 22:30:12 +08:00
|
|
|
|
2005-08-20 16:59:03 +08:00
|
|
|
useState = _graphicsContext->getState();
|
|
|
|
useContext = _graphicsContext.get();
|
|
|
|
useThread = useContext->getGraphicsThread();
|
2006-09-19 04:54:48 +08:00
|
|
|
useRenderInfo.setState(useState);
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2007-12-11 01:30:18 +08:00
|
|
|
// synchronize the frame stamps
|
2006-04-17 21:25:33 +08:00
|
|
|
useState->setFrameStamp(const_cast<osg::FrameStamp*>(state.getFrameStamp()));
|
2007-02-15 22:47:06 +08:00
|
|
|
|
|
|
|
// map the DynamicObjectCount across to the new window
|
2007-02-15 04:44:17 +08:00
|
|
|
useState->setDynamicObjectCount(state.getDynamicObjectCount());
|
|
|
|
useState->setDynamicObjectRenderingCompletedCallback(state.getDynamicObjectRenderingCompletedCallback());
|
2012-03-22 01:36:20 +08:00
|
|
|
|
|
|
|
if (!useThread)
|
2007-06-28 04:34:29 +08:00
|
|
|
{
|
|
|
|
previous = 0;
|
|
|
|
useContext->makeCurrent();
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2010-05-28 23:51:00 +08:00
|
|
|
// OSG_NOTICE<<" nested state before - "<<useState->getStateSetStackSize()<<std::endl;
|
2007-06-28 04:34:29 +08:00
|
|
|
}
|
2005-08-20 16:59:03 +08:00
|
|
|
}
|
2007-06-02 03:45:24 +08:00
|
|
|
|
2007-06-30 22:30:12 +08:00
|
|
|
unsigned int originalStackSize = useState->getStateSetStackSize();
|
|
|
|
|
2013-06-21 21:59:18 +08:00
|
|
|
if (_camera.valid() && _camera->getPreDrawCallback())
|
2007-06-02 03:45:24 +08:00
|
|
|
{
|
2008-02-29 23:25:57 +08:00
|
|
|
// if we have a camera with a pre draw callback invoke it.
|
|
|
|
(*(_camera->getPreDrawCallback()))(renderInfo);
|
2007-06-02 03:45:24 +08:00
|
|
|
}
|
2012-03-22 01:36:20 +08:00
|
|
|
|
|
|
|
bool doCopyTexture = _texture.valid() ?
|
2005-08-20 16:59:03 +08:00
|
|
|
(callingContext != useContext) :
|
|
|
|
false;
|
|
|
|
|
|
|
|
if (useThread)
|
|
|
|
{
|
2007-07-10 03:04:36 +08:00
|
|
|
#if 1
|
|
|
|
ref_ptr<osg::BlockAndFlushOperation> block = new osg::BlockAndFlushOperation;
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2007-07-10 03:04:36 +08:00
|
|
|
useThread->add(new DrawInnerOperation( this, renderInfo ));
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2007-07-10 03:04:36 +08:00
|
|
|
useThread->add(block.get());
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2007-07-10 03:04:36 +08:00
|
|
|
// wait till the DrawInnerOperations is complete.
|
|
|
|
block->block();
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2007-07-10 03:04:36 +08:00
|
|
|
doCopyTexture = false;
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2007-07-10 03:04:36 +08:00
|
|
|
#else
|
2006-09-19 04:54:48 +08:00
|
|
|
useThread->add(new DrawInnerOperation( this, renderInfo ), true);
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2005-08-20 16:59:03 +08:00
|
|
|
doCopyTexture = false;
|
2012-03-22 01:36:20 +08:00
|
|
|
#endif
|
2005-08-20 16:59:03 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-09-19 04:54:48 +08:00
|
|
|
drawInner( useRenderInfo, previous, doCopyTexture);
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2006-11-28 19:10:15 +08:00
|
|
|
if (useRenderInfo.getUserData() != renderInfo.getUserData())
|
|
|
|
{
|
|
|
|
renderInfo.setUserData(useRenderInfo.getUserData());
|
|
|
|
}
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2005-08-20 16:59:03 +08:00
|
|
|
}
|
|
|
|
|
2007-02-15 04:44:17 +08:00
|
|
|
if (useState != &state)
|
|
|
|
{
|
2007-02-15 22:47:06 +08:00
|
|
|
// reset the local State's DynamicObjectCount
|
2007-02-15 04:44:17 +08:00
|
|
|
state.setDynamicObjectCount(useState->getDynamicObjectCount());
|
|
|
|
useState->setDynamicObjectRenderingCompletedCallback(0);
|
|
|
|
}
|
|
|
|
|
2005-08-20 16:59:03 +08:00
|
|
|
|
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
|
2006-09-19 04:54:48 +08:00
|
|
|
copyTexture(renderInfo);
|
2005-08-20 16:59:03 +08:00
|
|
|
}
|
|
|
|
|
2013-06-21 21:59:18 +08:00
|
|
|
if (_camera.valid() && _camera->getPostDrawCallback())
|
2005-08-20 16:59:03 +08:00
|
|
|
{
|
|
|
|
// if we have a camera with a post draw callback invoke it.
|
2008-02-29 23:25:57 +08:00
|
|
|
(*(_camera->getPostDrawCallback()))(renderInfo);
|
2005-08-20 16:59:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (_graphicsContext.valid() && _graphicsContext != callingContext)
|
|
|
|
{
|
2007-06-30 22:30:12 +08:00
|
|
|
useState->popStateSetStackToSize(originalStackSize);
|
|
|
|
|
2007-02-16 23:14:16 +08:00
|
|
|
if (!useThread)
|
|
|
|
{
|
2007-06-30 22:30:12 +08:00
|
|
|
|
|
|
|
|
2007-02-16 23:14:16 +08:00
|
|
|
// flush any command left in the useContex's FIFO
|
|
|
|
// to ensure that textures are updated before main thread commenses.
|
|
|
|
glFlush();
|
2012-03-22 01:36:20 +08:00
|
|
|
|
|
|
|
|
2007-02-16 23:14:16 +08:00
|
|
|
useContext->releaseContext();
|
|
|
|
}
|
2005-08-20 16:59:03 +08:00
|
|
|
}
|
2005-08-17 18:12:49 +08:00
|
|
|
|
|
|
|
if (callingContext && useContext != callingContext)
|
|
|
|
{
|
|
|
|
// restore the graphics context.
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2007-06-28 04:34:29 +08:00
|
|
|
previous = saved_previous;
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2010-05-28 23:51:00 +08:00
|
|
|
// OSG_NOTICE<<" nested state after - "<<useState->getStateSetStackSize()<<std::endl;
|
|
|
|
// OSG_NOTICE<<" enclosing state after - "<<state.getStateSetStackSize()<<std::endl;
|
2007-06-30 22:30:12 +08:00
|
|
|
|
2005-08-17 18:12:49 +08:00
|
|
|
callingContext->makeCurrent();
|
|
|
|
}
|
|
|
|
|
2008-02-29 23:25:57 +08:00
|
|
|
// render all the post draw callbacks
|
2006-09-19 04:54:48 +08:00
|
|
|
drawPostRenderStages(renderInfo,previous);
|
2008-02-29 23:25:57 +08:00
|
|
|
|
2013-06-21 21:59:18 +08:00
|
|
|
if (_camera.valid() && _camera->getFinalDrawCallback())
|
2008-02-29 23:25:57 +08:00
|
|
|
{
|
|
|
|
// if we have a camera with a final callback invoke it.
|
|
|
|
(*(_camera->getFinalDrawCallback()))(renderInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
// pop the render stages camera.
|
2013-06-21 21:59:18 +08:00
|
|
|
if (_camera.valid()) renderInfo.popCamera();
|
2002-10-17 21:48:46 +08:00
|
|
|
}
|
|
|
|
|
2006-09-19 04:54:48 +08:00
|
|
|
void RenderStage::drawImplementation(osg::RenderInfo& renderInfo,RenderLeaf*& previous)
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
2006-09-19 04:54:48 +08:00
|
|
|
osg::State& state = *renderInfo.getState();
|
2005-11-23 21:44:27 +08:00
|
|
|
|
2001-09-22 10:42:08 +08:00
|
|
|
if (!_viewport)
|
|
|
|
{
|
2010-05-28 23:51:00 +08:00
|
|
|
OSG_FATAL << "Error: cannot draw stage due to undefined viewport."<< std::endl;
|
2001-09-22 10:42:08 +08:00
|
|
|
return;
|
|
|
|
}
|
2007-07-15 01:07:59 +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
|
|
|
|
2007-01-05 00:48:23 +08:00
|
|
|
glScissor( static_cast<int>(_viewport->x()),
|
|
|
|
static_cast<int>(_viewport->y()),
|
|
|
|
static_cast<int>(_viewport->width()),
|
|
|
|
static_cast<int>(_viewport->height()) );
|
2003-01-24 17:11:05 +08:00
|
|
|
//cout << " clearing "<<this<< " "<<_viewport->x()<<","<< _viewport->y()<<","<< _viewport->width()<<","<< _viewport->height()<<std::endl;
|
2009-05-18 23:46:02 +08:00
|
|
|
state.applyMode( GL_SCISSOR_TEST, true );
|
2001-09-20 05:19:47 +08:00
|
|
|
|
|
|
|
// 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)
|
2009-05-18 23:46:02 +08:00
|
|
|
{
|
2001-09-20 05:19:47 +08:00
|
|
|
glClearColor( _clearColor[0], _clearColor[1], _clearColor[2], _clearColor[3]);
|
2009-05-18 23:46:02 +08:00
|
|
|
}
|
2001-09-20 05:19:47 +08:00
|
|
|
|
|
|
|
if (_clearMask & GL_DEPTH_BUFFER_BIT)
|
2009-05-18 23:46:02 +08:00
|
|
|
{
|
2009-10-29 04:31:57 +08:00
|
|
|
#if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE)
|
|
|
|
glClearDepth( _clearDepth);
|
|
|
|
#else
|
|
|
|
glClearDepthf( _clearDepth);
|
|
|
|
#endif
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2009-05-18 23:46:02 +08:00
|
|
|
glDepthMask ( GL_TRUE );
|
|
|
|
state.haveAppliedAttribute( osg::StateAttribute::DEPTH );
|
|
|
|
}
|
2001-09-20 05:19:47 +08:00
|
|
|
|
|
|
|
if (_clearMask & GL_STENCIL_BUFFER_BIT)
|
2009-05-18 23:46:02 +08:00
|
|
|
{
|
2001-09-20 05:19:47 +08:00
|
|
|
glClearStencil( _clearStencil);
|
2009-05-27 20:11:41 +08:00
|
|
|
glStencilMask ( ~0u );
|
2009-05-18 23:46:02 +08:00
|
|
|
state.haveAppliedAttribute( osg::StateAttribute::STENCIL );
|
|
|
|
}
|
2001-09-20 05:19:47 +08:00
|
|
|
|
2009-11-04 00:34:54 +08:00
|
|
|
#if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GL3_AVAILABLE)
|
2009-10-29 04:31:57 +08:00
|
|
|
if (_clearMask & GL_ACCUM_BUFFER_BIT)
|
|
|
|
{
|
|
|
|
glClearAccum( _clearAccum[0], _clearAccum[1], _clearAccum[2], _clearAccum[3]);
|
|
|
|
}
|
|
|
|
#endif
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2001-09-20 05:19:47 +08:00
|
|
|
|
|
|
|
glClear( _clearMask );
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2009-10-29 04:31:57 +08:00
|
|
|
#ifdef USE_SCISSOR_TEST
|
|
|
|
glDisable( GL_SCISSOR_TEST );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef OSG_GL_MATRICES_AVAILABLE
|
|
|
|
glMatrixMode( GL_MODELVIEW );
|
|
|
|
glLoadIdentity();
|
2012-03-22 01:36:20 +08:00
|
|
|
#endif
|
2001-09-20 05:19:47 +08:00
|
|
|
|
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.
|
2006-09-19 04:54:48 +08:00
|
|
|
RenderBin::drawImplementation(renderInfo,previous);
|
2001-09-20 05:19:47 +08:00
|
|
|
|
2006-07-19 04:17:31 +08:00
|
|
|
state.apply();
|
2007-07-15 01:07:59 +08:00
|
|
|
|
2001-09-20 05:19:47 +08:00
|
|
|
}
|
2005-06-15 04:51:35 +08:00
|
|
|
|
2006-09-19 04:54:48 +08:00
|
|
|
void RenderStage::drawPostRenderStages(osg::RenderInfo& renderInfo,RenderLeaf*& previous)
|
2005-06-15 04:51:35 +08:00
|
|
|
{
|
|
|
|
if (_postRenderList.empty()) return;
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2005-06-15 04:51:35 +08:00
|
|
|
//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)
|
|
|
|
{
|
2006-09-19 04:54:48 +08:00
|
|
|
itr->second->draw(renderInfo,previous);
|
2005-06-15 04:51:35 +08:00
|
|
|
}
|
|
|
|
//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
|
2005-12-16 01:14:40 +08:00
|
|
|
bool RenderStage::getStats(Statistics& stats) const
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
2005-12-16 01:14:40 +08:00
|
|
|
bool statsCollected = false;
|
|
|
|
|
|
|
|
for(RenderStageList::const_iterator pre_itr = _preRenderList.begin();
|
|
|
|
pre_itr != _preRenderList.end();
|
|
|
|
++pre_itr)
|
|
|
|
{
|
2006-09-04 21:15:08 +08:00
|
|
|
if (pre_itr->second->getStats(stats))
|
2005-12-16 01:14:40 +08:00
|
|
|
{
|
|
|
|
statsCollected = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for(RenderStageList::const_iterator post_itr = _postRenderList.begin();
|
|
|
|
post_itr != _postRenderList.end();
|
|
|
|
++post_itr)
|
|
|
|
{
|
2006-09-04 21:15:08 +08:00
|
|
|
if (post_itr->second->getStats(stats))
|
2005-12-16 01:14:40 +08:00
|
|
|
{
|
|
|
|
statsCollected = true;
|
|
|
|
}
|
|
|
|
}
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2005-12-16 01:14:40 +08:00
|
|
|
if (RenderBin::getStats(stats))
|
2002-05-02 08:14:40 +08:00
|
|
|
{
|
2005-12-16 01:14:40 +08:00
|
|
|
statsCollected = true;
|
2002-05-02 08:14:40 +08:00
|
|
|
}
|
2005-12-16 01:14:40 +08:00
|
|
|
return statsCollected;
|
2001-09-20 05:19:47 +08:00
|
|
|
}
|
2006-11-27 19:25:40 +08:00
|
|
|
|
2006-11-27 22:52:07 +08:00
|
|
|
void RenderStage::attach(osg::Camera::BufferComponent buffer, osg::Image* image)
|
2006-11-27 19:25:40 +08:00
|
|
|
{
|
|
|
|
_bufferAttachmentMap[buffer]._image = image;
|
|
|
|
}
|
2007-01-30 06:44:29 +08:00
|
|
|
|
|
|
|
unsigned int RenderStage::computeNumberOfDynamicRenderLeaves() const
|
|
|
|
{
|
|
|
|
unsigned int count = 0;
|
|
|
|
|
|
|
|
for(RenderStageList::const_iterator pre_itr = _preRenderList.begin();
|
|
|
|
pre_itr != _preRenderList.end();
|
|
|
|
++pre_itr)
|
|
|
|
{
|
|
|
|
count += pre_itr->second->computeNumberOfDynamicRenderLeaves();
|
|
|
|
}
|
|
|
|
|
|
|
|
count += RenderBin::computeNumberOfDynamicRenderLeaves();
|
|
|
|
|
|
|
|
for(RenderStageList::const_iterator post_itr = _postRenderList.begin();
|
|
|
|
post_itr != _postRenderList.end();
|
|
|
|
++post_itr)
|
|
|
|
{
|
|
|
|
count += post_itr->second->computeNumberOfDynamicRenderLeaves();
|
|
|
|
}
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2007-01-30 06:44:29 +08:00
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2008-06-18 22:09:11 +08:00
|
|
|
|
2009-06-06 03:05:37 +08:00
|
|
|
void RenderStage::setMultisampleResolveFramebufferObject(osg::FrameBufferObject* fbo)
|
2008-06-18 22:09:11 +08:00
|
|
|
{
|
|
|
|
if (fbo && fbo->isMultisample())
|
|
|
|
{
|
2010-05-28 23:51:00 +08:00
|
|
|
OSG_WARN << "Resolve framebuffer must not be"
|
2008-06-18 22:09:11 +08:00
|
|
|
" multisampled." << std::endl;
|
|
|
|
}
|
|
|
|
_resolveFbo = fbo;
|
|
|
|
}
|
2009-06-06 03:05:37 +08:00
|
|
|
|
|
|
|
void RenderStage::collateReferencesToDependentCameras()
|
|
|
|
{
|
|
|
|
_dependentCameras.clear();
|
|
|
|
|
|
|
|
for(RenderStageList::iterator itr = _preRenderList.begin();
|
|
|
|
itr != _preRenderList.end();
|
|
|
|
++itr)
|
|
|
|
{
|
|
|
|
itr->second->collateReferencesToDependentCameras();
|
|
|
|
osg::Camera* camera = itr->second->getCamera();
|
|
|
|
if (camera) _dependentCameras.push_back(camera);
|
|
|
|
}
|
|
|
|
|
|
|
|
for(RenderStageList::iterator itr = _postRenderList.begin();
|
|
|
|
itr != _postRenderList.end();
|
|
|
|
++itr)
|
|
|
|
{
|
|
|
|
itr->second->collateReferencesToDependentCameras();
|
|
|
|
osg::Camera* camera = itr->second->getCamera();
|
|
|
|
if (camera) _dependentCameras.push_back(camera);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderStage::clearReferencesToDependentCameras()
|
|
|
|
{
|
|
|
|
for(RenderStageList::iterator itr = _preRenderList.begin();
|
|
|
|
itr != _preRenderList.end();
|
|
|
|
++itr)
|
|
|
|
{
|
2015-06-19 17:51:30 +08:00
|
|
|
itr->second->clearReferencesToDependentCameras();
|
2009-06-06 03:05:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
for(RenderStageList::iterator itr = _postRenderList.begin();
|
|
|
|
itr != _postRenderList.end();
|
|
|
|
++itr)
|
|
|
|
{
|
2015-06-19 17:51:30 +08:00
|
|
|
itr->second->clearReferencesToDependentCameras();
|
2009-06-06 03:05:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
_dependentCameras.clear();
|
|
|
|
}
|
2011-04-20 19:45:01 +08:00
|
|
|
|
|
|
|
void RenderStage::releaseGLObjects(osg::State* state) const
|
|
|
|
{
|
|
|
|
RenderBin::releaseGLObjects(state);
|
|
|
|
|
|
|
|
for(RenderStageList::const_iterator itr = _preRenderList.begin();
|
|
|
|
itr != _preRenderList.end();
|
|
|
|
++itr)
|
|
|
|
{
|
|
|
|
itr->second->releaseGLObjects(state);
|
|
|
|
}
|
|
|
|
|
|
|
|
for(RenderStageList::const_iterator itr = _postRenderList.begin();
|
|
|
|
itr != _postRenderList.end();
|
|
|
|
++itr)
|
|
|
|
{
|
|
|
|
itr->second->releaseGLObjects(state);
|
|
|
|
}
|
|
|
|
|
|
|
|
for(Cameras::const_iterator itr = _dependentCameras.begin();
|
|
|
|
itr != _dependentCameras.end();
|
|
|
|
++itr)
|
|
|
|
{
|
|
|
|
(*itr)->releaseGLObjects(state);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_texture.valid()) _texture->releaseGLObjects(state);
|
|
|
|
|
|
|
|
if (_fbo.valid()) _fbo->releaseGLObjects(state);
|
|
|
|
if (_resolveFbo.valid()) _resolveFbo->releaseGLObjects(state);
|
|
|
|
if (_graphicsContext.valid()) _graphicsContext->releaseGLObjects(state);
|
|
|
|
}
|