Work on the RenderToTexture usage of the new osg::CameraNode. Both osghud

and osgprerender now ported across to osg::CameraNode.
This commit is contained in:
Robert Osfield 2005-06-14 20:51:35 +00:00
parent 868d381528
commit 71122ff38f
9 changed files with 507 additions and 195 deletions

View File

@ -22,6 +22,7 @@
#include <osg/Projection>
#include <osg/PolygonOffset>
#include <osg/MatrixTransform>
#include <osg/CameraNode>
#include <osgText/Text>
@ -36,17 +37,6 @@ osg::Node* createHUD()
osg::StateSet* stateset = geode->getOrCreateStateSet();
stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
#if 0
// to ensure the hud appears on top we can either use osg::Depth to force the
// depth fragments to be placed at the front of the screen.
stateset->setAttribute(new osg::Depth(osg::Depth::LESS,0.0,0.0001));
#else
// or disable depth test, and make sure that the hud is drawn after everything
// else so that it always appears ontop.
stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
stateset->setRenderBinDetails(11,"RenderBin");
#endif
osg::Vec3 position(150.0f,800.0f,0.0f);
osg::Vec3 delta(0.0f,-120.0f,0.0f);
@ -146,6 +136,42 @@ osg::Node* createHUD()
geode->addDrawable(geom);
}
#if 1
osg::CameraNode* camera = new osg::CameraNode;
// set the projection matrix
camera->setProjectionMatrix(osg::Matrix::ortho2D(0,1280,0,1024));
// set the view matrix
camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
camera->setViewMatrix(osg::Matrix::identity());
// only clear the depth buffer
camera->setClearMask(GL_DEPTH_BUFFER_BIT);
// draw subgraph after main camera view.
camera->setRenderOrder(osg::CameraNode::POST_RENDER);
camera->addChild(geode);
return camera;
#else
#if 0
// to ensure the hud appears on top we can either use osg::Depth to force the
// depth fragments to be placed at the front of the screen.
stateset->setAttribute(new osg::Depth(osg::Depth::LESS,0.0,0.0001));
#else
// or disable depth test, and make sure that the hud is drawn after everything
// else so that it always appears ontop.
stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
stateset->setRenderBinDetails(11,"RenderBin");
#endif
// create the hud.
osg::MatrixTransform* modelview_abs = new osg::MatrixTransform;
modelview_abs->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
@ -157,6 +183,7 @@ osg::Node* createHUD()
projection->addChild(modelview_abs);
return projection;
#endif
}

View File

@ -23,6 +23,10 @@
#include <osgProducer/Viewer>
#define USE_CAMERA_NODE
#ifndef USE_CAMERA_NODE
class MyUpdateCallback : public osg::NodeCallback
{
public:
@ -42,6 +46,7 @@ class MyUpdateCallback : public osg::NodeCallback
osg::ref_ptr<osg::Node> _subgraph;
};
class MyCullCallback : public osg::NodeCallback
{
public:
@ -197,6 +202,7 @@ void MyCullCallback::doPreRender(osg::Node&, osgUtil::CullVisitor& cv)
if (_image.valid()) rtts->setImage(_image.get());
}
#endif
// call back which cretes a deformation field to oscilate the model.
class MyGeometryCallback :
@ -352,6 +358,8 @@ osg::Node* createPreRenderSubGraph(osg::Node* subgraph)
osg::Geode* geode = new osg::Geode();
geode->addDrawable(polyGeom);
#ifndef USE_CAMERA_NODE
osg::Group* parent = new osg::Group;
parent->setUpdateCallback(new MyUpdateCallback(subgraph));
@ -361,6 +369,63 @@ osg::Node* createPreRenderSubGraph(osg::Node* subgraph)
parent->addChild(geode);
return parent;
#else
osg::CameraNode* camera = new osg::CameraNode;
// set up the background color and clear mask.
camera->setClearColor(osg::Vec4(0.1f,0.1f,0.3f,1.0f));
camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
const osg::BoundingSphere& bs = subgraph->getBound();
if (!bs.valid())
{
return subgraph;
}
float znear = 1.0f*bs.radius();
float zfar = 3.0f*bs.radius();
// 2:1 aspect ratio as per flag geomtry below.
float proj_top = 0.25f*znear;
float proj_right = 0.5f*znear;
znear *= 0.9f;
zfar *= 1.1f;
// set up projection.
camera->setProjectionMatrixAsFrustum(-proj_right,proj_right,-proj_top,proj_top,znear,zfar);
// set view
camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
camera->setViewMatrixAsLookAt(bs.center()+osg::Vec3(0.0f,2.0f,0.0f)*bs.radius(),bs.center(),osg::Vec3(0.0f,0.0f,1.0f));
// set viewport
camera->setViewport(0,0,1024,512);
camera->getOrCreateStateSet()->setAttribute(camera->getViewport());
// set the camera to render before the main camera.
camera->setRenderOrder(osg::CameraNode::PRE_RENDER);
camera->attach(osg::CameraNode::COLOR_BUFFER,texture);
// add subgraph to render
camera->addChild(subgraph);
// create a group to contain the flag and the pre rendering camera.
osg::Group* parent = new osg::Group;
parent->addChild(camera);
parent->addChild(geode);
return parent;
#endif
}
int main( int argc, char **argv )

