You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openmw/apps/openmw/mwrender/postprocessor.hpp

266 lines
6.8 KiB
C++

#ifndef OPENMW_MWRENDER_POSTPROCESSOR_H
#define OPENMW_MWRENDER_POSTPROCESSOR_H
#include <array>
#include <vector>
#include <string>
#include <unordered_map>
#include <osg/Texture2D>
#include <osg/Group>
#include <osg/FrameBufferObject>
#include <osg/Camera>
#include <osgViewer/Viewer>
#include <components/fx/stateupdater.hpp>
#include <components/fx/technique.hpp>
#include <components/debug/debuglog.hpp>
#include "pingpongcanvas.hpp"
#include "transparentpass.hpp"
#include <memory>
namespace osgViewer
{
class Viewer;
}
namespace Stereo
{
class MultiviewFramebuffer;
}
namespace VFS
{
class Manager;
}
namespace Shader
{
class ShaderManager;
}
namespace MWRender
{
class RenderingManager;
class PingPongCull;
class PingPongCanvas;
class TransparentDepthBinCallback;
class PostProcessor : public osg::Group
{
public:
using FBOArray = std::array<osg::ref_ptr<osg::FrameBufferObject>, 5>;
using TextureArray = std::array<osg::ref_ptr<osg::Texture>, 5>;
using TechniqueList = std::vector<std::shared_ptr<fx::Technique>>;
enum TextureIndex
{
Tex_Scene,
Tex_Scene_LDR,
Tex_Depth,
Tex_OpaqueDepth,
Tex_Normal
};
enum FBOIndex
{
FBO_Primary,
FBO_Multisample,
FBO_FirstPerson,
FBO_OpaqueDepth,
FBO_Intercept
};
enum TextureUnits
{
Unit_LastShader = 0,
Unit_LastPass,
Unit_Depth,
Unit_EyeAdaptation,
Unit_Normals,
Unit_NextFree
};
enum Status
{
Status_Error,
Status_Toggled,
Status_Unchanged
};
PostProcessor(RenderingManager& rendering, osgViewer::Viewer* viewer, osg::Group* rootNode, const VFS::Manager* vfs);
~PostProcessor();
void traverse(osg::NodeVisitor& nv) override;
osg::ref_ptr<osg::FrameBufferObject> getFbo(FBOIndex index, unsigned int frameId) { return mFbos[frameId][index]; }
osg::ref_ptr<osg::Texture> getTexture(TextureIndex index, unsigned int frameId) { return mTextures[frameId][index]; }
osg::ref_ptr<osg::FrameBufferObject> getPrimaryFbo(unsigned int frameId) { return mFbos[frameId][FBO_Multisample] ? mFbos[frameId][FBO_Multisample] : mFbos[frameId][FBO_Primary]; }
osg::ref_ptr<fx::StateUpdater> getStateUpdater() { return mStateUpdater; }
const TechniqueList& getTechniques() { return mTechniques; }
const TechniqueList& getTemplates() const { return mTemplates; }
osg::ref_ptr<PingPongCanvas> getCanvas() { return mPingPongCanvas; }
const auto& getTechniqueMap() const { return mTechniqueFileMap; }
void resize();
Status enableTechnique(std::shared_ptr<fx::Technique> technique, std::optional<int> location = std::nullopt);
Status disableTechnique(std::shared_ptr<fx::Technique> technique, bool dirty = true);
bool getSupportsNormalsRT() const { return mNormalsSupported; }
template <class T>
void setUniform(std::shared_ptr<fx::Technique> technique, const std::string& name, const T& value)
{
if (!isEnabled())
return;
auto it = technique->findUniform(name);
if (it == technique->getUniformMap().end())
return;
if ((*it)->mStatic)
{
Log(Debug::Warning) << "Attempting to set a configration variable [" << name << "] as a uniform";
return;
}
(*it)->setValue(value);
}
std::optional<size_t> getUniformSize(std::shared_ptr<fx::Technique> technique, const std::string& name)
{
auto it = technique->findUniform(name);
if (it == technique->getUniformMap().end())
return std::nullopt;
return (*it)->getNumElements();
}
bool isTechniqueEnabled(const std::shared_ptr<fx::Technique>& technique) const;
void setExteriorFlag(bool exterior) { mExteriorFlag = exterior; }
void setUnderwaterFlag(bool underwater) { mUnderwater = underwater; }
void toggleMode();
std::shared_ptr<fx::Technique> loadTechnique(const std::string& name, bool loadNextFrame=false);
bool isEnabled() const { return mUsePostProcessing && mEnabled; }
bool softParticlesEnabled() const {return mSoftParticles; }
bool getHDR() const { return mHDR; }
void disable();
void enable(bool usePostProcessing = true);
void setRenderTargetSize(int width, int height) { mWidth = width; mHeight = height; }
void disableDynamicShaders();
int renderWidth() const;
int renderHeight() const;
void triggerShaderReload();
bool mEnableLiveReload;
void loadChain();
void saveChain();
private:
void populateTechniqueFiles();
size_t frame() const { return mViewer->getFrameStamp()->getFrameNumber(); }
void createObjectsForFrame(size_t frameId);
void createTexturesAndCamera(size_t frameId);
void reloadMainPass(fx::Technique& technique);
void dirtyTechniques();
void update(size_t frameId);
void reloadIfRequired();
void updateLiveReload();
void cull(size_t frameId, osgUtil::CullVisitor* cv);
osg::ref_ptr<osg::Group> mRootNode;
osg::ref_ptr<osg::Camera> mHUDCamera;
std::array<TextureArray, 2> mTextures;
std::array<FBOArray, 2> mFbos;
TechniqueList mTechniques;
TechniqueList mTemplates;
TechniqueList mQueuedTemplates;
std::unordered_map<std::string, boost::filesystem::path> mTechniqueFileMap;
int mSamples;
bool mDirty;
size_t mDirtyFrameId;
RenderingManager& mRendering;
osgViewer::Viewer* mViewer;
const VFS::Manager* mVFS;
bool mTriggerShaderReload;
bool mReload;
bool mEnabled;
bool mUsePostProcessing;
bool mSoftParticles;
bool mDisableDepthPasses;
size_t mLastFrameNumber;
float mLastSimulationTime;
bool mExteriorFlag;
bool mUnderwater;
bool mHDR;
bool mNormals;
bool mPrevNormals;
bool mNormalsSupported;
bool mPassLights;
bool mPrevPassLights;
bool mUBO;
int mGLSLVersion;
osg::ref_ptr<fx::StateUpdater> mStateUpdater;
osg::ref_ptr<PingPongCull> mPingPongCull;
osg::ref_ptr<PingPongCanvas> mPingPongCanvas;
osg::ref_ptr<TransparentDepthBinCallback> mTransparentDepthPostPass;
int mWidth;
int mHeight;
fx::DispatchArray mTemplateData;
};
}
#endif