2025-02-22 21:14:58 +03:00
|
|
|
#ifndef OPENMW_COMPONENTS_FX_TYPES_HPP
|
|
|
|
#define OPENMW_COMPONENTS_FX_TYPES_HPP
|
2022-05-13 18:58:00 -07:00
|
|
|
|
|
|
|
#include <optional>
|
2022-08-03 00:00:54 +02:00
|
|
|
#include <variant>
|
2022-05-13 18:58:00 -07:00
|
|
|
|
|
|
|
#include <osg/Texture2D>
|
|
|
|
#include <osg/Uniform>
|
|
|
|
|
|
|
|
#include <components/debug/debuglog.hpp>
|
2022-08-03 00:00:54 +02:00
|
|
|
#include <components/misc/strings/format.hpp>
|
2022-05-13 18:58:00 -07:00
|
|
|
#include <components/sceneutil/depth.hpp>
|
|
|
|
#include <components/settings/shadermanager.hpp>
|
|
|
|
|
|
|
|
namespace fx
|
|
|
|
{
|
|
|
|
namespace Types
|
|
|
|
{
|
|
|
|
struct SizeProxy
|
|
|
|
{
|
|
|
|
std::optional<float> mWidthRatio;
|
|
|
|
std::optional<float> mHeightRatio;
|
|
|
|
std::optional<int> mWidth;
|
|
|
|
std::optional<int> mHeight;
|
|
|
|
|
|
|
|
std::tuple<int, int> get(int width, int height) const
|
|
|
|
{
|
|
|
|
int scaledWidth = width;
|
|
|
|
int scaledHeight = height;
|
|
|
|
|
|
|
|
if (mWidthRatio)
|
|
|
|
scaledWidth = width * mWidthRatio.value();
|
|
|
|
else if (mWidth)
|
|
|
|
scaledWidth = mWidth.value();
|
|
|
|
|
|
|
|
if (mHeightRatio > 0.f)
|
|
|
|
scaledHeight = height * mHeightRatio.value();
|
|
|
|
else if (mHeight)
|
|
|
|
scaledHeight = mHeight.value();
|
|
|
|
|
|
|
|
return std::make_tuple(scaledWidth, scaledHeight);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct RenderTarget
|
|
|
|
{
|
|
|
|
osg::ref_ptr<osg::Texture2D> mTarget = new osg::Texture2D;
|
|
|
|
SizeProxy mSize;
|
|
|
|
bool mMipMap = false;
|
2023-11-10 21:22:11 -08:00
|
|
|
osg::Vec4f mClearColor = osg::Vec4f(0.0, 0.0, 0.0, 1.0);
|
2022-05-13 18:58:00 -07:00
|
|
|
};
|
|
|
|
|
2024-03-21 17:48:30 -07:00
|
|
|
template <class T>
|
|
|
|
struct Choice
|
|
|
|
{
|
|
|
|
std::string mLabel;
|
|
|
|
T mValue;
|
|
|
|
};
|
|
|
|
|
2022-05-13 18:58:00 -07:00
|
|
|
template <class T>
|
|
|
|
struct Uniform
|
|
|
|
{
|
|
|
|
std::optional<T> mValue;
|
2022-05-22 18:53:38 -07:00
|
|
|
std::optional<std::vector<T>> mArray;
|
|
|
|
|
|
|
|
T mDefault = {};
|
2022-05-13 18:58:00 -07:00
|
|
|
T mMin = std::numeric_limits<T>::lowest();
|
|
|
|
T mMax = std::numeric_limits<T>::max();
|
|
|
|
|
2024-03-21 17:48:30 -07:00
|
|
|
std::vector<Choice<T>> mChoices;
|
|
|
|
|
2022-05-13 18:58:00 -07:00
|
|
|
using value_type = T;
|
|
|
|
|
2022-05-22 18:53:38 -07:00
|
|
|
bool isArray() const { return mArray.has_value(); }
|
|
|
|
|
|
|
|
const std::vector<T>& getArray() const { return *mArray; }
|
|
|
|
|
2022-05-13 18:58:00 -07:00
|
|
|
T getValue() const { return mValue.value_or(mDefault); }
|
|
|
|
};
|
|
|
|
|
|
|
|
using Uniform_t = std::variant<Uniform<osg::Vec2f>, Uniform<osg::Vec3f>, Uniform<osg::Vec4f>, Uniform<bool>,
|
|
|
|
Uniform<float>, Uniform<int>>;
|
|
|
|
|
|
|
|
enum SamplerType
|
|
|
|
{
|
|
|
|
Texture_1D,
|
|
|
|
Texture_2D,
|
|
|
|
Texture_3D
|
|
|
|
};
|
|
|
|
|
|
|
|
struct UniformBase
|
|
|
|
{
|
|
|
|
std::string mName;
|
2022-05-25 19:17:31 -07:00
|
|
|
std::string mDisplayName;
|
2022-05-13 18:58:00 -07:00
|
|
|
std::string mHeader;
|
|
|
|
std::string mTechniqueName;
|
|
|
|
std::string mDescription;
|
|
|
|
|
|
|
|
bool mStatic = true;
|
|
|
|
std::optional<SamplerType> mSamplerType = std::nullopt;
|
2022-05-22 18:53:38 -07:00
|
|
|
double mStep = 1.0;
|
2022-05-13 18:58:00 -07:00
|
|
|
|
|
|
|
Uniform_t mData;
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
T getValue() const
|
|
|
|
{
|
|
|
|
auto value = Settings::ShaderManager::get().getValue<T>(mTechniqueName, mName);
|
|
|
|
|
|
|
|
return value.value_or(std::get<Uniform<T>>(mData).getValue());
|
|
|
|
}
|
|
|
|
|
2022-05-22 18:53:38 -07:00
|
|
|
size_t getNumElements() const
|
|
|
|
{
|
|
|
|
return std::visit(
|
|
|
|
[&](auto&& arg) {
|
|
|
|
;
|
|
|
|
return arg.isArray() ? arg.getArray().size() : 1;
|
|
|
|
},
|
|
|
|
mData);
|
|
|
|
}
|
|
|
|
|
2022-05-13 18:58:00 -07:00
|
|
|
template <class T>
|
|
|
|
T getMin() const
|
|
|
|
{
|
|
|
|
return std::get<Uniform<T>>(mData).mMin;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
T getMax() const
|
|
|
|
{
|
|
|
|
return std::get<Uniform<T>>(mData).mMax;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
T getDefault() const
|
|
|
|
{
|
|
|
|
return std::get<Uniform<T>>(mData).mDefault;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
void setValue(const T& value)
|
|
|
|
{
|
|
|
|
std::visit(
|
|
|
|
[&, value](auto&& arg) {
|
|
|
|
using U = typename std::decay_t<decltype(arg)>::value_type;
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2022-05-13 18:58:00 -07:00
|
|
|
if constexpr (std::is_same_v<T, U>)
|
|
|
|
{
|
|
|
|
arg.mValue = value;
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2022-05-22 18:53:38 -07:00
|
|
|
Settings::ShaderManager::get().setValue(mTechniqueName, mName, value);
|
2022-05-13 18:58:00 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Log(Debug::Warning) << "Attempting to set uniform '" << mName << "' with wrong type";
|
|
|
|
}
|
|
|
|
},
|
|
|
|
mData);
|
|
|
|
}
|
|
|
|
|
2022-05-22 18:53:38 -07:00
|
|
|
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;
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2022-05-22 18:53:38 -07:00
|
|
|
if (!arg.isArray() || arg.getArray().size() != value.size())
|
|
|
|
{
|
|
|
|
Log(Debug::Error)
|
|
|
|
<< "Attempting to set uniform array '" << mName << "' with mismatching array sizes";
|
|
|
|
return;
|
|
|
|
}
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2022-05-22 18:53:38 -07:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2022-05-13 18:58:00 -07:00
|
|
|
void setUniform(osg::Uniform* uniform)
|
|
|
|
{
|
|
|
|
auto type = getType();
|
|
|
|
if (!type || type.value() != uniform->getType())
|
|
|
|
return;
|
|
|
|
|
|
|
|
std::visit(
|
|
|
|
[&](auto&& arg) {
|
2022-05-22 18:53:38 -07:00
|
|
|
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());
|
2022-05-13 18:58:00 -07:00
|
|
|
},
|
|
|
|
mData);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<osg::Uniform::Type> getType() const
|
|
|
|
{
|
|
|
|
return std::visit(
|
|
|
|
[](auto&& arg) -> std::optional<osg::Uniform::Type> {
|
|
|
|
using T = typename std::decay_t<decltype(arg)>::value_type;
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2022-05-13 18:58:00 -07:00
|
|
|
if constexpr (std::is_same_v<T, osg::Vec2f>)
|
|
|
|
return osg::Uniform::FLOAT_VEC2;
|
|
|
|
else if constexpr (std::is_same_v<T, osg::Vec3f>)
|
|
|
|
return osg::Uniform::FLOAT_VEC3;
|
|
|
|
else if constexpr (std::is_same_v<T, osg::Vec4f>)
|
|
|
|
return osg::Uniform::FLOAT_VEC4;
|
|
|
|
else if constexpr (std::is_same_v<T, float>)
|
|
|
|
return osg::Uniform::FLOAT;
|
|
|
|
else if constexpr (std::is_same_v<T, int>)
|
|
|
|
return osg::Uniform::INT;
|
|
|
|
else if constexpr (std::is_same_v<T, bool>)
|
|
|
|
return osg::Uniform::BOOL;
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2022-05-13 18:58:00 -07:00
|
|
|
return std::nullopt;
|
|
|
|
},
|
|
|
|
mData);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<std::string> getGLSL()
|
|
|
|
{
|
|
|
|
if (mSamplerType)
|
|
|
|
{
|
|
|
|
switch (mSamplerType.value())
|
|
|
|
{
|
|
|
|
case Texture_1D:
|
|
|
|
return Misc::StringUtils::format("uniform sampler1D %s;", mName);
|
|
|
|
case Texture_2D:
|
|
|
|
return Misc::StringUtils::format("uniform sampler2D %s;", mName);
|
|
|
|
case Texture_3D:
|
|
|
|
return Misc::StringUtils::format("uniform sampler3D %s;", mName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return std::visit(
|
|
|
|
[&](auto&& arg) -> std::optional<std::string> {
|
|
|
|
using T = typename std::decay_t<decltype(arg)>::value_type;
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2022-05-13 18:58:00 -07:00
|
|
|
auto value = arg.getValue();
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2022-05-22 18:53:38 -07:00
|
|
|
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;
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2022-05-13 18:58:00 -07:00
|
|
|
if constexpr (std::is_same_v<T, osg::Vec2f>)
|
|
|
|
{
|
|
|
|
if (useUniform)
|
2022-05-22 18:53:38 -07:00
|
|
|
return Misc::StringUtils::format("uniform vec2 %s;", uname);
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2022-05-13 18:58:00 -07:00
|
|
|
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)
|
2022-05-22 18:53:38 -07:00
|
|
|
return Misc::StringUtils::format("uniform vec3 %s;", uname);
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2022-05-13 18:58:00 -07:00
|
|
|
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)
|
2022-05-22 18:53:38 -07:00
|
|
|
return Misc::StringUtils::format("uniform vec4 %s;", uname);
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2022-05-13 18:58:00 -07:00
|
|
|
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)
|
2022-05-22 18:53:38 -07:00
|
|
|
return Misc::StringUtils::format("uniform float %s;", uname);
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2022-05-13 18:58:00 -07:00
|
|
|
return Misc::StringUtils::format("const float %s=%f;", mName, value);
|
|
|
|
}
|
|
|
|
else if constexpr (std::is_same_v<T, int>)
|
|
|
|
{
|
|
|
|
if (useUniform)
|
2022-05-22 18:53:38 -07:00
|
|
|
return Misc::StringUtils::format("uniform int %s;", uname);
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2022-05-13 18:58:00 -07:00
|
|
|
return Misc::StringUtils::format("const int %s=%i;", mName, value);
|
|
|
|
}
|
|
|
|
else if constexpr (std::is_same_v<T, bool>)
|
|
|
|
{
|
|
|
|
if (useUniform)
|
2022-05-22 18:53:38 -07:00
|
|
|
return Misc::StringUtils::format("uniform bool %s;", uname);
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2022-05-13 18:58:00 -07:00
|
|
|
return Misc::StringUtils::format("const bool %s=%s;", mName, value ? "true" : "false");
|
|
|
|
}
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2022-05-13 18:58:00 -07:00
|
|
|
return std::nullopt;
|
|
|
|
},
|
|
|
|
mData);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|