mirror of https://github.com/OpenMW/openmw.git
Stereo friendly StateSetUpdater
(cherry picked from commit 496b3aef88b8fd867dcdd23a6ca43144573b1b2f) Stereo friendly water (cherry picked from commit 0e22c55e48a7f965367d3d430c1bef5357b22748) Option to disable per view mapping. Include memory header De-hardcode settings and buffers. formatting error Update water.cpp (whitespace) Update water.cpp (more whitespace) include render order c array -> c++ arraydont-compose-content
parent
0433a53883
commit
41c08b1c3b
@ -0,0 +1,110 @@
|
|||||||
|
#include "rtt.hpp"
|
||||||
|
#include "util.hpp"
|
||||||
|
|
||||||
|
#include <osg/Node>
|
||||||
|
#include <osg/NodeVisitor>
|
||||||
|
#include <osg/Texture2D>
|
||||||
|
#include <osgUtil/CullVisitor>
|
||||||
|
|
||||||
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
|
namespace SceneUtil
|
||||||
|
{
|
||||||
|
// RTTNode's cull callback
|
||||||
|
class CullCallback : public osg::NodeCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CullCallback(RTTNode* group)
|
||||||
|
: mGroup(group) {}
|
||||||
|
|
||||||
|
void operator()(osg::Node* node, osg::NodeVisitor* nv) override
|
||||||
|
{
|
||||||
|
osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(nv);
|
||||||
|
mGroup->cull(cv);
|
||||||
|
}
|
||||||
|
RTTNode* mGroup;
|
||||||
|
};
|
||||||
|
|
||||||
|
RTTNode::RTTNode(uint32_t textureWidth, uint32_t textureHeight, int renderOrderNum, bool doPerViewMapping)
|
||||||
|
: mTextureWidth(textureWidth)
|
||||||
|
, mTextureHeight(textureHeight)
|
||||||
|
, mRenderOrderNum(renderOrderNum)
|
||||||
|
, mDoPerViewMapping(doPerViewMapping)
|
||||||
|
{
|
||||||
|
addCullCallback(new CullCallback(this));
|
||||||
|
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::DEPTH_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);
|
||||||
|
camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
|
||||||
|
camera->setViewport(0, 0, mTextureWidth, mTextureHeight);
|
||||||
|
|
||||||
|
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::DEPTH_BUFFER) == 0)
|
||||||
|
{
|
||||||
|
auto depthBuffer = new osg::Texture2D;
|
||||||
|
depthBuffer->setTextureSize(mTextureWidth, mTextureHeight);
|
||||||
|
depthBuffer->setSourceFormat(GL_DEPTH_COMPONENT);
|
||||||
|
depthBuffer->setInternalFormat(GL_DEPTH_COMPONENT24);
|
||||||
|
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);
|
||||||
|
depthBuffer->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
|
||||||
|
depthBuffer->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
|
||||||
|
camera->attach(osg::Camera::DEPTH_BUFFER, depthBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mViewDependentDataMap[cv].get();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
#ifndef OPENMW_RTT_H
|
||||||
|
#define OPENMW_RTT_H
|
||||||
|
|
||||||
|
#include <osg/Node>
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace osg
|
||||||
|
{
|
||||||
|
class Texture2D;
|
||||||
|
class Camera;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace osgUtil
|
||||||
|
{
|
||||||
|
class CullVisitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace SceneUtil
|
||||||
|
{
|
||||||
|
/// @brief Implements per-view RTT operations.
|
||||||
|
/// @par With a naive RTT implementation, subsequent views of multiple views will overwrite the results of the previous views, leading to
|
||||||
|
/// the results of the last view being broadcast to all views. An error in all cases where the RTT result depends on the view.
|
||||||
|
/// @par If using an RTTNode this is solved by mapping RTT operations to CullVisitors, which will be unique per view. This requires
|
||||||
|
/// instancing one camera per view, and traversing only the camera mapped to that CV during cull traversals.
|
||||||
|
/// @par Camera settings should be effectuated by overriding the setDefaults() and apply() methods, following a pattern similar to SceneUtil::StateSetUpdater
|
||||||
|
/// @par When using the RTT texture in your statesets, it is recommended to use SceneUtil::StateSetUpdater as a cull callback to handle this as the appropriate
|
||||||
|
/// textures can be retrieved during SceneUtil::StateSetUpdater::Apply()
|
||||||
|
/// @par For any of COLOR_BUFFER or DEPTH_BUFFER not added during setDefaults(), RTTNode will attach a default buffer. The default color buffer has an internal format of GL_RGB.
|
||||||
|
/// The default depth buffer has internal format GL_DEPTH_COMPONENT24, source format GL_DEPTH_COMPONENT, and source type GL_UNSIGNED_INT. Default wrap is CLAMP_TO_EDGE and filter LINEAR.
|
||||||
|
class RTTNode : public osg::Node
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RTTNode(uint32_t textureWidth, uint32_t textureHeight, int renderOrderNum, bool doPerViewMapping);
|
||||||
|
~RTTNode();
|
||||||
|
|
||||||
|
osg::Texture* getColorTexture(osgUtil::CullVisitor* cv);
|
||||||
|
|
||||||
|
osg::Texture* getDepthTexture(osgUtil::CullVisitor* cv);
|
||||||
|
|
||||||
|
|
||||||
|
/// Apply state - to override in derived classes
|
||||||
|
/// @note Due to the view mapping approach you *have* to apply all camera settings, even if they have not changed since the last frame.
|
||||||
|
virtual void setDefaults(osg::Camera* camera) {};
|
||||||
|
|
||||||
|
/// Set default settings - optionally override in derived classes
|
||||||
|
virtual void apply(osg::Camera* camera) {};
|
||||||
|
|
||||||
|
void cull(osgUtil::CullVisitor* cv);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct ViewDependentData
|
||||||
|
{
|
||||||
|
osg::ref_ptr<osg::Camera> mCamera;
|
||||||
|
};
|
||||||
|
|
||||||
|
ViewDependentData* getViewDependentData(osgUtil::CullVisitor* cv);
|
||||||
|
|
||||||
|
typedef std::map< osgUtil::CullVisitor*, std::unique_ptr<ViewDependentData> > ViewDependentDataMap;
|
||||||
|
ViewDependentDataMap mViewDependentDataMap;
|
||||||
|
uint32_t mTextureWidth;
|
||||||
|
uint32_t mTextureHeight;
|
||||||
|
int mRenderOrderNum;
|
||||||
|
bool mDoPerViewMapping;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
Loading…
Reference in New Issue