View File

@ -16,12 +16,15 @@
#include <osg/Transform>
#include <osg/Viewport>
#include <osg/CullSettings>
#include <osg/Texture>
#include <osg/Image>
namespace osg {
/** CameraNode - is a subclass of Transform which represents encapsulates the settings of a Camera.
*/
class OSG_EXPORT CameraNode : public Transform
class OSG_EXPORT CameraNode : public Transform, public CullSettings
{
public :
@ -34,20 +37,6 @@ class OSG_EXPORT CameraNode : public Transform
META_Node(osg, CameraNode);
/** Sets the clear color. */
inline void setClearColor(const Vec4& color) { _clearColor = color; }
/** Returns the clear color. */
inline const Vec4& getClearColor() const { return _clearColor; }
/** Set the clear mask used in glClear(..).
* Defaults to GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT. */
inline void setClearMask(GLbitfield mask) { _clearMask = mask; }
/** Get the clear mask.*/
inline GLbitfield getClearMask() const { return _clearMask; }
/** Set the viewport of the scene view to use specified osg::Viewport. */
void setViewport(osg::Viewport* viewport)
@ -151,7 +140,76 @@ class OSG_EXPORT CameraNode : public Transform
/** Sets the clear color. */
inline void setClearColor(const Vec4& color) { _clearColor = color; }
/** Returns the clear color. */
inline const Vec4& getClearColor() const { return _clearColor; }
/** Set the clear mask used in glClear(..).
* Defaults to GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT. */
inline void setClearMask(GLbitfield mask) { _clearMask = mask; }
/** Get the clear mask.*/
inline GLbitfield getClearMask() const { return _clearMask; }
enum RenderOrder
{
PRE_RENDER,
NESTED_RENDER,
POST_RENDER
};
/** Set the rendering order of this camera's subgraph relative to any camera that this subgraph is nested within.
* For rendering to a texture, one typically uses PRE_RENDER.
* For Head Up Displays, one would typically use POST_RENDER.*/
void setRenderOrder(RenderOrder order) { _renderOrder = order; }
/** Get the rendering order of this camera's subgraph relative to any camera that this subgraph is nested within.*/
RenderOrder getRenderOrder() const { return _renderOrder; }
enum RenderTargetImplementation
{
FRAME_BUFFER_OBJECT,
PIXEL_BUFFER,
FRAME_BUFFER
};
void setRenderTargetImplmentation(RenderTargetImplementation impl) { _renderTargetImplementation = impl; }
RenderTargetImplementation getRenderTargetImplmentation() const { return _renderTargetImplementation; }
enum BufferComponent
{
COLOR_BUFFER,
DEPTH_BUFFER,
STENCIL_BUFFER
};
void attach(BufferComponent buffer, GLenum internalFormat);
void attach(BufferComponent buffer, osg::Texture* texture, unsigned int face=0);
void attach(BufferComponent buffer, osg::Image* image);
void detach(BufferComponent buffer);
struct Attachment
{
GLenum _internalFormat;
ref_ptr<Image> _image;
ref_ptr<Texture> _texture;
unsigned int _face;
};
typedef std::map< BufferComponent, Attachment> BufferAttachmentMap;
BufferAttachmentMap& getBufferAttachmentMap() { return _bufferAttachmentMap; }
const BufferAttachmentMap& getBufferAttachmentMap() const { return _bufferAttachmentMap; }
public:
/** Transform method that must be defined to provide generic interface for scene graph traversals.*/
@ -170,6 +228,11 @@ class OSG_EXPORT CameraNode : public Transform
Matrixd _projectionMatrix;
Matrixd _viewMatrix;
RenderOrder _renderOrder;
RenderTargetImplementation _renderTargetImplementation;
BufferAttachmentMap _bufferAttachmentMap;
};
}

View File

@ -25,6 +25,7 @@
#include <osg/StateSet>
#include <osg/State>
#include <osg/ClearNode>
#include <osg/CameraNode>
#include <osg/Notify>
#include <osg/CullStack>
@ -75,6 +76,7 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor, public osg::CullStac
virtual void apply(osg::Switch& node);
virtual void apply(osg::LOD& node);
virtual void apply(osg::ClearNode& node);
virtual void apply(osg::CameraNode& node);
virtual void apply(osg::OccluderNode& node);
void setClearNode(const osg::ClearNode* earthSky) { _clearNode = earthSky; }

