mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-17 01:10:10 +00:00
postprocessing lua api extensions
This commit is contained in:
parent
02cfb7e258
commit
6093cb5f2c
@ -296,7 +296,7 @@ namespace MWGui
|
||||
|
||||
auto technique = processor->loadTechnique(name);
|
||||
|
||||
if (!technique)
|
||||
if (!technique || technique->getStatus() == fx::Technique::Status::File_Not_exists)
|
||||
return;
|
||||
|
||||
while (mConfigArea->getChildCount() > 0)
|
||||
@ -304,9 +304,6 @@ namespace MWGui
|
||||
|
||||
mShaderInfo->setCaption("");
|
||||
|
||||
if (!technique)
|
||||
return;
|
||||
|
||||
std::ostringstream ss;
|
||||
|
||||
const std::string NA = "NA";
|
||||
@ -322,8 +319,8 @@ namespace MWGui
|
||||
|
||||
const auto flags = technique->getFlags();
|
||||
|
||||
const auto flag_interior = serializeBool (!(flags & fx::Technique::Flag_Disable_Interiors));
|
||||
const auto flag_exterior = serializeBool (!(flags & fx::Technique::Flag_Disable_Exteriors));
|
||||
const auto flag_interior = serializeBool(!(flags & fx::Technique::Flag_Disable_Interiors));
|
||||
const auto flag_exterior = serializeBool(!(flags & fx::Technique::Flag_Disable_Exteriors));
|
||||
const auto flag_underwater = serializeBool(!(flags & fx::Technique::Flag_Disable_Underwater));
|
||||
const auto flag_abovewater = serializeBool(!(flags & fx::Technique::Flag_Disable_Abovewater));
|
||||
|
||||
@ -339,14 +336,12 @@ namespace MWGui
|
||||
<< "#{fontcolourhtml=header} Underwater: #{fontcolourhtml=normal} " << flag_underwater
|
||||
<< "#{fontcolourhtml=header} Abovewater: #{fontcolourhtml=normal} " << flag_abovewater;
|
||||
break;
|
||||
case fx::Technique::Status::File_Not_exists:
|
||||
ss << "#{fontcolourhtml=negative}Shader Error: #{fontcolourhtml=header} <" << std::string(technique->getFileName()) << ">#{fontcolourhtml=normal} not found." << endl << endl
|
||||
<< "Ensure the shader file is in a 'Shaders/' sub directory in a data files directory";
|
||||
break;
|
||||
case fx::Technique::Status::Parse_Error:
|
||||
ss << "#{fontcolourhtml=negative}Shader Compile Error: #{fontcolourhtml=normal} <" << std::string(technique->getName()) << "> failed to compile." << endl << endl
|
||||
<< technique->getLastError();
|
||||
break;
|
||||
case fx::Technique::Status::File_Not_exists:
|
||||
break;
|
||||
}
|
||||
|
||||
mShaderInfo->setCaptionWithReplacing(ss.str());
|
||||
|
@ -59,9 +59,44 @@ namespace MWLua
|
||||
return Misc::StringUtils::format("Shader(%s, %s)", mShader->getName(), mShader->getFileName());
|
||||
}
|
||||
|
||||
bool mQueuedAction = false;
|
||||
enum { Action_None, Action_Enable, Action_Disable } mQueuedAction = Action_None;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
auto getSetter(const Context& context)
|
||||
{
|
||||
return [context](const Shader& shader, const std::string& name, const T& value) {
|
||||
context.mLuaManager->addAction(std::make_unique<SetUniformShaderAction<T>>(context.mLua, shader.mShader, name, value));
|
||||
};
|
||||
}
|
||||
|
||||
template <class T>
|
||||
auto getArraySetter(const Context& context)
|
||||
{
|
||||
return [context](const Shader& shader, const std::string& name, const sol::table& table) {
|
||||
auto targetSize = MWBase::Environment::get().getWorld()->getPostProcessor()->getUniformSize(shader.mShader, name);
|
||||
|
||||
if (!targetSize.has_value())
|
||||
throw std::runtime_error(Misc::StringUtils::format("Failed setting uniform array '%s'", name));
|
||||
|
||||
if (*targetSize != table.size())
|
||||
throw std::runtime_error(Misc::StringUtils::format("Mismatching uniform array size, got %zu expected %zu", table.size(), *targetSize));
|
||||
|
||||
std::vector<T> values;
|
||||
values.reserve(*targetSize);
|
||||
|
||||
for (size_t i = 0; i < *targetSize; ++i)
|
||||
{
|
||||
sol::object obj = table[i+1];
|
||||
if (!obj.is<T>())
|
||||
throw std::runtime_error("Invalid type for uniform array");
|
||||
values.push_back(obj.as<T>());
|
||||
}
|
||||
|
||||
context.mLuaManager->addAction(std::make_unique<SetUniformShaderAction<std::vector<T>>>(context.mLua, shader.mShader, name, values));
|
||||
};
|
||||
}
|
||||
|
||||
sol::table initPostprocessingPackage(const Context& context)
|
||||
{
|
||||
sol::table api(context.mLua->sol(), sol::create);
|
||||
@ -76,62 +111,64 @@ namespace MWLua
|
||||
pos = optPos.value();
|
||||
|
||||
if (shader.mShader && shader.mShader->isValid())
|
||||
shader.mQueuedAction = true;
|
||||
shader.mQueuedAction = Shader::Action_Enable;
|
||||
|
||||
context.mLuaManager->addAction(
|
||||
[=] { MWBase::Environment::get().getWorld()->getPostProcessor()->enableTechnique(shader.mShader, pos); },
|
||||
[=, &shader] {
|
||||
shader.mQueuedAction = Shader::Action_None;
|
||||
|
||||
if (!MWBase::Environment::get().getWorld()->getPostProcessor()->enableTechnique(shader.mShader, pos))
|
||||
throw std::runtime_error("Failed enabling shader '" + shader.mShader->getName() + "'");
|
||||
},
|
||||
"Enable shader " + (shader.mShader ? shader.mShader->getName() : "nil")
|
||||
);
|
||||
};
|
||||
|
||||
shader["disable"] = [context](Shader& shader)
|
||||
{
|
||||
shader.mQueuedAction = false;
|
||||
shader.mQueuedAction = Shader::Action_Disable;
|
||||
|
||||
context.mLuaManager->addAction(
|
||||
[&] { MWBase::Environment::get().getWorld()->getPostProcessor()->disableTechnique(shader.mShader); },
|
||||
[&] {
|
||||
shader.mQueuedAction = Shader::Action_None;
|
||||
|
||||
if (!MWBase::Environment::get().getWorld()->getPostProcessor()->disableTechnique(shader.mShader))
|
||||
throw std::runtime_error("Failed disabling shader '" + shader.mShader->getName() + "'");
|
||||
},
|
||||
"Disable shader " + (shader.mShader ? shader.mShader->getName() : "nil")
|
||||
);
|
||||
};
|
||||
|
||||
shader["isEnabled"] = [](const Shader& shader)
|
||||
{
|
||||
return shader.mQueuedAction;
|
||||
if (shader.mQueuedAction == Shader::Action_Enable)
|
||||
return true;
|
||||
else if (shader.mQueuedAction == Shader::Action_Disable)
|
||||
return false;
|
||||
return MWBase::Environment::get().getWorld()->getPostProcessor()->isTechniqueEnabled(shader.mShader);
|
||||
};
|
||||
|
||||
shader["setBool"] = [context](const Shader& shader, const std::string& name, bool value)
|
||||
{
|
||||
context.mLuaManager->addAction(std::make_unique<SetUniformShaderAction<bool>>(context.mLua, shader.mShader, name, value));
|
||||
};
|
||||
shader["setBool"] = getSetter<bool>(context);
|
||||
shader["setFloat"] = getSetter<float>(context);
|
||||
shader["setInt"] = getSetter<int>(context);
|
||||
shader["setVector2"] = getSetter<osg::Vec2f>(context);
|
||||
shader["setVector3"] = getSetter<osg::Vec3f>(context);
|
||||
shader["setVector4"] = getSetter<osg::Vec4f>(context);
|
||||
|
||||
shader["setFloat"] = [context](const Shader& shader, const std::string& name, float value)
|
||||
{
|
||||
context.mLuaManager->addAction(std::make_unique<SetUniformShaderAction<float>>(context.mLua, shader.mShader, name, value));
|
||||
};
|
||||
|
||||
shader["setInt"] = [context](const Shader& shader, const std::string& name, int value)
|
||||
{
|
||||
context.mLuaManager->addAction(std::make_unique<SetUniformShaderAction<int>>(context.mLua, shader.mShader, name, value));
|
||||
};
|
||||
|
||||
shader["setVector2"] = [context](const Shader& shader, const std::string& name, const osg::Vec2f& value)
|
||||
{
|
||||
context.mLuaManager->addAction(std::make_unique<SetUniformShaderAction<osg::Vec2f>>(context.mLua, shader.mShader, name, value));
|
||||
};
|
||||
|
||||
shader["setVector3"] = [context](const Shader& shader, const std::string& name, const osg::Vec3f& value)
|
||||
{
|
||||
context.mLuaManager->addAction(std::make_unique<SetUniformShaderAction<osg::Vec3f>>(context.mLua, shader.mShader, name, value));
|
||||
};
|
||||
|
||||
shader["setVector4"] = [context](const Shader& shader, const std::string& name, const osg::Vec4f& value)
|
||||
{
|
||||
context.mLuaManager->addAction(std::make_unique<SetUniformShaderAction<osg::Vec4f>>(context.mLua, shader.mShader, name, value));
|
||||
};
|
||||
shader["setFloatArray"] = getArraySetter<float>(context);
|
||||
shader["setIntArray"] = getArraySetter<int>(context);
|
||||
shader["setVector2Array"] = getArraySetter<osg::Vec2f>(context);
|
||||
shader["setVector3Array"] = getArraySetter<osg::Vec3f>(context);
|
||||
shader["setVector4Array"] = getArraySetter<osg::Vec4f>(context);
|
||||
|
||||
api["load"] = [](const std::string& name)
|
||||
{
|
||||
return Shader(MWBase::Environment::get().getWorld()->getPostProcessor()->loadTechnique(name, false));
|
||||
Shader shader{MWBase::Environment::get().getWorld()->getPostProcessor()->loadTechnique(name, false)};
|
||||
|
||||
if (!shader.mShader || !shader.mShader->isValid())
|
||||
throw std::runtime_error(Misc::StringUtils::format("Failed loading shader '%s'", name));
|
||||
|
||||
return shader;
|
||||
};
|
||||
|
||||
return LuaUtil::makeReadOnly(api);
|
||||
|
@ -406,6 +406,13 @@ namespace MWRender
|
||||
|
||||
void PostProcessor::update(size_t frameId)
|
||||
{
|
||||
while (!mQueuedTemplates.empty())
|
||||
{
|
||||
mTemplates.push_back(std::move(mQueuedTemplates.back()));
|
||||
|
||||
mQueuedTemplates.pop_back();
|
||||
}
|
||||
|
||||
updateLiveReload();
|
||||
|
||||
reloadIfRequired();
|
||||
@ -582,7 +589,7 @@ namespace MWRender
|
||||
if (uniform->mSamplerType) continue;
|
||||
|
||||
if (auto type = uniform->getType())
|
||||
uniform->setUniform(node.mRootStateSet->getOrCreateUniform(uniform->mName, type.value()));
|
||||
uniform->setUniform(node.mRootStateSet->getOrCreateUniform(uniform->mName.c_str(), *type, uniform->getNumElements()));
|
||||
}
|
||||
|
||||
std::unordered_map<osg::Texture2D*, osg::Texture2D*> renderTargetCache;
|
||||
@ -643,7 +650,13 @@ namespace MWRender
|
||||
|
||||
bool PostProcessor::enableTechnique(std::shared_ptr<fx::Technique> technique, std::optional<int> location)
|
||||
{
|
||||
if (!technique || technique->getName() == "main" || (location.has_value() && location.value() <= 0))
|
||||
if (!isEnabled())
|
||||
{
|
||||
Log(Debug::Warning) << "PostProcessing disabled, cannot load technique '" << technique->getName() << "'";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!technique || Misc::StringUtils::ciEqual(technique->getName(), "main") || (location.has_value() && location.value() <= 0))
|
||||
return false;
|
||||
|
||||
disableTechnique(technique, false);
|
||||
@ -753,14 +766,21 @@ namespace MWRender
|
||||
mHUDCamera->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
|
||||
}
|
||||
|
||||
std::shared_ptr<fx::Technique> PostProcessor::loadTechnique(const std::string& name, bool insert)
|
||||
std::shared_ptr<fx::Technique> PostProcessor::loadTechnique(const std::string& name, bool loadNextFrame)
|
||||
{
|
||||
if (!isEnabled())
|
||||
{
|
||||
Log(Debug::Warning) << "PostProcessing disabled, cannot load technique '" << name << "'";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < mTemplates.size(); ++i)
|
||||
if (name == mTemplates[i]->getName())
|
||||
return mTemplates[i];
|
||||
for (const auto& technique : mTemplates)
|
||||
if (Misc::StringUtils::ciEqual(technique->getName(), name))
|
||||
return technique;
|
||||
|
||||
for (const auto& technique : mQueuedTemplates)
|
||||
if (Misc::StringUtils::ciEqual(technique->getName(), name))
|
||||
return technique;
|
||||
|
||||
auto technique = std::make_shared<fx::Technique>(*mVFS, *mRendering.getResourceSystem()->getImageManager(), name, mWidth, mHeight, mUBO, mNormalsSupported);
|
||||
|
||||
@ -769,8 +789,11 @@ namespace MWRender
|
||||
if (technique->getStatus() != fx::Technique::Status::File_Not_exists)
|
||||
technique->setLastModificationTime(std::filesystem::last_write_time(mTechniqueFileMap[technique->getName()]));
|
||||
|
||||
if (!insert)
|
||||
if (!loadNextFrame)
|
||||
{
|
||||
mQueuedTemplates.push_back(technique);
|
||||
return technique;
|
||||
}
|
||||
|
||||
reloadMainPass(*technique);
|
||||
|
||||
@ -779,18 +802,6 @@ namespace MWRender
|
||||
return mTemplates.back();
|
||||
}
|
||||
|
||||
void PostProcessor::addTemplate(std::shared_ptr<fx::Technique> technique)
|
||||
{
|
||||
if (!isEnabled())
|
||||
return;
|
||||
|
||||
for (size_t i = 0; i < mTemplates.size(); ++i)
|
||||
if (technique.get() == mTemplates[i].get())
|
||||
return;
|
||||
|
||||
mTemplates.push_back(technique);
|
||||
}
|
||||
|
||||
void PostProcessor::reloadTechniques()
|
||||
{
|
||||
if (!isEnabled())
|
||||
@ -810,7 +821,7 @@ namespace MWRender
|
||||
if (techniqueName.empty())
|
||||
continue;
|
||||
|
||||
if ((&techniqueName != &techniqueStrings.front()) && Misc::StringUtils::ciEqual(techniqueName, "main"))
|
||||
if ((&techniqueName != &techniqueStrings.front()) && techniqueName == "main")
|
||||
{
|
||||
Log(Debug::Warning) << "main.omwfx techniqued specified in chain, this is not allowed. technique file will be ignored if it exists.";
|
||||
continue;
|
||||
|
@ -136,6 +136,16 @@ namespace MWRender
|
||||
(*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; }
|
||||
@ -144,9 +154,7 @@ namespace MWRender
|
||||
|
||||
void toggleMode();
|
||||
|
||||
std::shared_ptr<fx::Technique> loadTechnique(const std::string& name, bool insert=true);
|
||||
|
||||
void addTemplate(std::shared_ptr<fx::Technique> technique);
|
||||
std::shared_ptr<fx::Technique> loadTechnique(const std::string& name, bool loadNextFrame=true);
|
||||
|
||||
bool isEnabled() const { return mUsePostProcessing && mEnabled; }
|
||||
|
||||
@ -192,6 +200,7 @@ namespace MWRender
|
||||
|
||||
TechniqueList mTechniques;
|
||||
TechniqueList mTemplates;
|
||||
TechniqueList mQueuedTemplates;
|
||||
|
||||
std::unordered_map<std::string, std::filesystem::path> mTechniqueFileMap;
|
||||
|
||||
|
@ -171,7 +171,7 @@ TestFile repeated_shared_block{R"(
|
||||
const auto& uniform = mTechnique->getUniformMap().front();
|
||||
|
||||
EXPECT_TRUE(uniform->mStatic);
|
||||
EXPECT_FLOAT_EQ(uniform->mStep, 0.5f);
|
||||
EXPECT_DOUBLE_EQ(uniform->mStep, 0.5);
|
||||
EXPECT_EQ(uniform->getDefault<osg::Vec4f>(), osg::Vec4f(0,0,0,0));
|
||||
EXPECT_EQ(uniform->getMin<osg::Vec4f>(), osg::Vec4f(0,1,0,0));
|
||||
EXPECT_EQ(uniform->getMax<osg::Vec4f>(), osg::Vec4f(0,0,1,0));
|
||||
|
@ -526,7 +526,7 @@ namespace fx
|
||||
error(Misc::StringUtils::format("redeclaration of uniform '%s'", std::string(mBlockName)));
|
||||
|
||||
std::shared_ptr<Types::UniformBase> uniform = std::make_shared<Types::UniformBase>();
|
||||
Types::Uniform<SrcT> data;
|
||||
Types::Uniform<SrcT> data = Types::Uniform<SrcT>();
|
||||
|
||||
while (!isNext<Lexer::Close_bracket>() && !isNext<Lexer::Eof>())
|
||||
{
|
||||
@ -543,11 +543,6 @@ namespace fx
|
||||
|
||||
static_assert(isVec || isFloat || isInt || isBool, "Unsupported type");
|
||||
|
||||
std::optional<double> step;
|
||||
|
||||
if constexpr (isInt)
|
||||
step = 1.0;
|
||||
|
||||
if (key == "default")
|
||||
{
|
||||
if constexpr (isVec)
|
||||
@ -559,6 +554,15 @@ namespace fx
|
||||
else if constexpr (isBool)
|
||||
data.mDefault = parseBool();
|
||||
}
|
||||
else if (key == "size")
|
||||
{
|
||||
if constexpr (isBool)
|
||||
error("bool arrays currently unsupported");
|
||||
|
||||
int size = parseInteger();
|
||||
if (size > 1)
|
||||
data.mArray = std::vector<SrcT>(size);
|
||||
}
|
||||
else if (key == "min")
|
||||
{
|
||||
if constexpr (isVec)
|
||||
@ -582,7 +586,7 @@ namespace fx
|
||||
data.mMax = parseBool();
|
||||
}
|
||||
else if (key == "step")
|
||||
step = parseFloat();
|
||||
uniform->mStep = parseFloat();
|
||||
else if (key == "static")
|
||||
uniform->mStatic = parseBool();
|
||||
else if (key == "description")
|
||||
@ -598,18 +602,28 @@ namespace fx
|
||||
else
|
||||
error(Misc::StringUtils::format("unexpected key '%s'", std::string{key}));
|
||||
|
||||
if (step)
|
||||
uniform->mStep = step.value();
|
||||
|
||||
expect<Lexer::SemiColon>();
|
||||
}
|
||||
|
||||
if (data.isArray())
|
||||
uniform->mStatic = false;
|
||||
|
||||
uniform->mName = std::string(mBlockName);
|
||||
uniform->mData = data;
|
||||
uniform->mTechniqueName = mName;
|
||||
|
||||
if (auto cached = Settings::ShaderManager::get().getValue<SrcT>(mName, uniform->mName))
|
||||
uniform->setValue<SrcT>(cached.value());
|
||||
if (data.mArray)
|
||||
{
|
||||
if constexpr (!std::is_same_v<bool, SrcT>)
|
||||
{
|
||||
if (auto cached = Settings::ShaderManager::get().getValue<std::vector<SrcT>>(mName, uniform->mName))
|
||||
uniform->setValue(cached.value());
|
||||
}
|
||||
}
|
||||
else if (auto cached = Settings::ShaderManager::get().getValue<SrcT>(mName, uniform->mName))
|
||||
{
|
||||
uniform->setValue(cached.value());
|
||||
}
|
||||
|
||||
mDefinedUniforms.emplace_back(std::move(uniform));
|
||||
}
|
||||
|
@ -60,12 +60,24 @@ namespace fx
|
||||
struct Uniform
|
||||
{
|
||||
std::optional<T> mValue;
|
||||
T mDefault;
|
||||
std::optional<std::vector<T>> mArray;
|
||||
|
||||
T mDefault = {};
|
||||
T mMin = std::numeric_limits<T>::lowest();
|
||||
T mMax = std::numeric_limits<T>::max();
|
||||
|
||||
using value_type = T;
|
||||
|
||||
bool isArray() const
|
||||
{
|
||||
return mArray.has_value();
|
||||
}
|
||||
|
||||
const std::vector<T>& getArray() const
|
||||
{
|
||||
return *mArray;
|
||||
}
|
||||
|
||||
T getValue() const
|
||||
{
|
||||
return mValue.value_or(mDefault);
|
||||
@ -97,7 +109,7 @@ namespace fx
|
||||
|
||||
bool mStatic = true;
|
||||
std::optional<SamplerType> mSamplerType = std::nullopt;
|
||||
double mStep;
|
||||
double mStep = 1.0;
|
||||
|
||||
Uniform_t mData;
|
||||
|
||||
@ -109,6 +121,11 @@ namespace fx
|
||||
return value.value_or(std::get<Uniform<T>>(mData).getValue());
|
||||
}
|
||||
|
||||
size_t getNumElements() const
|
||||
{
|
||||
return std::visit([&](auto&& arg) { ;return arg.isArray() ? arg.getArray().size() : 1; }, mData);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T getMin() const
|
||||
{
|
||||
@ -137,8 +154,7 @@ namespace fx
|
||||
{
|
||||
arg.mValue = value;
|
||||
|
||||
if (mStatic)
|
||||
Settings::ShaderManager::get().setValue<T>(mTechniqueName, mName, value);
|
||||
Settings::ShaderManager::get().setValue(mTechniqueName, mName, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -147,6 +163,28 @@ namespace fx
|
||||
}, mData);
|
||||
}
|
||||
|
||||
template <class T, class A>
|
||||
void setValue(const std::vector<T, A>& value)
|
||||
{
|
||||
std::visit([&, value](auto&& arg) {
|
||||
using U = typename std::decay_t<decltype(arg)>::value_type;
|
||||
|
||||
if (!arg.isArray() || arg.getArray().size() != value.size())
|
||||
{
|
||||
Log(Debug::Error) << "Attempting to set uniform array '" << mName << "' with mismatching array sizes";
|
||||
return;
|
||||
}
|
||||
|
||||
if constexpr (std::is_same_v<T, U>)
|
||||
{
|
||||
arg.mArray = value;
|
||||
Settings::ShaderManager::get().setValue(mTechniqueName, mName, value);
|
||||
}
|
||||
else
|
||||
Log(Debug::Warning) << "Attempting to set uniform array '" << mName << "' with wrong type";
|
||||
}, mData);
|
||||
}
|
||||
|
||||
void setUniform(osg::Uniform* uniform)
|
||||
{
|
||||
auto type = getType();
|
||||
@ -155,8 +193,14 @@ namespace fx
|
||||
|
||||
std::visit([&](auto&& arg)
|
||||
{
|
||||
const auto value = arg.getValue();
|
||||
uniform->set(value);
|
||||
if (arg.isArray())
|
||||
{
|
||||
for (size_t i = 0; i < arg.getArray().size(); ++i)
|
||||
uniform->setElement(i, arg.getArray()[i]);
|
||||
uniform->dirty();
|
||||
}
|
||||
else
|
||||
uniform->set(arg.getValue());
|
||||
}, mData);
|
||||
}
|
||||
|
||||
@ -197,52 +241,53 @@ namespace fx
|
||||
}
|
||||
}
|
||||
|
||||
bool useUniform = (Settings::ShaderManager::get().getMode() == Settings::ShaderManager::Mode::Debug || mStatic == false);
|
||||
|
||||
return std::visit([&](auto&& arg) -> std::optional<std::string> {
|
||||
using T = typename std::decay_t<decltype(arg)>::value_type;
|
||||
|
||||
auto value = arg.getValue();
|
||||
|
||||
const bool useUniform = arg.isArray() || (Settings::ShaderManager::get().getMode() == Settings::ShaderManager::Mode::Debug || mStatic == false);
|
||||
const std::string uname = arg.isArray() ? Misc::StringUtils::format("%s[%zu]", mName, arg.getArray().size()) : mName;
|
||||
|
||||
if constexpr (std::is_same_v<T, osg::Vec2f>)
|
||||
{
|
||||
if (useUniform)
|
||||
return Misc::StringUtils::format("uniform vec2 %s;", mName);
|
||||
return Misc::StringUtils::format("uniform vec2 %s;", uname);
|
||||
|
||||
return Misc::StringUtils::format("const vec2 %s=vec2(%f,%f);", mName, value[0], value[1]);
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, osg::Vec3f>)
|
||||
{
|
||||
if (useUniform)
|
||||
return Misc::StringUtils::format("uniform vec3 %s;", mName);
|
||||
return Misc::StringUtils::format("uniform vec3 %s;", uname);
|
||||
|
||||
return Misc::StringUtils::format("const vec3 %s=vec3(%f,%f,%f);", mName, value[0], value[1], value[2]);
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, osg::Vec4f>)
|
||||
{
|
||||
if (useUniform)
|
||||
return Misc::StringUtils::format("uniform vec4 %s;", mName);
|
||||
return Misc::StringUtils::format("uniform vec4 %s;", uname);
|
||||
|
||||
return Misc::StringUtils::format("const vec4 %s=vec4(%f,%f,%f,%f);", mName, value[0], value[1], value[2], value[3]);
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, float>)
|
||||
{
|
||||
if (useUniform)
|
||||
return Misc::StringUtils::format("uniform float %s;", mName);
|
||||
return Misc::StringUtils::format("uniform float %s;", uname);
|
||||
|
||||
return Misc::StringUtils::format("const float %s=%f;", mName, value);
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, int>)
|
||||
{
|
||||
if (useUniform)
|
||||
return Misc::StringUtils::format("uniform int %s;", mName);
|
||||
return Misc::StringUtils::format("uniform int %s;", uname);
|
||||
|
||||
return Misc::StringUtils::format("const int %s=%i;", mName, value);
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, bool>)
|
||||
{
|
||||
if (useUniform)
|
||||
return Misc::StringUtils::format("uniform bool %s;", mName);
|
||||
return Misc::StringUtils::format("uniform bool %s;", uname);
|
||||
|
||||
return Misc::StringUtils::format("const bool %s=%s;", mName, value ? "true" : "false");
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
|
@ -271,10 +271,10 @@ Below is an example of passing a value through a custom vertex shader to the fra
|
||||
}
|
||||
|
||||
fragment pass {
|
||||
omw_Out vec2 omw_TexCoord;
|
||||
omw_In vec2 omw_TexCoord;
|
||||
|
||||
// our custom output from the vertex shader is available
|
||||
omw_Out float noise;
|
||||
omw_In float noise;
|
||||
|
||||
void main()
|
||||
{
|
||||
@ -461,6 +461,14 @@ To use the uniform you can reference it in any pass, it should **not** be declar
|
||||
}
|
||||
}
|
||||
|
||||
You can use uniform arrays as well, but they are restricted to the `Lua API <../lua-scripting/openmw_postprocessing.html>`_ scripts.
|
||||
These uniform blocks must be defined with the new ``size`` parameter.
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
uniform_vec3 uArray {
|
||||
size = 10;
|
||||
}
|
||||
|
||||
``render_target``
|
||||
*****************
|
||||
|
@ -7,7 +7,7 @@ Overview
|
||||
|
||||
OpenMW supports a moddable post process framework for creating and
|
||||
controlling screenspace effects. This is integrated into OpenMW's Lua API, see
|
||||
`reference <../lua-scripting/openmw_shader.html>`_ for details.
|
||||
`reference <../lua-scripting/openmw_postprocessing.html>`_ for details.
|
||||
|
||||
Basic concepts
|
||||
==============
|
||||
|
@ -1,19 +1,18 @@
|
||||
---
|
||||
-- `openmw.postprocessing` is an interface to postprocessing shaders.
|
||||
-- Can be used only by local scripts, that are attached to a player.
|
||||
-- @module shader
|
||||
-- @module postprocessing
|
||||
-- @usage local postprocessing = require('openmw.postprocessing')
|
||||
|
||||
|
||||
|
||||
---
|
||||
-- Load a shader and return its handle.
|
||||
-- @function [parent=#postprocessing] load
|
||||
-- @param #string name Name of the shader without its extension
|
||||
-- @return #Shader
|
||||
-- @usage
|
||||
-- If the shader exists and compiles, the shader will still be off by default.
|
||||
-- It must be enabled to see its effect.
|
||||
-- -- If the shader exists and compiles, the shader will still be off by default.
|
||||
-- -- It must be enabled to see its effect.
|
||||
-- local vignetteShader = postprocessing.load('vignette')
|
||||
|
||||
---
|
||||
@ -72,21 +71,62 @@
|
||||
-- @function [parent=#Shader] setVector2
|
||||
-- @param self
|
||||
-- @param #string name Name of uniform
|
||||
-- @param #Vector2 value Value of uniform.
|
||||
-- @param openmw.util#Vector2 value Value of uniform.
|
||||
|
||||
---
|
||||
-- Set a non static Vector3 shader variable.
|
||||
-- @function [parent=#Shader] setVector3
|
||||
-- @param self
|
||||
-- @param #string name Name of uniform
|
||||
-- @param #Vector3 value Value of uniform.
|
||||
-- @param openmw.util#Vector3 value Value of uniform.
|
||||
|
||||
---
|
||||
-- Set a non static Vector4 shader variable.
|
||||
-- @function [parent=#Shader] setVector4
|
||||
-- @param self
|
||||
-- @param #string name Name of uniform
|
||||
-- @param #Vector4 value Value of uniform.
|
||||
-- @param openmw.util#Vector4 value Value of uniform.
|
||||
|
||||
---
|
||||
-- Set a non static integer array shader variable.
|
||||
-- @function [parent=#Shader] setIntArray
|
||||
-- @param self
|
||||
-- @param #string name Name of uniform
|
||||
-- @param #table array Contains equal number of #number elements as the uniform array.
|
||||
|
||||
---
|
||||
-- Set a non static float array shader variable.
|
||||
-- @function [parent=#Shader] setFloatArray
|
||||
-- @param self
|
||||
-- @param #string name Name of uniform
|
||||
-- @param #table array Contains equal number of #number elements as the uniform array.
|
||||
|
||||
---
|
||||
-- Set a non static Vector2 array shader variable.
|
||||
-- @function [parent=#Shader] setVector2Array
|
||||
-- @param self
|
||||
-- @param #string name Name of uniform
|
||||
-- @param #table array Contains equal number of @{openmw.util#Vector2} elements as the uniform array.
|
||||
|
||||
---
|
||||
-- Set a non static Vector3 array shader variable.
|
||||
-- @function [parent=#Shader] setVector3Array
|
||||
-- @param self
|
||||
-- @param #string name Name of uniform
|
||||
-- @param #table array Contains equal number of @{openmw.util#Vector3} elements as the uniform array.
|
||||
|
||||
---
|
||||
-- Set a non static Vector4 array shader variable.
|
||||
-- @function [parent=#Shader] setVector4Array
|
||||
-- @param self
|
||||
-- @param #string name Name of uniform
|
||||
-- @param #table array Contains equal number of @{openmw.util#Vector4} elements as the uniform array.
|
||||
-- @usage
|
||||
-- -- Setting an array
|
||||
-- local shader = postprocessing.load('godrays')
|
||||
-- -- Toggle shader on
|
||||
-- shader:enable()
|
||||
-- -- Set new array uniform which was defined with length 2
|
||||
-- shader:setVector4Array('myArray', { util.vector4(1,0,0,1), util.vector4(1,0,1,1) })
|
||||
|
||||
return nil
|
||||
|
Loading…
Reference in New Issue
Block a user