|
|
|
@ -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["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["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["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["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);
|
|
|
|
|
|
|
|
|
|
shader["setVector3"] = [context](const Shader& shader, const std::string& name, const osg::Vec3f& value)
|
|
|
|
|
api["load"] = [](const std::string& name)
|
|
|
|
|
{
|
|
|
|
|
context.mLuaManager->addAction(std::make_unique<SetUniformShaderAction<osg::Vec3f>>(context.mLua, shader.mShader, name, value));
|
|
|
|
|
};
|
|
|
|
|
Shader shader{MWBase::Environment::get().getWorld()->getPostProcessor()->loadTechnique(name, false)};
|
|
|
|
|
|
|
|
|
|
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));
|
|
|
|
|
};
|
|
|
|
|
if (!shader.mShader || !shader.mShader->isValid())
|
|
|
|
|
throw std::runtime_error(Misc::StringUtils::format("Failed loading shader '%s'", name));
|
|
|
|
|
|
|
|
|
|
api["load"] = [](const std::string& name)
|
|
|
|
|
{
|
|
|
|
|
return Shader(MWBase::Environment::get().getWorld()->getPostProcessor()->loadTechnique(name, false));
|
|
|
|
|
return shader;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return LuaUtil::makeReadOnly(api);
|
|
|
|
|