View File

@ -127,9 +127,14 @@ class OSGUTIL_EXPORT RenderStage : public RenderBin
virtual void draw(osg::State& state,RenderLeaf*& previous);
virtual void drawPostRenderStages(osg::State& state,RenderLeaf*& previous);
virtual void drawImplementation(osg::State& state,RenderLeaf*& previous);
void addToDependencyList(RenderStage* rs);
void addToDependencyList(RenderStage* rs) { addPreRenderStage(rs); }
void addPreRenderStage(RenderStage* rs);
void addPostRenderStage(RenderStage* rs);
/** Extract stats for current draw list. */
bool getStats(Statistics* primStats);
@ -138,10 +143,11 @@ class OSGUTIL_EXPORT RenderStage : public RenderBin
virtual ~RenderStage();
typedef std::vector< osg::ref_ptr<RenderStage> > DependencyList;
typedef std::vector< osg::ref_ptr<RenderStage> > RenderStageList;
bool _stageDrawnThisFrame;
DependencyList _dependencyList;
RenderStageList _preRenderList;
RenderStageList _postRenderList;
// viewport x,y,width,height.
osg::ref_ptr<osg::Viewport> _viewport;

View File

@ -18,17 +18,24 @@ using namespace osg;
CameraNode::CameraNode():
_clearColor(osg::Vec4(0.0f,0.0f,0.0f,1.0f)),
_clearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
_clearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT),
_renderOrder(POST_RENDER),
_renderTargetImplementation(FRAME_BUFFER)
{
}
CameraNode::CameraNode(const CameraNode& camera,const CopyOp& copyop):
Transform(camera,copyop),
CullSettings(camera),
_clearColor(camera._clearColor),
_clearMask(camera._clearMask),
_viewport(camera._viewport),
_projectionMatrix(camera._projectionMatrix),
_viewMatrix(camera._viewMatrix)
_viewMatrix(camera._viewMatrix),
_renderOrder(camera._renderOrder),
_renderTargetImplementation(camera._renderTargetImplementation),
_bufferAttachmentMap(camera._bufferAttachmentMap)
{
}
@ -109,6 +116,29 @@ void CameraNode::getViewMatrixAsLookAt(Vec3& eye,Vec3& center,Vec3& up,float loo
_viewMatrix.getLookAt(eye,center,up,lookDistance);
}
void CameraNode::attach(BufferComponent buffer, GLenum internalFormat)
{
_bufferAttachmentMap[buffer]._internalFormat = internalFormat;
}
void CameraNode::attach(BufferComponent buffer, osg::Texture* texture, unsigned int face)
{
_bufferAttachmentMap[buffer]._texture = texture;
_bufferAttachmentMap[buffer]._face = face;
}
void CameraNode::attach(BufferComponent buffer, osg::Image* image)
{
_bufferAttachmentMap[buffer]._image = image;
}
void CameraNode::detach(BufferComponent buffer)
{
_bufferAttachmentMap.erase(buffer);
}
bool CameraNode::computeLocalToWorldMatrix(Matrix& matrix,NodeVisitor*) const
{
if (_referenceFrame==RELATIVE_RF)

View File

@ -1023,6 +1023,100 @@ void CullVisitor::apply(osg::ClearNode& node)
}
void CullVisitor::apply(osg::CameraNode& camera)
{
// push the node's state.
StateSet* node_state = camera.getStateSet();
if (node_state) pushStateSet(node_state);
// use render to texture stage.
{
// create the render to texture stage.
osg::ref_ptr<osgUtil::RenderToTextureStage> rtts = new osgUtil::RenderToTextureStage;
// set up lighting.
// currently ignore lights in the scene graph itself..
// will do later.
osgUtil::RenderStage* previous_stage = getCurrentRenderBin()->getStage();
// set up the background color and clear mask.
rtts->setClearColor(camera.getClearColor());
rtts->setClearMask(camera.getClearMask());
// set up the viewport.
rtts->setViewport( camera.getViewport()!=0 ? camera.getViewport() : previous_stage->getViewport());
// set up to charge the same RenderStageLighting is the parent previous stage.
rtts->setRenderStageLighting(previous_stage->getRenderStageLighting());
// record the render bin, to be restored after creation
// of the render to text
osgUtil::RenderBin* previousRenderBin = getCurrentRenderBin();
// set the current renderbin to be the newly created stage.
setCurrentRenderBin(rtts.get());
pushProjectionMatrix(new osg::RefMatrix(camera.getProjectionMatrix()));
pushModelViewMatrix(new osg::RefMatrix(camera.getViewMatrix()));
// traverse the subgraph
{
handle_cull_callbacks_and_traverse(camera);
}
// restore the previous model view matrix.
popModelViewMatrix();
// restore the previous model view matrix.
popProjectionMatrix();
// restore the previous renderbin.
setCurrentRenderBin(previousRenderBin);
if (rtts->getRenderGraphList().size()==0 && rtts->getRenderBinList().size()==0)
{
// getting to this point means that all the subgraph has been
// culled by small feature culling or is beyond LOD ranges.
}
// and the render to texture stage to the current stages
// dependancy list.
switch(camera.getRenderOrder())
{
case osg::CameraNode::PRE_RENDER :
getCurrentRenderBin()->getStage()->addPreRenderStage(rtts.get());
break;
case osg::CameraNode::NESTED_RENDER :
getCurrentRenderBin()->getStage()->addPostRenderStage(rtts.get());
break;
case osg::CameraNode::POST_RENDER :
getCurrentRenderBin()->getStage()->addPostRenderStage(rtts.get());
break;
}
osg::CameraNode::BufferAttachmentMap& bufferAttachements = camera.getBufferAttachmentMap();
for(osg::CameraNode::BufferAttachmentMap::iterator itr = bufferAttachements.begin();
itr != bufferAttachements.end();
++itr)
{
// if one exist attach texture to the RenderToTextureStage.
osg::Texture2D* texture2D = dynamic_cast<osg::Texture2D*>(itr->second._texture.get());
if (texture2D) rtts->setTexture(texture2D);
// if one exist attach image to the RenderToTextureStage.
if (itr->second._image.valid()) rtts->setImage(itr->second._image.get());
}
}
// pop the node's state off the render graph stack.
if (node_state) popStateSet();
}
void CullVisitor::apply(osg::OccluderNode& node)
{
// need to check if occlusion node is in the occluder

View File

@ -322,7 +322,7 @@ RenderBin* RenderBin::find_or_insert(int binNum,const std::string& binName)
rs->_binNum = binNum;
rs->_parent = NULL;
rs->_stage = rs;
_stage->addToDependencyList(rs);
_stage->addPreRenderStage(rs);
}
else
{

View File

@ -56,7 +56,8 @@ RenderStage::RenderStage(SortMode mode):
RenderStage::RenderStage(const RenderStage& rhs,const osg::CopyOp& copyop):
RenderBin(rhs,copyop),
_stageDrawnThisFrame(false),
_dependencyList(rhs._dependencyList),
_preRenderList(rhs._preRenderList),
_postRenderList(rhs._postRenderList),
_viewport(rhs._viewport),
_clearMask(rhs._clearMask),
_colorMask(rhs._colorMask),
@ -77,7 +78,7 @@ RenderStage::~RenderStage()
void RenderStage::reset()
{
_dependencyList.clear();
_preRenderList.clear();
_stageDrawnThisFrame = false;
if (_renderStageLighting.valid()) _renderStageLighting->reset();
@ -85,18 +86,23 @@ void RenderStage::reset()
RenderBin::reset();
}
void RenderStage::addToDependencyList(RenderStage* rs)
void RenderStage::addPreRenderStage(RenderStage* rs)
{
if (rs) _dependencyList.push_back(rs);
if (rs) _preRenderList.push_back(rs);
}
void RenderStage::addPostRenderStage(RenderStage* rs)
{
if (rs) _postRenderList.push_back(rs);
}
void RenderStage::drawPreRenderStages(osg::State& state,RenderLeaf*& previous)
{
if (_dependencyList.empty()) return;
if (_preRenderList.empty()) return;
//cout << "Drawing prerendering stages "<<this<< " "<<_viewport->x()<<","<< _viewport->y()<<","<< _viewport->width()<<","<< _viewport->height()<<std::endl;
for(DependencyList::iterator itr=_dependencyList.begin();
itr!=_dependencyList.end();
for(RenderStageList::iterator itr=_preRenderList.begin();
itr!=_preRenderList.end();
++itr)
{
(*itr)->draw(state,previous);
@ -115,6 +121,10 @@ void RenderStage::draw(osg::State& state,RenderLeaf*& previous)
//drawPreRenderStages(state,previous);
RenderBin::draw(state,previous);
// place the post draw here temprorarily while we figure out how
// best to do SceneView.
drawPostRenderStages(state,previous);
}
void RenderStage::drawImplementation(osg::State& state,RenderLeaf*& previous)
@ -182,6 +192,21 @@ void RenderStage::drawImplementation(osg::State& state,RenderLeaf*& previous)
}
}
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;
}
// Statistics features
bool RenderStage::getStats(Statistics* primStats)
{