mirror of https://github.com/OpenMW/openmw.git
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.
146 lines
5.5 KiB
C++
146 lines
5.5 KiB
C++
#ifndef OPENMW_COMPONENTS_SHADERMANAGER_H
|
|
#define OPENMW_COMPONENTS_SHADERMANAGER_H
|
|
|
|
#include <array>
|
|
#include <map>
|
|
#include <memory>
|
|
#include <mutex>
|
|
#include <optional>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include <osg/ref_ptr>
|
|
|
|
#include <filesystem>
|
|
#include <osg/Program>
|
|
#include <osg/Shader>
|
|
|
|
namespace osgViewer
|
|
{
|
|
class Viewer;
|
|
}
|
|
|
|
namespace Shader
|
|
{
|
|
struct HotReloadManager;
|
|
/// @brief Reads shader template files and turns them into a concrete shader, based on a list of define's.
|
|
/// @par Shader templates can get the value of a define with the syntax @define.
|
|
class ShaderManager
|
|
{
|
|
public:
|
|
friend HotReloadManager;
|
|
ShaderManager();
|
|
~ShaderManager();
|
|
|
|
void setShaderPath(const std::filesystem::path& path);
|
|
|
|
typedef std::map<std::string, std::string> DefineMap;
|
|
|
|
/// Create or retrieve a shader instance.
|
|
/// @param templateName The path of the shader template.
|
|
/// @param defines Define values that can be retrieved by the shader template.
|
|
/// @param shaderType The type of shader (usually vertex or fragment shader).
|
|
/// @note May return nullptr on failure.
|
|
/// @note Thread safe.
|
|
osg::ref_ptr<osg::Shader> getShader(std::string templateName, const DefineMap& defines = {},
|
|
std::optional<osg::Shader::Type> type = std::nullopt);
|
|
|
|
osg::ref_ptr<osg::Program> getProgram(const std::string& templateName, const DefineMap& defines = {},
|
|
const osg::Program* programTemplate = nullptr);
|
|
|
|
osg::ref_ptr<osg::Program> getProgram(osg::ref_ptr<osg::Shader> vertexShader,
|
|
osg::ref_ptr<osg::Shader> fragmentShader, const osg::Program* programTemplate = nullptr);
|
|
|
|
const osg::Program* getProgramTemplate() const { return mProgramTemplate; }
|
|
void setProgramTemplate(const osg::Program* program) { mProgramTemplate = program; }
|
|
|
|
/// Clone an osg::Program including bindUniformBlocks that osg::Program::clone does not copy for some reason.
|
|
static osg::ref_ptr<osg::Program> cloneProgram(const osg::Program*);
|
|
|
|
/// Get (a copy of) the DefineMap used to construct all shaders
|
|
DefineMap getGlobalDefines();
|
|
|
|
/// Set the DefineMap used to construct all shaders
|
|
/// @param defines The DefineMap to use
|
|
/// @note This will change the source code for any shaders already created, potentially causing problems if
|
|
/// they're being used to render a frame. It is recommended that any associated Viewers have their threading
|
|
/// stopped while this function is running if any shaders are in use.
|
|
void setGlobalDefines(DefineMap& globalDefines);
|
|
|
|
void releaseGLObjects(osg::State* state);
|
|
|
|
bool createSourceFromTemplate(std::string& source, std::vector<std::string>& linkedShaderTemplateNames,
|
|
const std::string& templateName, const ShaderManager::DefineMap& defines);
|
|
|
|
void setMaxTextureUnits(int maxTextureUnits) { mMaxTextureUnits = maxTextureUnits; }
|
|
int getMaxTextureUnits() const { return mMaxTextureUnits; }
|
|
int getAvailableTextureUnits() const { return mMaxTextureUnits - mReservedTextureUnits; }
|
|
|
|
enum class Slot
|
|
{
|
|
OpaqueDepthTexture,
|
|
SkyTexture,
|
|
ShadowMaps,
|
|
SLOT_COUNT
|
|
};
|
|
|
|
int reserveGlobalTextureUnits(Slot slot, int count = 1);
|
|
|
|
void update(osgViewer::Viewer& viewer);
|
|
void setHotReloadEnabled(bool value);
|
|
void triggerShaderReload();
|
|
|
|
private:
|
|
void getLinkedShaders(osg::ref_ptr<osg::Shader> shader, const std::vector<std::string>& linkedShaderNames,
|
|
const DefineMap& defines);
|
|
void addLinkedShaders(osg::ref_ptr<osg::Shader> shader, osg::ref_ptr<osg::Program> program);
|
|
|
|
std::filesystem::path mPath;
|
|
|
|
DefineMap mGlobalDefines;
|
|
|
|
// <name, code>
|
|
typedef std::map<std::string, std::string> TemplateMap;
|
|
TemplateMap mShaderTemplates;
|
|
|
|
typedef std::pair<std::string, DefineMap> MapKey;
|
|
typedef std::map<MapKey, osg::ref_ptr<osg::Shader>> ShaderMap;
|
|
ShaderMap mShaders;
|
|
|
|
typedef std::map<std::pair<osg::ref_ptr<osg::Shader>, osg::ref_ptr<osg::Shader>>, osg::ref_ptr<osg::Program>>
|
|
ProgramMap;
|
|
ProgramMap mPrograms;
|
|
|
|
typedef std::vector<osg::ref_ptr<osg::Shader>> ShaderList;
|
|
typedef std::map<osg::ref_ptr<osg::Shader>, ShaderList> LinkedShadersMap;
|
|
LinkedShadersMap mLinkedShaders;
|
|
|
|
std::mutex mMutex;
|
|
|
|
osg::ref_ptr<const osg::Program> mProgramTemplate;
|
|
|
|
int mMaxTextureUnits = 0;
|
|
int mReservedTextureUnits = 0;
|
|
std::unique_ptr<HotReloadManager> mHotReloadManager;
|
|
struct ReservedTextureUnits
|
|
{
|
|
int index = -1;
|
|
int count = 0;
|
|
};
|
|
std::array<ReservedTextureUnits, static_cast<int>(Slot::SLOT_COUNT)> mReservedTextureUnitsBySlot = {};
|
|
};
|
|
|
|
bool parseForeachDirective(std::string& source, const std::string& templateName, size_t foundPos);
|
|
bool parseLinkDirective(
|
|
std::string& source, std::string& linkTarget, const std::string& templateName, size_t foundPos);
|
|
|
|
bool parseDefines(std::string& source, const ShaderManager::DefineMap& defines,
|
|
const ShaderManager::DefineMap& globalDefines, const std::string& templateName);
|
|
|
|
bool parseDirectives(std::string& source, std::vector<std::string>& linkedShaderTemplateNames,
|
|
const ShaderManager::DefineMap& defines, const ShaderManager::DefineMap& globalDefines,
|
|
const std::string& templateName);
|
|
}
|
|
|
|
#endif
|