mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-05 06:45:34 +00:00
Merge branch 'save_me_not' into 'master'
[Postprocessing] Fix a couple awkward issues with Lua API See merge request OpenMW/openmw!1946
This commit is contained in:
commit
7bc0d46896
9 changed files with 74 additions and 29 deletions
|
@ -30,7 +30,7 @@ namespace
|
||||||
{
|
{
|
||||||
auto technique = processor->getTechniques()[i];
|
auto technique = processor->getTechniques()[i];
|
||||||
|
|
||||||
if (!technique)
|
if (!technique || technique->getDynamic())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
chain << technique->getName();
|
chain << technique->getName();
|
||||||
|
@ -140,10 +140,15 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
auto* processor = MWBase::Environment::get().getWorld()->getPostProcessor();
|
auto* processor = MWBase::Environment::get().getWorld()->getPostProcessor();
|
||||||
mOverrideHint = list->getItemNameAt(selected);
|
mOverrideHint = list->getItemNameAt(selected);
|
||||||
|
|
||||||
|
auto technique = *list->getItemDataAt<std::shared_ptr<fx::Technique>>(selected);
|
||||||
|
if (technique->getDynamic())
|
||||||
|
return;
|
||||||
|
|
||||||
if (enabled)
|
if (enabled)
|
||||||
processor->enableTechnique(*list->getItemDataAt<std::shared_ptr<fx::Technique>>(selected));
|
processor->enableTechnique(technique);
|
||||||
else
|
else
|
||||||
processor->disableTechnique(*list->getItemDataAt<std::shared_ptr<fx::Technique>>(selected));
|
processor->disableTechnique(technique);
|
||||||
saveChain();
|
saveChain();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,7 +177,11 @@ namespace MWGui
|
||||||
|
|
||||||
if (static_cast<size_t>(index) != selected)
|
if (static_cast<size_t>(index) != selected)
|
||||||
{
|
{
|
||||||
if (processor->enableTechnique(*mActiveList->getItemDataAt<std::shared_ptr<fx::Technique>>(selected), index))
|
auto technique = *mActiveList->getItemDataAt<std::shared_ptr<fx::Technique>>(selected);
|
||||||
|
if (technique->getDynamic())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (processor->enableTechnique(technique, index) != MWRender::PostProcessor::Status_Error)
|
||||||
saveChain();
|
saveChain();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -330,6 +339,9 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
case fx::Technique::Status::Success:
|
case fx::Technique::Status::Success:
|
||||||
case fx::Technique::Status::Uncompiled:
|
case fx::Technique::Status::Uncompiled:
|
||||||
|
{
|
||||||
|
if (technique->getDynamic())
|
||||||
|
ss << "#{fontcolourhtml=header}Locked: #{fontcolourhtml=normal} Cannot be toggled or moved, controlled by external Lua script" << endl << endl;
|
||||||
ss << "#{fontcolourhtml=header}Author: #{fontcolourhtml=normal} " << author << endl << endl
|
ss << "#{fontcolourhtml=header}Author: #{fontcolourhtml=normal} " << author << endl << endl
|
||||||
<< "#{fontcolourhtml=header}Version: #{fontcolourhtml=normal} " << version << endl << endl
|
<< "#{fontcolourhtml=header}Version: #{fontcolourhtml=normal} " << version << endl << endl
|
||||||
<< "#{fontcolourhtml=header}Description: #{fontcolourhtml=normal} " << description << endl << endl
|
<< "#{fontcolourhtml=header}Description: #{fontcolourhtml=normal} " << description << endl << endl
|
||||||
|
@ -338,6 +350,7 @@ namespace MWGui
|
||||||
<< "#{fontcolourhtml=header} Underwater: #{fontcolourhtml=normal} " << flag_underwater
|
<< "#{fontcolourhtml=header} Underwater: #{fontcolourhtml=normal} " << flag_underwater
|
||||||
<< "#{fontcolourhtml=header} Abovewater: #{fontcolourhtml=normal} " << flag_abovewater;
|
<< "#{fontcolourhtml=header} Abovewater: #{fontcolourhtml=normal} " << flag_abovewater;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case fx::Technique::Status::Parse_Error:
|
case fx::Technique::Status::Parse_Error:
|
||||||
ss << "#{fontcolourhtml=negative}Shader Compile Error: #{fontcolourhtml=normal} <" << std::string(technique->getName()) << "> failed to compile." << endl << endl
|
ss << "#{fontcolourhtml=negative}Shader Compile Error: #{fontcolourhtml=normal} <" << std::string(technique->getName()) << "> failed to compile." << endl << endl
|
||||||
<< technique->getLastError();
|
<< technique->getLastError();
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
|
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
|
||||||
|
#include "../mwrender/postprocessor.hpp"
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
|
@ -271,6 +273,7 @@ namespace MWLua
|
||||||
LuaUi::clearUserInterface();
|
LuaUi::clearUserInterface();
|
||||||
mUiResourceManager.clear();
|
mUiResourceManager.clear();
|
||||||
MWBase::Environment::get().getWindowManager()->setConsoleMode("");
|
MWBase::Environment::get().getWindowManager()->setConsoleMode("");
|
||||||
|
MWBase::Environment::get().getWorld()->getPostProcessor()->disableDynamicShaders();
|
||||||
mActiveLocalScripts.clear();
|
mActiveLocalScripts.clear();
|
||||||
mLocalEvents.clear();
|
mLocalEvents.clear();
|
||||||
mGlobalEvents.clear();
|
mGlobalEvents.clear();
|
||||||
|
|
|
@ -117,10 +117,9 @@ namespace MWLua
|
||||||
[=, &shader] {
|
[=, &shader] {
|
||||||
shader.mQueuedAction = Shader::Action_None;
|
shader.mQueuedAction = Shader::Action_None;
|
||||||
|
|
||||||
if (!MWBase::Environment::get().getWorld()->getPostProcessor()->enableTechnique(shader.mShader, pos))
|
if (MWBase::Environment::get().getWorld()->getPostProcessor()->enableTechnique(shader.mShader, pos) == MWRender::PostProcessor::Status_Error)
|
||||||
throw std::runtime_error("Failed enabling shader '" + shader.mShader->getName() + "'");
|
throw std::runtime_error("Failed enabling shader '" + shader.mShader->getName() + "'");
|
||||||
},
|
}
|
||||||
"Enable shader " + (shader.mShader ? shader.mShader->getName() : "nil")
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -132,10 +131,9 @@ namespace MWLua
|
||||||
[&] {
|
[&] {
|
||||||
shader.mQueuedAction = Shader::Action_None;
|
shader.mQueuedAction = Shader::Action_None;
|
||||||
|
|
||||||
if (!MWBase::Environment::get().getWorld()->getPostProcessor()->disableTechnique(shader.mShader))
|
if (MWBase::Environment::get().getWorld()->getPostProcessor()->disableTechnique(shader.mShader) == MWRender::PostProcessor::Status_Error)
|
||||||
throw std::runtime_error("Failed disabling shader '" + shader.mShader->getName() + "'");
|
throw std::runtime_error("Failed disabling shader '" + shader.mShader->getName() + "'");
|
||||||
},
|
}
|
||||||
"Disable shader " + (shader.mShader ? shader.mShader->getName() : "nil")
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -168,6 +166,9 @@ namespace MWLua
|
||||||
if (!shader.mShader || !shader.mShader->isValid())
|
if (!shader.mShader || !shader.mShader->isValid())
|
||||||
throw std::runtime_error(Misc::StringUtils::format("Failed loading shader '%s'", name));
|
throw std::runtime_error(Misc::StringUtils::format("Failed loading shader '%s'", name));
|
||||||
|
|
||||||
|
if (!shader.mShader->getDynamic())
|
||||||
|
throw std::runtime_error(Misc::StringUtils::format("Shader '%s' is not marked as dynamic", name));
|
||||||
|
|
||||||
return shader;
|
return shader;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -182,7 +182,6 @@ namespace MWRender
|
||||||
if (!path.parent_path().has_parent_path() && fileExt == fx::Technique::sExt)
|
if (!path.parent_path().has_parent_path() && fileExt == fx::Technique::sExt)
|
||||||
{
|
{
|
||||||
auto absolutePath = std::filesystem::path(mVFS->getAbsoluteFileName(name));
|
auto absolutePath = std::filesystem::path(mVFS->getAbsoluteFileName(name));
|
||||||
|
|
||||||
mTechniqueFileMap[absolutePath.stem().string()] = absolutePath;
|
mTechniqueFileMap[absolutePath.stem().string()] = absolutePath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -210,7 +209,6 @@ namespace MWRender
|
||||||
if (mUsePostProcessing && mTechniqueFileMap.empty())
|
if (mUsePostProcessing && mTechniqueFileMap.empty())
|
||||||
{
|
{
|
||||||
populateTechniqueFiles();
|
populateTechniqueFiles();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mMainTemplate->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
|
mMainTemplate->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
|
||||||
|
@ -648,16 +646,16 @@ namespace MWRender
|
||||||
mRendering.getSkyManager()->setSunglare(sunglare);
|
mRendering.getSkyManager()->setSunglare(sunglare);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PostProcessor::enableTechnique(std::shared_ptr<fx::Technique> technique, std::optional<int> location)
|
PostProcessor::Status PostProcessor::enableTechnique(std::shared_ptr<fx::Technique> technique, std::optional<int> location)
|
||||||
{
|
{
|
||||||
if (!isEnabled())
|
if (!isEnabled())
|
||||||
{
|
{
|
||||||
Log(Debug::Warning) << "PostProcessing disabled, cannot load technique '" << technique->getName() << "'";
|
Log(Debug::Warning) << "PostProcessing disabled, cannot load technique '" << technique->getName() << "'";
|
||||||
return false;
|
return Status_Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!technique || Misc::StringUtils::ciEqual(technique->getName(), "main") || (location.has_value() && location.value() <= 0))
|
if (!technique || Misc::StringUtils::ciEqual(technique->getName(), "main") || (location.has_value() && location.value() <= 0))
|
||||||
return false;
|
return Status_Error;
|
||||||
|
|
||||||
disableTechnique(technique, false);
|
disableTechnique(technique, false);
|
||||||
|
|
||||||
|
@ -666,23 +664,23 @@ namespace MWRender
|
||||||
mTechniques.insert(mTechniques.begin() + pos, technique);
|
mTechniques.insert(mTechniques.begin() + pos, technique);
|
||||||
dirtyTechniques();
|
dirtyTechniques();
|
||||||
|
|
||||||
return true;
|
return Status_Toggled;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PostProcessor::disableTechnique(std::shared_ptr<fx::Technique> technique, bool dirty)
|
PostProcessor::Status PostProcessor::disableTechnique(std::shared_ptr<fx::Technique> technique, bool dirty)
|
||||||
{
|
{
|
||||||
if (Misc::StringUtils::ciEqual(technique->getName(), "main"))
|
if (Misc::StringUtils::ciEqual(technique->getName(), "main"))
|
||||||
return false;
|
return Status_Error;
|
||||||
|
|
||||||
auto it = std::find(mTechniques.begin(), mTechniques.end(), technique);
|
auto it = std::find(mTechniques.begin(), mTechniques.end(), technique);
|
||||||
if (it == std::end(mTechniques))
|
if (it == std::end(mTechniques))
|
||||||
return false;
|
return Status_Unchanged;
|
||||||
|
|
||||||
mTechniques.erase(it);
|
mTechniques.erase(it);
|
||||||
if (dirty)
|
if (dirty)
|
||||||
dirtyTechniques();
|
dirtyTechniques();
|
||||||
|
|
||||||
return true;
|
return Status_Toggled;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PostProcessor::isTechniqueEnabled(const std::shared_ptr<fx::Technique>& technique) const
|
bool PostProcessor::isTechniqueEnabled(const std::shared_ptr<fx::Technique>& technique) const
|
||||||
|
@ -792,7 +790,7 @@ namespace MWRender
|
||||||
if (technique->getStatus() != fx::Technique::Status::File_Not_exists)
|
if (technique->getStatus() != fx::Technique::Status::File_Not_exists)
|
||||||
technique->setLastModificationTime(std::filesystem::last_write_time(mTechniqueFileMap[technique->getName()]));
|
technique->setLastModificationTime(std::filesystem::last_write_time(mTechniqueFileMap[technique->getName()]));
|
||||||
|
|
||||||
if (!loadNextFrame)
|
if (loadNextFrame)
|
||||||
{
|
{
|
||||||
mQueuedTemplates.push_back(technique);
|
mQueuedTemplates.push_back(technique);
|
||||||
return technique;
|
return technique;
|
||||||
|
@ -853,5 +851,12 @@ namespace MWRender
|
||||||
|
|
||||||
dirtyTechniques();
|
dirtyTechniques();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PostProcessor::disableDynamicShaders()
|
||||||
|
{
|
||||||
|
for (auto& technique : mTechniques)
|
||||||
|
if (technique->getDynamic())
|
||||||
|
disableTechnique(technique);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,9 +110,16 @@ namespace MWRender
|
||||||
|
|
||||||
void resize();
|
void resize();
|
||||||
|
|
||||||
bool enableTechnique(std::shared_ptr<fx::Technique> technique, std::optional<int> location = std::nullopt);
|
enum Status
|
||||||
|
{
|
||||||
|
Status_Error,
|
||||||
|
Status_Toggled,
|
||||||
|
Status_Unchanged
|
||||||
|
};
|
||||||
|
|
||||||
bool disableTechnique(std::shared_ptr<fx::Technique> technique, bool dirty = true);
|
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; }
|
bool getSupportsNormalsRT() const { return mNormalsSupported; }
|
||||||
|
|
||||||
|
@ -154,7 +161,7 @@ namespace MWRender
|
||||||
|
|
||||||
void toggleMode();
|
void toggleMode();
|
||||||
|
|
||||||
std::shared_ptr<fx::Technique> loadTechnique(const std::string& name, bool loadNextFrame=true);
|
std::shared_ptr<fx::Technique> loadTechnique(const std::string& name, bool loadNextFrame=false);
|
||||||
|
|
||||||
bool isEnabled() const { return mUsePostProcessing && mEnabled; }
|
bool isEnabled() const { return mUsePostProcessing && mEnabled; }
|
||||||
|
|
||||||
|
@ -168,6 +175,8 @@ namespace MWRender
|
||||||
|
|
||||||
void setRenderTargetSize(int width, int height) { mWidth = width; mHeight = height; }
|
void setRenderTargetSize(int width, int height) { mWidth = width; mHeight = height; }
|
||||||
|
|
||||||
|
void disableDynamicShaders();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void populateTechniqueFiles();
|
void populateTechniqueFiles();
|
||||||
|
|
|
@ -75,6 +75,7 @@ namespace fx
|
||||||
mGLSLExtensions.clear();
|
mGLSLExtensions.clear();
|
||||||
mGLSLVersion = mUBO ? 330 : 120;
|
mGLSLVersion = mUBO ? 330 : 120;
|
||||||
mGLSLProfile.clear();
|
mGLSLProfile.clear();
|
||||||
|
mDynamic = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Technique::getBlockWithLineDirective()
|
std::string Technique::getBlockWithLineDirective()
|
||||||
|
@ -249,11 +250,13 @@ namespace fx
|
||||||
for (const auto& ext : parseLiteralList<Lexer::Comma>())
|
for (const auto& ext : parseLiteralList<Lexer::Comma>())
|
||||||
mGLSLExtensions.emplace(ext);
|
mGLSLExtensions.emplace(ext);
|
||||||
}
|
}
|
||||||
|
else if (key == "dynamic")
|
||||||
|
mDynamic = parseBool();
|
||||||
else
|
else
|
||||||
error(Misc::StringUtils::format("unexpected key '%s'", std::string{key}));
|
error(Misc::StringUtils::format("unexpected key '%s'", std::string{key}));
|
||||||
|
|
||||||
expect<Lexer::SemiColon>();
|
expect<Lexer::SemiColon>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mPassKeys.empty())
|
if (mPassKeys.empty())
|
||||||
error("pass list in 'technique' block cannot be empty.");
|
error("pass list in 'technique' block cannot be empty.");
|
||||||
|
|
|
@ -159,6 +159,8 @@ namespace fx
|
||||||
|
|
||||||
UniformMap::iterator findUniform(const std::string& name);
|
UniformMap::iterator findUniform(const std::string& name);
|
||||||
|
|
||||||
|
bool getDynamic() const { return mDynamic; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
[[noreturn]] void error(const std::string& msg);
|
[[noreturn]] void error(const std::string& msg);
|
||||||
|
|
||||||
|
@ -275,6 +277,8 @@ namespace fx
|
||||||
std::string mBuffer;
|
std::string mBuffer;
|
||||||
|
|
||||||
std::string mLastError;
|
std::string mLastError;
|
||||||
|
|
||||||
|
bool mDynamic = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> void Technique::parseBlockImp<Lexer::Shared>();
|
template<> void Technique::parseBlockImp<Lexer::Shared>();
|
||||||
|
|
|
@ -5,8 +5,8 @@ Connecting With Lua
|
||||||
Overview
|
Overview
|
||||||
########
|
########
|
||||||
|
|
||||||
Every shader can be controlled through the Lua scripting system. While shaders can be disabled and enabled,
|
Every shader that is marked as ``dynamic`` can be controlled through the Lua scripting system. Shaders can be disabled and enabled,
|
||||||
shader uniforms can also be controlled. For details reference the API documentation, found :doc:`here<../lua-scripting/openmw_postprocessing>`.
|
and their uniforms can be controlled via scripts. For details, reference the API documentation :doc:`here<../lua-scripting/openmw_postprocessing>`.
|
||||||
|
|
||||||
Toggling Shaders With a Keybind
|
Toggling Shaders With a Keybind
|
||||||
###############################
|
###############################
|
||||||
|
@ -42,12 +42,14 @@ It is assumed the shader has the filename ``desaturate.omwfx`` in this example.
|
||||||
|
|
||||||
technique {
|
technique {
|
||||||
description = "Desaturates scene";
|
description = "Desaturates scene";
|
||||||
passes = desaturate;
|
|
||||||
version = "1.0";
|
version = "1.0";
|
||||||
author = "Fargoth";
|
author = "Fargoth";
|
||||||
passes = desaturate;
|
passes = desaturate;
|
||||||
|
dynamic = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
The ``dynamic`` flag here is very important, otherwise Lua will not be able to interact with this shader.
|
||||||
|
|
||||||
Next, a script that is attached to the player is needed. The shader is loaded first, then toggled on and off in response to key presses.
|
Next, a script that is attached to the player is needed. The shader is loaded first, then toggled on and off in response to key presses.
|
||||||
Below is a working example to illustrate this.
|
Below is a working example to illustrate this.
|
||||||
|
@ -83,11 +85,11 @@ hidden in this HUD, this can done by adding the ``hidden`` flag to the main tech
|
||||||
|
|
||||||
technique {
|
technique {
|
||||||
description = "Desaturates scene";
|
description = "Desaturates scene";
|
||||||
passes = desaturate;
|
|
||||||
version = "1.0";
|
version = "1.0";
|
||||||
author = "Fargoth";
|
author = "Fargoth";
|
||||||
passes = desaturate;
|
passes = desaturate;
|
||||||
flags = hidden;
|
flags = hidden;
|
||||||
|
dynamic = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
This flag is usually used when the shader is associated with something special, like special weather, spell, or alcohol effects.
|
This flag is usually used when the shader is associated with something special, like special weather, spell, or alcohol effects.
|
||||||
|
|
|
@ -314,6 +314,11 @@ Exactly one ``technique`` block is required for every shader file. In this we de
|
||||||
+------------------+--------------------+---------------------------------------------------+
|
+------------------+--------------------+---------------------------------------------------+
|
||||||
| flags | `SHADER_FLAG`_ | ``,`` separated list of shader flags |
|
| flags | `SHADER_FLAG`_ | ``,`` separated list of shader flags |
|
||||||
+------------------+--------------------+---------------------------------------------------+
|
+------------------+--------------------+---------------------------------------------------+
|
||||||
|
| dynamic | boolean | Whether shader is exposed to Lua |
|
||||||
|
+------------------+--------------------+---------------------------------------------------+
|
||||||
|
|
||||||
|
When ``dynamic`` is set to ``true``, the shaders order cannot be manually moved, enabled, or disabled. The shaders state
|
||||||
|
can only be controlled via a Lua script.
|
||||||
|
|
||||||
In the code snippet below, a shader is defined that requires GLSL `330`, HDR capatiblities, and is only enabled underwater in exteriors.
|
In the code snippet below, a shader is defined that requires GLSL `330`, HDR capatiblities, and is only enabled underwater in exteriors.
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue