|
|
|
#include "rtt.hpp"
|
|
|
|
#include "util.hpp"
|
|
|
|
|
|
|
|
#include <osg/Node>
|
|
|
|
#include <osg/NodeVisitor>
|
|
|
|
#include <osg/Texture2D>
|
|
|
|
#include <osgUtil/CullVisitor>
|
|
|
|
|
|
|
|
#include <components/sceneutil/nodecallback.hpp>
|
|
|
|
#include <components/settings/settings.hpp>
|
|
|
|
#include <components/sceneutil/depth.hpp>
|
|
|
|
|
|
|
|
namespace SceneUtil
|
|
|
|
{
|
|
|
|
class CullCallback : public SceneUtil::NodeCallback<CullCallback, RTTNode*, osgUtil::CullVisitor*>
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
void operator()(RTTNode* node, osgUtil::CullVisitor* cv)
|
|
|
|
{
|
|
|
|
node->cull(cv);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
RTTNode::RTTNode(uint32_t textureWidth, uint32_t textureHeight, int renderOrderNum, bool doPerViewMapping)
|
|
|
|
: mTextureWidth(textureWidth)
|
|
|
|
, mTextureHeight(textureHeight)
|
|
|
|
, mRenderOrderNum(renderOrderNum)
|
|
|
|
, mDoPerViewMapping(doPerViewMapping)
|
|
|
|
{
|
|
|
|
addCullCallback(new CullCallback);
|
|
|
|
setCullingActive(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
RTTNode::~RTTNode()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void RTTNode::cull(osgUtil::CullVisitor* cv)
|
|
|
|
{
|
|
|
|
auto* vdd = getViewDependentData(cv);
|
|
|
|
apply(vdd->mCamera);
|
|
|
|
vdd->mCamera->accept(*cv);
|
|
|
|
}
|
|
|
|
|
|
|
|
osg::Texture* RTTNode::getColorTexture(osgUtil::CullVisitor* cv)
|
|
|
|
{
|
|
|
|
return getViewDependentData(cv)->mCamera->getBufferAttachmentMap()[osg::Camera::COLOR_BUFFER]._texture;
|
|
|
|
}
|
|
|
|
|
|
|
|
osg::Texture* RTTNode::getDepthTexture(osgUtil::CullVisitor* cv)
|
|
|
|
{
|
|
|
|
return getViewDependentData(cv)->mCamera->getBufferAttachmentMap()[osg::Camera::PACKED_DEPTH_STENCIL_BUFFER]._texture;
|
|
|
|
}
|
|
|
|
|
|
|
|
RTTNode::ViewDependentData* RTTNode::getViewDependentData(osgUtil::CullVisitor* cv)
|
|
|
|
{
|
|
|
|
if (!mDoPerViewMapping)
|
|
|
|
// Always setting it to null is an easy way to disable per-view mapping when mDoPerViewMapping is false.
|
|
|
|
// This is safe since the visitor is never dereferenced.
|
|
|
|
cv = nullptr;
|
|
|
|
|
|
|
|
if (mViewDependentDataMap.count(cv) == 0)
|
|
|
|
{
|
|
|
|
auto camera = new osg::Camera();
|
|
|
|
mViewDependentDataMap[cv].reset(new ViewDependentData);
|
|
|
|
mViewDependentDataMap[cv]->mCamera = camera;
|
|
|
|
|
|
|
|
camera->setRenderOrder(osg::Camera::PRE_RENDER, mRenderOrderNum);
|
|
|
|
camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
|
|
|
camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
|
|
|
|
camera->setViewport(0, 0, mTextureWidth, mTextureHeight);
|
|
|
|
SceneUtil::setCameraClearDepth(camera);
|
|
|
|
|
|
|
|
setDefaults(mViewDependentDataMap[cv]->mCamera.get());
|
|
|
|
|
|
|
|
// Create any buffer attachments not added in setDefaults
|
|
|
|
if (camera->getBufferAttachmentMap().count(osg::Camera::COLOR_BUFFER) == 0)
|
|
|
|
{
|
|
|
|
auto colorBuffer = new osg::Texture2D;
|
|
|
|
colorBuffer->setTextureSize(mTextureWidth, mTextureHeight);
|
|
|
|
colorBuffer->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
|
|
|
|
colorBuffer->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
|
|
|
|
colorBuffer->setInternalFormat(GL_RGB);
|
|
|
|
colorBuffer->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
|
|
|
|
colorBuffer->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
|
|
|
|
camera->attach(osg::Camera::COLOR_BUFFER, colorBuffer);
|
|
|
|
SceneUtil::attachAlphaToCoverageFriendlyFramebufferToCamera(camera, osg::Camera::COLOR_BUFFER, colorBuffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (camera->getBufferAttachmentMap().count(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER) == 0)
|
|
|
|
{
|
|
|
|
auto depthBuffer = new osg::Texture2D;
|
|
|
|
depthBuffer->setTextureSize(mTextureWidth, mTextureHeight);
|
|
|
|
depthBuffer->setSourceFormat(GL_DEPTH_STENCIL_EXT);
|
|
|
|
depthBuffer->setInternalFormat(GL_DEPTH24_STENCIL8_EXT);
|
|
|
|
depthBuffer->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
|
|
|
|
depthBuffer->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
|
|
|
|
depthBuffer->setSourceType(GL_UNSIGNED_INT_24_8_EXT);
|
|
|
|
depthBuffer->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
|
|
|
|
depthBuffer->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
|
|
|
|
camera->attach(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER, depthBuffer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return mViewDependentDataMap[cv].get();
|
|
|
|
}
|
|
|
|
}
|