mirror of https://github.com/AxioDL/metaforce.git
CModelShaders implementation updates (WIP)
This commit is contained in:
parent
d07f5320bd
commit
7bffc621b8
|
@ -10,6 +10,69 @@
|
||||||
|
|
||||||
#include "zeus/CAABox.hpp"
|
#include "zeus/CAABox.hpp"
|
||||||
|
|
||||||
|
namespace urde {
|
||||||
|
using BlendMaterial = hecl::blender::Material;
|
||||||
|
using MaterialBlendMode = BlendMaterial::BlendMode;
|
||||||
|
|
||||||
|
enum class MaterialTexCoordSource : uint32_t {
|
||||||
|
Invalid = 0xff,
|
||||||
|
Position = 0,
|
||||||
|
Normal = 1,
|
||||||
|
Tex0 = 2,
|
||||||
|
Tex1 = 3,
|
||||||
|
Tex2 = 4,
|
||||||
|
Tex3 = 5,
|
||||||
|
Tex4 = 6,
|
||||||
|
Tex5 = 7,
|
||||||
|
Tex6 = 8,
|
||||||
|
Tex7 = 9,
|
||||||
|
};
|
||||||
|
|
||||||
|
// FIXME hsh bug: u8 generates '\xCC', '\xCC', '\xCC', '\xFF' which cause issues
|
||||||
|
template <bool HasValue, int R = 0, int G = 0, int B = 0, int A = 0>
|
||||||
|
struct ColorValue {
|
||||||
|
static constexpr bool Constant = HasValue;
|
||||||
|
static constexpr float R_ = u8(R) / 255.f;
|
||||||
|
static constexpr float G_ = u8(G) / 255.f;
|
||||||
|
static constexpr float B_ = u8(B) / 255.f;
|
||||||
|
static constexpr float A_ = u8(A) / 255.f;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <MaterialTexCoordSource Source, bool Normalize, int MtxIdx, bool SampleAlpha,
|
||||||
|
class ConstantColor = ColorValue<false>>
|
||||||
|
struct PassTraits {
|
||||||
|
static constexpr MaterialTexCoordSource Source_ = Source;
|
||||||
|
static constexpr bool Normalize_ = Normalize;
|
||||||
|
static constexpr int MtxIdx_ = MtxIdx;
|
||||||
|
static constexpr bool SampleAlpha_ = SampleAlpha;
|
||||||
|
using ConstantColor_ = ConstantColor;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <int R, int G, int B, int A = 255>
|
||||||
|
using PassConstantColor = PassTraits<MaterialTexCoordSource::Invalid, false, -1, false, ColorValue<true, R, G, B, A>>;
|
||||||
|
|
||||||
|
template <MaterialTexCoordSource Source, int MtxIdx = -1>
|
||||||
|
using PassTex = PassTraits<Source, false, MtxIdx, false>;
|
||||||
|
|
||||||
|
template <bool Normalize = true, int MtxIdx = -1>
|
||||||
|
using PassNormal = PassTraits<MaterialTexCoordSource::Normal, Normalize, MtxIdx, false>;
|
||||||
|
|
||||||
|
using PassNone = PassTraits<MaterialTexCoordSource::Invalid, false, -1, false>;
|
||||||
|
|
||||||
|
template <bool CubeReflection>
|
||||||
|
struct DynReflectionTex {
|
||||||
|
using type = hsh::texture2d;
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct DynReflectionTex<true> {
|
||||||
|
using type = hsh::texturecube;
|
||||||
|
};
|
||||||
|
template <bool CubeReflection>
|
||||||
|
using DynReflectionTexType = typename DynReflectionTex<CubeReflection>::type;
|
||||||
|
} // namespace urde
|
||||||
|
|
||||||
|
#include "CModelShaders.cpp.hshhead"
|
||||||
|
|
||||||
namespace urde {
|
namespace urde {
|
||||||
|
|
||||||
void CModelShaders::FragmentUniform::ActivateLights(const std::vector<CLight>& lts) {
|
void CModelShaders::FragmentUniform::ActivateLights(const std::vector<CLight>& lts) {
|
||||||
|
@ -60,109 +123,24 @@ void CModelShaders::FragmentUniform::ActivateLights(const std::vector<CLight>& l
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
using TexCoordSource = hecl::Backend::TexCoordSource;
|
//constexpr std::array<hecl::Backend::TextureInfo, 1> ThermalTextures{{
|
||||||
|
// {TexCoordSource::Normal, 7, true},
|
||||||
constexpr std::array<hecl::Backend::TextureInfo, 1> ThermalTextures{{
|
//}};
|
||||||
{TexCoordSource::Normal, 7, true},
|
//
|
||||||
}};
|
//constexpr std::array<hecl::Backend::TextureInfo, 3> BallFadeTextures{{
|
||||||
|
// {TexCoordSource::Position, 0, false}, // ID tex
|
||||||
constexpr std::array<hecl::Backend::TextureInfo, 3> BallFadeTextures{{
|
// {TexCoordSource::Position, 0, false}, // Sphere ramp
|
||||||
{TexCoordSource::Position, 0, false}, // ID tex
|
// {TexCoordSource::Position, 1, false}, // TXTR_BallFade
|
||||||
{TexCoordSource::Position, 0, false}, // Sphere ramp
|
//}};
|
||||||
{TexCoordSource::Position, 1, false}, // TXTR_BallFade
|
//
|
||||||
}};
|
//constexpr std::array<hecl::Backend::TextureInfo, 1> WorldShadowTextures{{
|
||||||
|
// {TexCoordSource::Position, 7, false}, // Shadow tex
|
||||||
constexpr std::array<hecl::Backend::TextureInfo, 1> WorldShadowTextures{{
|
//}};
|
||||||
{TexCoordSource::Position, 7, false}, // Shadow tex
|
//
|
||||||
}};
|
//constexpr std::array<hecl::Backend::TextureInfo, 2> DisintegrateTextures{{
|
||||||
|
// {TexCoordSource::Position, 0, false}, // Ashy tex
|
||||||
constexpr std::array<hecl::Backend::TextureInfo, 2> DisintegrateTextures{{
|
// {TexCoordSource::Position, 1, false}, // Ashy tex
|
||||||
{TexCoordSource::Position, 0, false}, // Ashy tex
|
//}};
|
||||||
{TexCoordSource::Position, 1, false}, // Ashy tex
|
|
||||||
}};
|
|
||||||
|
|
||||||
static std::array<hecl::Backend::ExtensionSlot, size_t(EExtendedShader::MAX)> g_ExtensionSlots{{
|
|
||||||
/* Default solid shading */
|
|
||||||
{},
|
|
||||||
/* Normal lit shading */
|
|
||||||
{0, nullptr, hecl::Backend::BlendFactor::Original, hecl::Backend::BlendFactor::Original,
|
|
||||||
hecl::Backend::ZTest::Original, hecl::Backend::CullMode::Backface, false, false, true},
|
|
||||||
/* Thermal Visor shading */
|
|
||||||
{1, ThermalTextures.data(), hecl::Backend::BlendFactor::One, hecl::Backend::BlendFactor::One,
|
|
||||||
hecl::Backend::ZTest::Original, hecl::Backend::CullMode::Backface, false, false, false, true},
|
|
||||||
/* Forced alpha shading */
|
|
||||||
{0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::InvSrcAlpha,
|
|
||||||
hecl::Backend::ZTest::Original, hecl::Backend::CullMode::Backface, false, false, true},
|
|
||||||
/* Forced additive shading */
|
|
||||||
{0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::One, hecl::Backend::ZTest::Original,
|
|
||||||
hecl::Backend::CullMode::Backface, false, false, true},
|
|
||||||
/* Solid color */
|
|
||||||
{0, nullptr, hecl::Backend::BlendFactor::One, hecl::Backend::BlendFactor::Zero, hecl::Backend::ZTest::LEqual,
|
|
||||||
hecl::Backend::CullMode::Backface, false, false, false},
|
|
||||||
/* Solid color additive */
|
|
||||||
{0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::One, hecl::Backend::ZTest::LEqual,
|
|
||||||
hecl::Backend::CullMode::Backface, true, false, true},
|
|
||||||
/* Alpha-only Solid color frontface cull, LEqual */
|
|
||||||
{0, nullptr, hecl::Backend::BlendFactor::Zero, hecl::Backend::BlendFactor::One, hecl::Backend::ZTest::LEqual,
|
|
||||||
hecl::Backend::CullMode::Frontface, false, true, false},
|
|
||||||
/* Alpha-only Solid color frontface cull, Always, No Z-write */
|
|
||||||
{0, nullptr, hecl::Backend::BlendFactor::Zero, hecl::Backend::BlendFactor::One, hecl::Backend::ZTest::None,
|
|
||||||
hecl::Backend::CullMode::Frontface, true, true, false},
|
|
||||||
/* Alpha-only Solid color backface cull, LEqual */
|
|
||||||
{0, nullptr, hecl::Backend::BlendFactor::Zero, hecl::Backend::BlendFactor::One, hecl::Backend::ZTest::LEqual,
|
|
||||||
hecl::Backend::CullMode::Backface, false, true, false},
|
|
||||||
/* Alpha-only Solid color backface cull, Greater, No Z-write */
|
|
||||||
{0, nullptr, hecl::Backend::BlendFactor::Zero, hecl::Backend::BlendFactor::One, hecl::Backend::ZTest::Greater,
|
|
||||||
hecl::Backend::CullMode::Backface, true, true, false},
|
|
||||||
/* MorphBall shadow shading */
|
|
||||||
{3, BallFadeTextures.data(), hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::InvSrcAlpha,
|
|
||||||
hecl::Backend::ZTest::Equal, hecl::Backend::CullMode::Backface, false, false, true, false, true},
|
|
||||||
/* World shadow shading (modified lighting) */
|
|
||||||
{1, WorldShadowTextures.data(), hecl::Backend::BlendFactor::Original, hecl::Backend::BlendFactor::Original,
|
|
||||||
hecl::Backend::ZTest::Original, hecl::Backend::CullMode::Backface, false, false, true},
|
|
||||||
/* Forced alpha shading without culling */
|
|
||||||
{0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::InvSrcAlpha,
|
|
||||||
hecl::Backend::ZTest::Original, hecl::Backend::CullMode::None, false, false, true},
|
|
||||||
/* Forced additive shading without culling */
|
|
||||||
{0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::One, hecl::Backend::ZTest::Original,
|
|
||||||
hecl::Backend::CullMode::None, false, false, true},
|
|
||||||
/* Forced alpha shading without Z-write */
|
|
||||||
{0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::InvSrcAlpha,
|
|
||||||
hecl::Backend::ZTest::Original, hecl::Backend::CullMode::Original, true, false, true},
|
|
||||||
/* Forced additive shading without Z-write */
|
|
||||||
{0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::One, hecl::Backend::ZTest::Original,
|
|
||||||
hecl::Backend::CullMode::Original, true, false, true},
|
|
||||||
/* Forced alpha shading without culling or Z-write */
|
|
||||||
{0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::InvSrcAlpha,
|
|
||||||
hecl::Backend::ZTest::Original, hecl::Backend::CullMode::None, true, false, true},
|
|
||||||
/* Forced additive shading without culling or Z-write */
|
|
||||||
{0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::One, hecl::Backend::ZTest::Original,
|
|
||||||
hecl::Backend::CullMode::None, true, false, true},
|
|
||||||
/* Depth GEqual no Z-write */
|
|
||||||
{0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::InvSrcAlpha,
|
|
||||||
hecl::Backend::ZTest::GEqual, hecl::Backend::CullMode::Backface, true, false, true},
|
|
||||||
/* Disintegration */
|
|
||||||
{2, DisintegrateTextures.data(), hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::InvSrcAlpha,
|
|
||||||
hecl::Backend::ZTest::LEqual, hecl::Backend::CullMode::Original, false, false, true, false, false, true},
|
|
||||||
/* Forced additive shading without culling or Z-write and greater depth test */
|
|
||||||
{0, nullptr, hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::One, hecl::Backend::ZTest::Greater,
|
|
||||||
hecl::Backend::CullMode::None, true, false, true},
|
|
||||||
/* Thermal cold shading */
|
|
||||||
{0, nullptr, hecl::Backend::BlendFactor::Original, hecl::Backend::BlendFactor::Original,
|
|
||||||
hecl::Backend::ZTest::Original, hecl::Backend::CullMode::Original, false, false, true, false, false, false, true},
|
|
||||||
/* Normal lit shading with alpha */
|
|
||||||
{0, nullptr, hecl::Backend::BlendFactor::Original, hecl::Backend::BlendFactor::Original,
|
|
||||||
hecl::Backend::ZTest::Original, hecl::Backend::CullMode::Backface},
|
|
||||||
/* Normal lit shading with alpha without Z-write or depth test */
|
|
||||||
{0, nullptr, hecl::Backend::BlendFactor::Original, hecl::Backend::BlendFactor::Original,
|
|
||||||
hecl::Backend::ZTest::None, hecl::Backend::CullMode::Backface, true},
|
|
||||||
/* Normal lit shading with cube reflection */
|
|
||||||
{0, nullptr, hecl::Backend::BlendFactor::Original, hecl::Backend::BlendFactor::Original,
|
|
||||||
hecl::Backend::ZTest::Original, hecl::Backend::CullMode::Backface, false, false, true},
|
|
||||||
/* Normal lit shading with cube reflection and world shadow */
|
|
||||||
{1, WorldShadowTextures.data(), hecl::Backend::BlendFactor::Original, hecl::Backend::BlendFactor::Original,
|
|
||||||
hecl::Backend::ZTest::Original, hecl::Backend::CullMode::Backface, false, false, true},
|
|
||||||
}};
|
|
||||||
|
|
||||||
// TODO: put somewhere common
|
// TODO: put somewhere common
|
||||||
template <typename BitType>
|
template <typename BitType>
|
||||||
|
@ -180,7 +158,7 @@ public:
|
||||||
constexpr explicit Flags(MaskType flags) noexcept : m_mask(flags) {}
|
constexpr explicit Flags(MaskType flags) noexcept : m_mask(flags) {}
|
||||||
|
|
||||||
// relational operators
|
// relational operators
|
||||||
auto operator<=>(Flags<BitType> const&) const = default;
|
// auto operator<=>(Flags<BitType> const&) const = default;
|
||||||
|
|
||||||
// logical operator
|
// logical operator
|
||||||
constexpr bool operator!() const noexcept { return !m_mask; }
|
constexpr bool operator!() const noexcept { return !m_mask; }
|
||||||
|
@ -282,7 +260,7 @@ struct CCubeSurface {
|
||||||
float x20_normal[3];
|
float x20_normal[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CMetroidModelInstance {
|
struct CMetroidModelInstance_ {
|
||||||
u32 x0_visorFlags;
|
u32 x0_visorFlags;
|
||||||
zeus::CTransform x4_worldXf;
|
zeus::CTransform x4_worldXf;
|
||||||
zeus::CAABox x34_worldAABB;
|
zeus::CAABox x34_worldAABB;
|
||||||
|
@ -352,41 +330,6 @@ constexpr hsh::sampler ClampEdgeSamp(hsh::Linear, hsh::Linear, hsh::Linear, hsh:
|
||||||
constexpr hsh::sampler ReflectSamp(hsh::Linear, hsh::Linear, hsh::Linear, hsh::ClampToBorder, hsh::ClampToBorder,
|
constexpr hsh::sampler ReflectSamp(hsh::Linear, hsh::Linear, hsh::Linear, hsh::ClampToBorder, hsh::ClampToBorder,
|
||||||
hsh::ClampToBorder);
|
hsh::ClampToBorder);
|
||||||
|
|
||||||
template <bool CubeReflection>
|
|
||||||
struct DynReflectionTex {
|
|
||||||
using type = hsh::texture2d;
|
|
||||||
};
|
|
||||||
template <>
|
|
||||||
struct DynReflectionTex<true> {
|
|
||||||
using type = hsh::texturecube;
|
|
||||||
};
|
|
||||||
template <bool CubeReflection>
|
|
||||||
using DynReflectionTexType = typename DynReflectionTex<CubeReflection>::type;
|
|
||||||
|
|
||||||
using BlendMaterial = hecl::blender::Material;
|
|
||||||
using MaterialBlendMode = BlendMaterial::BlendMode;
|
|
||||||
using MaterialTexCoordSource = BlendMaterial::TexCoordSource;
|
|
||||||
|
|
||||||
struct NoColorValue {
|
|
||||||
static constexpr bool Constant = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <float R, float G, float B, float A>
|
|
||||||
struct ColorValue {
|
|
||||||
static constexpr bool Constant = true;
|
|
||||||
static constexpr hsh::float3 RGB{R, G, B};
|
|
||||||
static constexpr float A_ = A;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <MaterialTexCoordSource Source, bool Normalize, int MtxIdx, bool SampleAlpha, class ConstantColor = NoColorValue>
|
|
||||||
struct PassTraits {
|
|
||||||
static constexpr MaterialTexCoordSource Source_ = Source;
|
|
||||||
static constexpr bool Normalize_ = Normalize;
|
|
||||||
static constexpr int MtxIdx_ = MtxIdx;
|
|
||||||
static constexpr bool SampleAlpha_ = SampleAlpha;
|
|
||||||
using ConstantColor_ = ConstantColor;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <MaterialBlendMode Mode>
|
template <MaterialBlendMode Mode>
|
||||||
constexpr hsh::BlendFactor MaterialBlendModeSrcFactor = hsh::One;
|
constexpr hsh::BlendFactor MaterialBlendModeSrcFactor = hsh::One;
|
||||||
template <>
|
template <>
|
||||||
|
@ -407,15 +350,18 @@ constexpr hsh::ColorComponentFlags
|
||||||
(AlphaUpdate ? hsh::CC_Alpha : 0));
|
(AlphaUpdate ? hsh::CC_Alpha : 0));
|
||||||
|
|
||||||
template <MaterialBlendMode MaterialBlendMode, bool ColorUpdate, bool AlphaUpdate, bool DstAlpha>
|
template <MaterialBlendMode MaterialBlendMode, bool ColorUpdate, bool AlphaUpdate, bool DstAlpha>
|
||||||
struct CModelShadersColorAttachmentBase
|
struct CModelShadersColorAttachmentBase {
|
||||||
: color_attachment<MaterialBlendModeSrcFactor<MaterialBlendMode>, MaterialBlendModeDstFactor<MaterialBlendMode>,
|
using type =
|
||||||
hsh::Add, DstAlpha ? hsh::ConstAlpha : hsh::Zero, hsh::Zero, hsh::Add,
|
color_attachment<MaterialBlendModeSrcFactor<MaterialBlendMode>, MaterialBlendModeDstFactor<MaterialBlendMode>,
|
||||||
ColorUpdateFlags<ColorUpdate, AlphaUpdate>> {};
|
hsh::Add, DstAlpha ? hsh::ConstAlpha : hsh::Zero, hsh::Zero, hsh::Add,
|
||||||
|
ColorUpdateFlags<ColorUpdate, AlphaUpdate>>;
|
||||||
|
};
|
||||||
|
|
||||||
template <hsh::BlendFactor Src, hsh::BlendFactor Dst, bool ColorUpdate, bool AlphaUpdate, bool DstAlpha>
|
template <hsh::BlendFactor Src, hsh::BlendFactor Dst, bool ColorUpdate, bool AlphaUpdate, bool DstAlpha>
|
||||||
struct CModelShadersColorAttachmentOverride
|
struct CModelShadersColorAttachmentOverride {
|
||||||
: color_attachment<Src, Dst, hsh::Add, DstAlpha ? hsh::ConstAlpha : hsh::Zero, hsh::Zero, hsh::Add,
|
using type = color_attachment<Src, Dst, hsh::Add, DstAlpha ? hsh::ConstAlpha : hsh::Zero, hsh::Zero, hsh::Add,
|
||||||
ColorUpdateFlags<ColorUpdate, AlphaUpdate>> {};
|
ColorUpdateFlags<ColorUpdate, AlphaUpdate>>;
|
||||||
|
};
|
||||||
|
|
||||||
template <MaterialBlendMode MaterialBlendMode, bool AlphaTest, bool ColorUpdate, bool AlphaUpdate, bool DstAlpha>
|
template <MaterialBlendMode MaterialBlendMode, bool AlphaTest, bool ColorUpdate, bool AlphaUpdate, bool DstAlpha>
|
||||||
struct CModelShadersColorAttachment0To4
|
struct CModelShadersColorAttachment0To4
|
||||||
|
@ -451,7 +397,9 @@ struct CModelShadersColorAttachment7To8<MaterialBlendMode, true, ColorUpdate, Al
|
||||||
|
|
||||||
template <MaterialBlendMode MaterialBlendMode, u8 GameBlendMode, bool AlphaTest, bool ColorUpdate, bool AlphaUpdate,
|
template <MaterialBlendMode MaterialBlendMode, u8 GameBlendMode, bool AlphaTest, bool ColorUpdate, bool AlphaUpdate,
|
||||||
bool DstAlpha>
|
bool DstAlpha>
|
||||||
struct CModelShadersColorAttachment : color_attachment<> {};
|
struct CModelShadersColorAttachment {
|
||||||
|
using type = color_attachment<>;
|
||||||
|
};
|
||||||
|
|
||||||
template <MaterialBlendMode MaterialBlendMode, bool AlphaTest, bool ColorUpdate, bool AlphaUpdate, bool DstAlpha>
|
template <MaterialBlendMode MaterialBlendMode, bool AlphaTest, bool ColorUpdate, bool AlphaUpdate, bool DstAlpha>
|
||||||
struct CModelShadersColorAttachment<MaterialBlendMode, 0, AlphaTest, ColorUpdate, AlphaUpdate, DstAlpha>
|
struct CModelShadersColorAttachment<MaterialBlendMode, 0, AlphaTest, ColorUpdate, AlphaUpdate, DstAlpha>
|
||||||
|
@ -489,46 +437,55 @@ template <MaterialBlendMode MaterialBlendMode, bool AlphaTest, bool ColorUpdate,
|
||||||
struct CModelShadersColorAttachment<MaterialBlendMode, 8, AlphaTest, ColorUpdate, AlphaUpdate, DstAlpha>
|
struct CModelShadersColorAttachment<MaterialBlendMode, 8, AlphaTest, ColorUpdate, AlphaUpdate, DstAlpha>
|
||||||
: CModelShadersColorAttachment7To8<MaterialBlendMode, AlphaTest, ColorUpdate, AlphaUpdate, DstAlpha> {};
|
: CModelShadersColorAttachment7To8<MaterialBlendMode, AlphaTest, ColorUpdate, AlphaUpdate, DstAlpha> {};
|
||||||
|
|
||||||
template <MaterialBlendMode MaterialBlendMode, u32 MaterialFlags, u8 GameBlendMode, u16 ModelFlags, bool ColorUpdate,
|
template <MaterialBlendMode MaterialBlendMode, u16 MaterialFlags, u8 GameBlendMode, u16 ModelFlags, bool ColorUpdate,
|
||||||
bool AlphaUpdate, bool DstAlpha>
|
bool AlphaUpdate, bool DstAlpha, ERglCullMode CullMode>
|
||||||
struct CModelShadersPipelineConfig
|
struct CModelShadersPipelineConfig
|
||||||
: pipeline<
|
: public pipeline<
|
||||||
CModelShadersColorAttachment<MaterialBlendMode, GameBlendMode,
|
topology<hsh::TriangleStrip>,
|
||||||
MaterialFlags & u16(CCubeMaterialFlagBits::fAlphaTest), ColorUpdate, AlphaUpdate,
|
typename CModelShadersColorAttachment<MaterialBlendMode, GameBlendMode,
|
||||||
DstAlpha>,
|
(MaterialFlags & u16(CCubeMaterialFlagBits::fAlphaTest)) != 0, ColorUpdate,
|
||||||
|
AlphaUpdate, DstAlpha>::type,
|
||||||
depth_compare<ModelFlags & u16(CModelFlagsFlagBits::fDepthTest)
|
depth_compare<ModelFlags & u16(CModelFlagsFlagBits::fDepthTest)
|
||||||
? (ModelFlags& u16(CModelFlagsFlagBits::kDepthGreater)
|
? (ModelFlags& u16(CModelFlagsFlagBits::kDepthGreater)
|
||||||
? (ModelFlags& u16(CModelFlagsFlagBits::fDepthNonInclusive) ? hsh::Greater : hsh::GEqual)
|
? (ModelFlags& u16(CModelFlagsFlagBits::fDepthNonInclusive) ? hsh::Greater : hsh::GEqual)
|
||||||
: (ModelFlags& u16(CModelFlagsFlagBits::fDepthNonInclusive) ? hsh::Less : hsh::LEqual))
|
: (ModelFlags& u16(CModelFlagsFlagBits::fDepthNonInclusive) ? hsh::Less : hsh::LEqual))
|
||||||
: hsh::Always>,
|
: hsh::Always>,
|
||||||
depth_write<ModelFlags & u16(CModelFlagsFlagBits::fDepthWrite) &&
|
depth_write<ModelFlags & u16(CModelFlagsFlagBits::fDepthWrite) &&
|
||||||
MaterialFlags & u32(CCubeMaterialFlagBits::fDepthWrite)>,
|
MaterialFlags & u16(CCubeMaterialFlagBits::fDepthWrite)>,
|
||||||
early_depth_stencil<(MaterialFlags & u16(CCubeMaterialFlagBits::fAlphaTest)) == 0>> {
|
early_depth_stencil<(MaterialFlags & u16(CCubeMaterialFlagBits::fAlphaTest)) == 0>,
|
||||||
|
ERglCullModeAttachment<CullMode>> {
|
||||||
static constexpr bool AlphaTest = MaterialFlags & u16(CCubeMaterialFlagBits::fAlphaTest);
|
static constexpr bool AlphaTest = MaterialFlags & u16(CCubeMaterialFlagBits::fAlphaTest);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <uint32_t NSkinSlots, uint32_t NCol, uint32_t NUv, uint32_t NWeight, BlendMaterial::ShaderType Type, EPostType Post,
|
template <uint32_t NSkinSlots, uint32_t NCol, uint32_t NUv, uint32_t NWeight, BlendMaterial::ShaderType Type,
|
||||||
bool WorldShadow, class LightmapTraits, class DiffuseTraits,
|
EPostType Post, bool WorldShadow, class LightmapTraits, class DiffuseTraits, class EmissiveTraits,
|
||||||
class EmissiveTraits, class SpecularTraits, class ExtendedSpecularTraits, class ReflectionTraits,
|
class SpecularTraits, class ExtendedSpecularTraits, class ReflectionTraits, class AlphaTraits,
|
||||||
class AlphaTraits, bool CubeReflection, MaterialBlendMode MaterialBlendMode, u32 MaterialFlags,
|
bool CubeReflection, MaterialBlendMode MaterialBlendMode, u16 MaterialFlags,
|
||||||
u8 GameBlendMode, u16 ModelFlags, bool ColorUpdate, bool AlphaUpdate, bool DstAlpha>
|
// FIXME hsh bug: u8 generates broken characters for profiling
|
||||||
|
u16 GameBlendMode,
|
||||||
|
u16 ModelFlags, bool ColorUpdate = true, bool AlphaUpdate = false, bool DstAlpha = false,
|
||||||
|
ERglCullMode CullMode = ERglCullMode::Back>
|
||||||
struct CModelShadersPipeline : CModelShadersPipelineConfig<MaterialBlendMode, MaterialFlags, GameBlendMode, ModelFlags,
|
struct CModelShadersPipeline : CModelShadersPipelineConfig<MaterialBlendMode, MaterialFlags, GameBlendMode, ModelFlags,
|
||||||
ColorUpdate, AlphaUpdate, DstAlpha> {
|
ColorUpdate, AlphaUpdate, DstAlpha, CullMode> {
|
||||||
|
using PipelineConfig = CModelShadersPipelineConfig<MaterialBlendMode, MaterialFlags, GameBlendMode, ModelFlags,
|
||||||
|
ColorUpdate, AlphaUpdate, DstAlpha, CullMode>;
|
||||||
|
|
||||||
CModelShadersPipeline(hsh::uniform_buffer<CModelShaders::VertUniform<NSkinSlots>> vu,
|
CModelShadersPipeline(hsh::uniform_buffer<CModelShaders::VertUniform<NSkinSlots>> vu,
|
||||||
hsh::uniform_buffer<CModelShaders::FragmentUniform> fragu HSH_VAR_STAGE(fragment),
|
hsh::uniform_buffer<CModelShaders::FragmentUniform> fragu HSH_VAR_STAGE(fragment),
|
||||||
hsh::uniform_buffer<std::array<CModelShaders::TCGMatrix, 8>> tcgu,
|
hsh::uniform_buffer<CModelShaders::TCGMatrixUniform> tcgu,
|
||||||
hsh::uniform_buffer<CModelShaders::ReflectMtx> refu, hsh::texture2d Lightmap,
|
hsh::uniform_buffer<CModelShaders::ReflectMtx> refu, hsh::texture2d Lightmap,
|
||||||
hsh::texture2d Diffuse, hsh::texture2d Emissive, hsh::texture2d Specular,
|
hsh::texture2d Diffuse, hsh::texture2d Emissive, hsh::texture2d Specular,
|
||||||
hsh::texture2d ExtendedSpecular, hsh::texture2d Reflection, hsh::texture2d Alpha,
|
hsh::texture2d ExtendedSpecular, hsh::texture2d Reflection, hsh::texture2d Alpha,
|
||||||
hsh::texture2d ReflectionIndTex, hsh::texture2d ExtTex0, hsh::texture2d ExtTex1,
|
hsh::texture2d ReflectionIndTex, hsh::texture2d ExtTex0, hsh::texture2d ExtTex1,
|
||||||
hsh::texture2d ExtTex2, DynReflectionTexType<CubeReflection> dynReflection,
|
hsh::texture2d ExtTex2, DynReflectionTexType<CubeReflection> dynReflection,
|
||||||
hsh::vertex_buffer<CModelShaders::VertData<NCol, NUv, NWeight>> vd) {
|
hsh::vertex_buffer<CModelShaders::VertData<NCol, NUv, NWeight>> vd,
|
||||||
|
hsh::index_buffer<u32> ibo) {
|
||||||
hsh::float4 mvPos;
|
hsh::float4 mvPos;
|
||||||
hsh::float4 mvNorm;
|
hsh::float4 mvNorm;
|
||||||
|
|
||||||
hsh::float4 objPos;
|
hsh::float4 objPos;
|
||||||
hsh::float4 objNorm;
|
hsh::float4 objNorm;
|
||||||
if constexpr (NSkinSlots != 0) {
|
if constexpr (NSkinSlots > 0) {
|
||||||
objPos = hsh::float4(0.f);
|
objPos = hsh::float4(0.f);
|
||||||
objNorm = hsh::float4(0.f);
|
objNorm = hsh::float4(0.f);
|
||||||
for (uint32_t i = 0; i < NSkinSlots; ++i) {
|
for (uint32_t i = 0; i < NSkinSlots; ++i) {
|
||||||
|
@ -566,39 +523,26 @@ struct CModelShadersPipeline : CModelShadersPipelineConfig<MaterialBlendMode, Ma
|
||||||
if constexpr (Pass##Traits::Source_ != MaterialTexCoordSource::Invalid) { \
|
if constexpr (Pass##Traits::Source_ != MaterialTexCoordSource::Invalid) { \
|
||||||
if constexpr (Pass##Traits::MtxIdx_ >= 0) { \
|
if constexpr (Pass##Traits::MtxIdx_ >= 0) { \
|
||||||
hsh::float4 src; \
|
hsh::float4 src; \
|
||||||
switch (Pass##Traits::Source_) { \
|
if constexpr (Pass##Traits::Source_ == MaterialTexCoordSource::Position) { \
|
||||||
case MaterialTexCoordSource::Position: \
|
|
||||||
src = hsh::float4(objPos.xyz(), 1.f); \
|
src = hsh::float4(objPos.xyz(), 1.f); \
|
||||||
break; \
|
} else if constexpr (Pass##Traits::Source_ == MaterialTexCoordSource::Normal) { \
|
||||||
case MaterialTexCoordSource::Normal: \
|
|
||||||
src = hsh::float4(objNorm.xyz(), 1.f); \
|
src = hsh::float4(objNorm.xyz(), 1.f); \
|
||||||
break; \
|
} else if constexpr (Pass##Traits::Source_ == MaterialTexCoordSource::Tex0) { \
|
||||||
case MaterialTexCoordSource::Tex0: \
|
|
||||||
src = hsh::float4(vd->uvIn[0], 0.f, 1.f); \
|
src = hsh::float4(vd->uvIn[0], 0.f, 1.f); \
|
||||||
break; \
|
} else if constexpr (Pass##Traits::Source_ == MaterialTexCoordSource::Tex1) { \
|
||||||
case MaterialTexCoordSource::Tex1: \
|
|
||||||
src = hsh::float4(vd->uvIn[1], 0.f, 1.f); \
|
src = hsh::float4(vd->uvIn[1], 0.f, 1.f); \
|
||||||
break; \
|
} else if constexpr (Pass##Traits::Source_ == MaterialTexCoordSource::Tex2) { \
|
||||||
case MaterialTexCoordSource::Tex2: \
|
|
||||||
src = hsh::float4(vd->uvIn[2], 0.f, 1.f); \
|
src = hsh::float4(vd->uvIn[2], 0.f, 1.f); \
|
||||||
break; \
|
} else if constexpr (Pass##Traits::Source_ == MaterialTexCoordSource::Tex3) { \
|
||||||
case MaterialTexCoordSource::Tex3: \
|
|
||||||
src = hsh::float4(vd->uvIn[3], 0.f, 1.f); \
|
src = hsh::float4(vd->uvIn[3], 0.f, 1.f); \
|
||||||
break; \
|
} else if constexpr (Pass##Traits::Source_ == MaterialTexCoordSource::Tex4) { \
|
||||||
case MaterialTexCoordSource::Tex4: \
|
|
||||||
src = hsh::float4(vd->uvIn[4], 0.f, 1.f); \
|
src = hsh::float4(vd->uvIn[4], 0.f, 1.f); \
|
||||||
break; \
|
} else if constexpr (Pass##Traits::Source_ == MaterialTexCoordSource::Tex5) { \
|
||||||
case MaterialTexCoordSource::Tex5: \
|
|
||||||
src = hsh::float4(vd->uvIn[5], 0.f, 1.f); \
|
src = hsh::float4(vd->uvIn[5], 0.f, 1.f); \
|
||||||
break; \
|
} else if constexpr (Pass##Traits::Source_ == MaterialTexCoordSource::Tex6) { \
|
||||||
case MaterialTexCoordSource::Tex6: \
|
|
||||||
src = hsh::float4(vd->uvIn[6], 0.f, 1.f); \
|
src = hsh::float4(vd->uvIn[6], 0.f, 1.f); \
|
||||||
break; \
|
} else if constexpr (Pass##Traits::Source_ == MaterialTexCoordSource::Tex7) { \
|
||||||
case MaterialTexCoordSource::Tex7: \
|
|
||||||
src = hsh::float4(vd->uvIn[7], 0.f, 1.f); \
|
src = hsh::float4(vd->uvIn[7], 0.f, 1.f); \
|
||||||
break; \
|
|
||||||
case MaterialTexCoordSource::Invalid: \
|
|
||||||
break; \
|
|
||||||
} \
|
} \
|
||||||
hsh::float3 tmp = ((*tcgu)[Pass##Traits::MtxIdx_].mtx * src).xyz(); \
|
hsh::float3 tmp = ((*tcgu)[Pass##Traits::MtxIdx_].mtx * src).xyz(); \
|
||||||
if constexpr (Pass##Traits::Normalize_) \
|
if constexpr (Pass##Traits::Normalize_) \
|
||||||
|
@ -606,39 +550,26 @@ struct CModelShadersPipeline : CModelShadersPipelineConfig<MaterialBlendMode, Ma
|
||||||
hsh::float4 tmpProj = (*tcgu)[Pass##Traits::MtxIdx_].postMtx * hsh::float4(tmp, 1.f); \
|
hsh::float4 tmpProj = (*tcgu)[Pass##Traits::MtxIdx_].postMtx * hsh::float4(tmp, 1.f); \
|
||||||
Pass##Uv = (tmpProj / tmpProj.w).xy(); \
|
Pass##Uv = (tmpProj / tmpProj.w).xy(); \
|
||||||
} else { \
|
} else { \
|
||||||
switch (Pass##Traits::Source_) { \
|
if constexpr (Pass##Traits::Source_ == MaterialTexCoordSource::Position) { \
|
||||||
case MaterialTexCoordSource::Position: \
|
|
||||||
Pass##Uv = objPos.xy(); \
|
Pass##Uv = objPos.xy(); \
|
||||||
break; \
|
} else if constexpr (Pass##Traits::Source_ == MaterialTexCoordSource::Normal) { \
|
||||||
case MaterialTexCoordSource::Normal: \
|
|
||||||
Pass##Uv = objNorm.xy(); \
|
Pass##Uv = objNorm.xy(); \
|
||||||
break; \
|
} else if constexpr (Pass##Traits::Source_ == MaterialTexCoordSource::Tex0) { \
|
||||||
case MaterialTexCoordSource::Tex0: \
|
|
||||||
Pass##Uv = vd->uvIn[0]; \
|
Pass##Uv = vd->uvIn[0]; \
|
||||||
break; \
|
} else if constexpr (Pass##Traits::Source_ == MaterialTexCoordSource::Tex1) { \
|
||||||
case MaterialTexCoordSource::Tex1: \
|
|
||||||
Pass##Uv = vd->uvIn[1]; \
|
Pass##Uv = vd->uvIn[1]; \
|
||||||
break; \
|
} else if constexpr (Pass##Traits::Source_ == MaterialTexCoordSource::Tex2) { \
|
||||||
case MaterialTexCoordSource::Tex2: \
|
|
||||||
Pass##Uv = vd->uvIn[2]; \
|
Pass##Uv = vd->uvIn[2]; \
|
||||||
break; \
|
} else if constexpr (Pass##Traits::Source_ == MaterialTexCoordSource::Tex3) { \
|
||||||
case MaterialTexCoordSource::Tex3: \
|
|
||||||
Pass##Uv = vd->uvIn[3]; \
|
Pass##Uv = vd->uvIn[3]; \
|
||||||
break; \
|
} else if constexpr (Pass##Traits::Source_ == MaterialTexCoordSource::Tex4) { \
|
||||||
case MaterialTexCoordSource::Tex4: \
|
|
||||||
Pass##Uv = vd->uvIn[4]; \
|
Pass##Uv = vd->uvIn[4]; \
|
||||||
break; \
|
} else if constexpr (Pass##Traits::Source_ == MaterialTexCoordSource::Tex5) { \
|
||||||
case MaterialTexCoordSource::Tex5: \
|
|
||||||
Pass##Uv = vd->uvIn[5]; \
|
Pass##Uv = vd->uvIn[5]; \
|
||||||
break; \
|
} else if constexpr (Pass##Traits::Source_ == MaterialTexCoordSource::Tex6) { \
|
||||||
case MaterialTexCoordSource::Tex6: \
|
|
||||||
Pass##Uv = vd->uvIn[6]; \
|
Pass##Uv = vd->uvIn[6]; \
|
||||||
break; \
|
} else if constexpr (Pass##Traits::Source_ == MaterialTexCoordSource::Tex7) { \
|
||||||
case MaterialTexCoordSource::Tex7: \
|
|
||||||
Pass##Uv = vd->uvIn[7]; \
|
Pass##Uv = vd->uvIn[7]; \
|
||||||
break; \
|
|
||||||
case MaterialTexCoordSource::Invalid: \
|
|
||||||
break; \
|
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
@ -658,14 +589,10 @@ struct CModelShadersPipeline : CModelShadersPipelineConfig<MaterialBlendMode, Ma
|
||||||
}
|
}
|
||||||
|
|
||||||
hsh::float3 lighting;
|
hsh::float3 lighting;
|
||||||
switch (Post) {
|
if constexpr (Post == EPostType::ThermalHot || Post == EPostType::ThermalCold || Post == EPostType::Solid ||
|
||||||
case EPostType::ThermalHot:
|
Post == EPostType::MBShadow) {
|
||||||
case EPostType::ThermalCold:
|
|
||||||
case EPostType::Solid:
|
|
||||||
case EPostType::MBShadow:
|
|
||||||
lighting = hsh::float3(1.f);
|
lighting = hsh::float3(1.f);
|
||||||
break;
|
} else {
|
||||||
default:
|
|
||||||
lighting = fragu->ambient.xyz();
|
lighting = fragu->ambient.xyz();
|
||||||
|
|
||||||
for (int i = 0; i < URDE_MAX_LIGHTS; ++i) {
|
for (int i = 0; i < URDE_MAX_LIGHTS; ++i) {
|
||||||
|
@ -685,19 +612,14 @@ struct CModelShadersPipeline : CModelShadersPipelineConfig<MaterialBlendMode, Ma
|
||||||
}
|
}
|
||||||
|
|
||||||
lighting = hsh::saturate(lighting);
|
lighting = hsh::saturate(lighting);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hsh::float3 DynReflectionSample HSH_VAR_STAGE(fragment);
|
hsh::float3 DynReflectionSample HSH_VAR_STAGE(fragment);
|
||||||
if constexpr ((MaterialFlags & u32(CCubeMaterialFlagBits::fSamusReflectionIndirectTexture)) != 0) {
|
if constexpr ((MaterialFlags & u32(CCubeMaterialFlagBits::fSamusReflectionIndirectTexture)) != 0) {
|
||||||
DynReflectionSample = dynReflection
|
DynReflectionUv +=
|
||||||
.template sample<float>((ReflectionIndTex.sample<float>(DynReflectionIndUv, Samp).xw() -
|
(ReflectionIndTex.sample<float>(DynReflectionIndUv, Samp).xw() - hsh::float2(0.5f)) * hsh::float2(0.5f);
|
||||||
hsh::float2(0.5f)) *
|
DynReflectionSample =
|
||||||
hsh::float2(0.5f) +
|
dynReflection.template sample<float>(DynReflectionUv, ReflectSamp).xyz() * refu->reflectAlpha;
|
||||||
DynReflectionUv,
|
|
||||||
ReflectSamp)
|
|
||||||
.xyz() *
|
|
||||||
refu->reflectAlpha;
|
|
||||||
} else if constexpr ((MaterialFlags & u32(CCubeMaterialFlagBits::fSamusReflection)) != 0) {
|
} else if constexpr ((MaterialFlags & u32(CCubeMaterialFlagBits::fSamusReflection)) != 0) {
|
||||||
DynReflectionSample =
|
DynReflectionSample =
|
||||||
dynReflection.template sample<float>(DynReflectionUv, ReflectSamp).xyz() * refu->reflectAlpha;
|
dynReflection.template sample<float>(DynReflectionUv, ReflectSamp).xyz() * refu->reflectAlpha;
|
||||||
|
@ -705,70 +627,82 @@ struct CModelShadersPipeline : CModelShadersPipelineConfig<MaterialBlendMode, Ma
|
||||||
DynReflectionSample = hsh::float3(0.f);
|
DynReflectionSample = hsh::float3(0.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
const hsh::float3 kRGBToYPrime = hsh::float3(0.257f, 0.504f, 0.098f);
|
const hsh::float3 kRGBToYPrime = hsh::float3(0.299f, 0.587f, 0.114f);
|
||||||
|
|
||||||
#define Sample(Pass) \
|
#define Sample(Pass) \
|
||||||
(Pass##Traits::SampleAlpha_ \
|
(Pass##Traits::SampleAlpha_ \
|
||||||
? (Pass##Traits::ConstantColor_::Constant ? hsh::float3(Pass##Traits::ConstantColor_::A_) \
|
? (Pass##Traits::ConstantColor_::Constant ? hsh::float3(Pass##Traits::ConstantColor_::A_) \
|
||||||
: hsh::float3(Pass.sample<float>(Pass##Uv, Samp).w)) \
|
: hsh::float3(Pass.sample<float>(Pass##Uv, Samp).w)) \
|
||||||
: (Pass##Traits::ConstantColor_::Constant ? Pass##Traits::ConstantColor_::RGB \
|
: (Pass##Traits::ConstantColor_::Constant \
|
||||||
: Pass.sample<float>(Pass##Uv, Samp).xyz()))
|
? hsh::float3(Pass##Traits::ConstantColor_::R_, Pass##Traits::ConstantColor_::G_, \
|
||||||
|
Pass##Traits::ConstantColor_::B_) \
|
||||||
|
: Pass.sample<float>(Pass##Uv, Samp).xyz()))
|
||||||
#define SampleAlpha(Pass) \
|
#define SampleAlpha(Pass) \
|
||||||
(Pass##Traits::SampleAlpha_ \
|
(Pass##Traits::SampleAlpha_ \
|
||||||
? (Pass##Traits::ConstantColor_::Constant ? Pass##Traits::ConstantColor_::A_ \
|
? (Pass##Traits::ConstantColor_::Constant ? Pass##Traits::ConstantColor_::A_ \
|
||||||
: Pass.sample<float>(Pass##Uv, Samp).w) \
|
: Pass.sample<float>(Pass##Uv, Samp).w) \
|
||||||
: (Pass##Traits::ConstantColor_::Constant ? hsh::dot(Pass##Traits::ConstantColor_::RGB, kRGBToYPrime) \
|
: (Pass##Traits::ConstantColor_::Constant \
|
||||||
: hsh::dot(Pass.sample<float>(Pass##Uv, Samp).xyz(), kRGBToYPrime)))
|
? hsh::dot(hsh::float3(Pass##Traits::ConstantColor_::R_, Pass##Traits::ConstantColor_::G_, \
|
||||||
|
Pass##Traits::ConstantColor_::B_), \
|
||||||
|
kRGBToYPrime) \
|
||||||
|
: hsh::dot(Pass.sample<float>(Pass##Uv, Samp).xyz(), kRGBToYPrime)))
|
||||||
|
|
||||||
switch (Type) {
|
if constexpr (Type == BlendMaterial::ShaderType::Invalid) {
|
||||||
case BlendMaterial::ShaderType::Invalid:
|
|
||||||
this->color_out[0] = hsh::float4(Sample(Diffuse), SampleAlpha(Alpha));
|
this->color_out[0] = hsh::float4(Sample(Diffuse), SampleAlpha(Alpha));
|
||||||
break;
|
} else if constexpr (Type == BlendMaterial::ShaderType::RetroShader) {
|
||||||
case BlendMaterial::ShaderType::RetroShader:
|
hsh::float3 rgb = Sample(Lightmap) * fragu->lightmapMul.xyz() + lighting;
|
||||||
this->color_out[0] = hsh::float4(
|
rgb *= Sample(Diffuse);
|
||||||
(Sample(Lightmap) * fragu->lightmapMul.xyz() + lighting) * Sample(Diffuse) + Sample(Emissive) +
|
rgb += Sample(Emissive);
|
||||||
(Sample(Specular) + Sample(ExtendedSpecular) * lighting) * Sample(Reflection) + DynReflectionSample,
|
hsh::float3 specular = Sample(Specular) + Sample(ExtendedSpecular) * lighting;
|
||||||
SampleAlpha(Alpha));
|
rgb += specular * Sample(Reflection);
|
||||||
break;
|
rgb += DynReflectionSample;
|
||||||
case BlendMaterial::ShaderType::RetroDynamicShader:
|
this->color_out[0] = hsh::float4(rgb, SampleAlpha(Alpha));
|
||||||
this->color_out[0] = hsh::float4(
|
} else if constexpr (Type == BlendMaterial::ShaderType::RetroDynamicShader) {
|
||||||
(Sample(Lightmap) * fragu->lightmapMul.xyz() + lighting) * (Sample(Diffuse) + Sample(Emissive)) *
|
hsh::float3 rgb = Sample(Lightmap) * fragu->lightmapMul.xyz() + lighting;
|
||||||
fragu->lightmapMul.xyz() +
|
rgb *= Sample(Diffuse) * Sample(Emissive);
|
||||||
(Sample(Specular) + Sample(ExtendedSpecular) * lighting) * Sample(Reflection) + DynReflectionSample,
|
rgb *= fragu->lightmapMul.xyz();
|
||||||
SampleAlpha(Alpha));
|
hsh::float3 specular = Sample(Specular) + Sample(ExtendedSpecular) * lighting;
|
||||||
break;
|
rgb += specular * Sample(Reflection);
|
||||||
case BlendMaterial::ShaderType::RetroDynamicAlphaShader:
|
rgb += DynReflectionSample;
|
||||||
this->color_out[0] = hsh::float4(
|
this->color_out[0] = hsh::float4(rgb, SampleAlpha(Alpha));
|
||||||
(Sample(Lightmap) * fragu->lightmapMul.xyz() + lighting) * (Sample(Diffuse) + Sample(Emissive)) *
|
} else if constexpr (Type == BlendMaterial::ShaderType::RetroDynamicAlphaShader) {
|
||||||
fragu->lightmapMul.xyz() +
|
hsh::float3 rgb = Sample(Lightmap) * fragu->lightmapMul.xyz() + lighting;
|
||||||
(Sample(Specular) + Sample(ExtendedSpecular) * lighting) * Sample(Reflection) + DynReflectionSample,
|
rgb *= Sample(Diffuse) * Sample(Emissive);
|
||||||
SampleAlpha(Alpha) * fragu->lightmapMul.w);
|
rgb *= fragu->lightmapMul.xyz();
|
||||||
break;
|
hsh::float3 specular = Sample(Specular) + Sample(ExtendedSpecular) * lighting;
|
||||||
case BlendMaterial::ShaderType::RetroDynamicCharacterShader:
|
rgb += specular * Sample(Reflection);
|
||||||
this->color_out[0] = hsh::float4(
|
rgb += DynReflectionSample;
|
||||||
(Sample(Lightmap) + lighting) * Sample(Diffuse) + Sample(Emissive) * fragu->lightmapMul.xyz() +
|
this->color_out[0] = hsh::float4(rgb, SampleAlpha(Alpha) * fragu->lightmapMul.w);
|
||||||
(Sample(Specular) + Sample(ExtendedSpecular) * lighting) * Sample(Reflection) + DynReflectionSample,
|
} else if constexpr (Type == BlendMaterial::ShaderType::RetroDynamicCharacterShader) {
|
||||||
SampleAlpha(Alpha));
|
hsh::float3 rgb = Sample(Lightmap) + lighting;
|
||||||
break;
|
rgb *= Sample(Diffuse);
|
||||||
|
rgb += Sample(Emissive) * fragu->lightmapMul.xyz();
|
||||||
|
hsh::float3 specular = Sample(Specular) + Sample(ExtendedSpecular) * lighting;
|
||||||
|
rgb += specular * Sample(Reflection);
|
||||||
|
rgb += DynReflectionSample;
|
||||||
|
this->color_out[0] = hsh::float4(rgb, SampleAlpha(Alpha));
|
||||||
}
|
}
|
||||||
|
|
||||||
FOG_SHADER(fragu->fog)
|
FOG_SHADER(fragu->fog)
|
||||||
|
|
||||||
if constexpr (Post == EPostType::Normal) {
|
if constexpr (Post == EPostType::Normal) {
|
||||||
if constexpr (this->DstColorBlendFactor<0> == hsh::One)
|
if constexpr (PipelineConfig::template DstColorBlendFactor<0> == hsh::One) {
|
||||||
this->color_out[0] =
|
this->color_out[0] =
|
||||||
hsh::float4(hsh::lerp(this->color_out[0], hsh::float4(0.f), fogZ).xyz(), this->color_out[0].w);
|
hsh::float4(hsh::lerp(this->color_out[0], hsh::float4(0.f), fogZ).xyz(), this->color_out[0].w);
|
||||||
else
|
} else {
|
||||||
this->color_out[0] =
|
this->color_out[0] =
|
||||||
hsh::float4(hsh::lerp(this->color_out[0], fragu->fog.m_color, fogZ).xyz(), this->color_out[0].w);
|
hsh::float4(hsh::lerp(this->color_out[0], fragu->fog.m_color, fogZ).xyz(), this->color_out[0].w);
|
||||||
|
}
|
||||||
if constexpr (GameBlendMode == 2) {
|
if constexpr (GameBlendMode == 2) {
|
||||||
if (this->DstColorBlendFactor<0> != hsh::One)
|
if constexpr (PipelineConfig::template DstColorBlendFactor<0> != hsh::One) {
|
||||||
this->color_out[0] += fragu->flagsColor;
|
this->color_out[0] += fragu->flagsColor;
|
||||||
|
}
|
||||||
} else if constexpr (GameBlendMode != 0) {
|
} else if constexpr (GameBlendMode != 0) {
|
||||||
this->color_out[0] *= fragu->flagsColor;
|
this->color_out[0] *= fragu->flagsColor;
|
||||||
}
|
}
|
||||||
} else if constexpr (Post == EPostType::ThermalHot) {
|
} else if constexpr (Post == EPostType::ThermalHot) {
|
||||||
this->color_out[0] = hsh::float4(ExtTex0.sample<float>(ExtUv0, Samp).x) * fragu->flagsColor + fragu->ambient;
|
this->color_out[0] = hsh::float4(ExtTex0.sample<float>(ExtUv0, Samp).x) * fragu->flagsColor;
|
||||||
|
this->color_out[0] += fragu->ambient;
|
||||||
} else if constexpr (Post == EPostType::ThermalCold) {
|
} else if constexpr (Post == EPostType::ThermalCold) {
|
||||||
this->color_out[0] *= hsh::float4(0.75f);
|
this->color_out[0] *= hsh::float4(0.75f);
|
||||||
} else if constexpr (Post == EPostType::Solid) {
|
} else if constexpr (Post == EPostType::Solid) {
|
||||||
|
@ -787,36 +721,113 @@ struct CModelShadersPipeline : CModelShadersPipelineConfig<MaterialBlendMode, Ma
|
||||||
hsh::float4 texel1 = ExtTex0.sample<float>(ExtUv1, Samp);
|
hsh::float4 texel1 = ExtTex0.sample<float>(ExtUv1, Samp);
|
||||||
this->color_out[0] = hsh::lerp(hsh::float4(0.f), texel1, texel0);
|
this->color_out[0] = hsh::lerp(hsh::float4(0.f), texel1, texel0);
|
||||||
this->color_out[0] = hsh::float4(fragu->flagsColor.xyz() + this->color_out[0].xyz(), this->color_out[0].w);
|
this->color_out[0] = hsh::float4(fragu->flagsColor.xyz() + this->color_out[0].xyz(), this->color_out[0].w);
|
||||||
if constexpr (this->DstColorBlendFactor<0> == hsh::One)
|
if constexpr (PipelineConfig::template DstColorBlendFactor<0> == hsh::One) {
|
||||||
this->color_out[0] =
|
this->color_out[0] =
|
||||||
hsh::float4(hsh::lerp(this->color_out[0], hsh::float4(0.f), fogZ).xyz(), this->color_out[0].w);
|
hsh::float4(hsh::lerp(this->color_out[0], hsh::float4(0.f), fogZ).xyz(), this->color_out[0].w);
|
||||||
else
|
} else {
|
||||||
this->color_out[0] =
|
this->color_out[0] =
|
||||||
hsh::float4(hsh::lerp(this->color_out[0], fragu->fog.m_color, fogZ).xyz(), this->color_out[0].w);
|
hsh::float4(hsh::lerp(this->color_out[0], fragu->fog.m_color, fogZ).xyz(), this->color_out[0].w);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->AlphaTest && this->color_out[0].w < 0.25f)
|
if (PipelineConfig::AlphaTest && this->color_out[0].w < 0.25f) {
|
||||||
hsh::discard();
|
hsh::discard();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#if 0
|
void CModelShaders::SetCurrent(hsh::binding& binding, const CModelFlags& modelFlags, const CBooModel& model,
|
||||||
template <uint32_t NSkinSlots, uint32_t NCol, uint32_t NUv, uint32_t NWeight, EShaderType Type, EPostType Post,
|
const ModelInstance& inst, const CBooSurface& surface) {
|
||||||
bool WorldShadow, class LightmapTraits, class DiffuseTraits,
|
|
||||||
class EmissiveTraits, class SpecularTraits, class ExtendedSpecularTraits, class ReflectionTraits,
|
|
||||||
class AlphaTraits, bool CubeReflection, MaterialBlendMode MaterialBlendMode, u32 MaterialFlags,
|
|
||||||
u8 GameBlendMode, u16 ModelFlags, bool ColorUpdate, bool AlphaUpdate, bool DstAlpha>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
hsh::binding& CModelShaders::SetCurrent(const CModelFlags& modelFlags, const CBooSurface& surface, const CBooModel& model) {
|
|
||||||
const auto& material = model.x4_matSet->materials[surface.m_data.matIdx];
|
const auto& material = model.x4_matSet->materials[surface.m_data.matIdx];
|
||||||
const auto& vtxFmt = model.m_vtxFmt;
|
const auto& vtxFmt = model.m_vtxFmt;
|
||||||
material.chunks
|
|
||||||
m_dataBind.hsh_bind(CModelShadersPipeline<vtxFmt.NSkinSlots, vtxFmt.NCol, vtxFmt.NUv, vtxFmt.NWeight, material.shaderType,
|
std::array<MaterialTexCoordSource, 7> texSources{};
|
||||||
modelFlags.m_postType, CBooModel::g_shadowMap, >());
|
texSources.fill(MaterialTexCoordSource::Invalid);
|
||||||
return m_dataBind;
|
std::array<bool, 7> normalize{};
|
||||||
|
std::array<bool, 7> alpha{};
|
||||||
|
std::array<hsh::texture2d, 12> texs{
|
||||||
|
g_Renderer->m_clearTexture.get(), g_Renderer->m_clearTexture.get(), g_Renderer->m_clearTexture.get(),
|
||||||
|
g_Renderer->m_clearTexture.get(), g_Renderer->m_clearTexture.get(), g_Renderer->m_clearTexture.get(),
|
||||||
|
g_Renderer->m_whiteTexture.get(), g_Renderer->m_clearTexture.get(), g_Renderer->x220_sphereRamp.get(),
|
||||||
|
g_Renderer->x220_sphereRamp.get(), g_Renderer->x220_sphereRamp.get(), g_Renderer->x220_sphereRamp.get(),
|
||||||
|
};
|
||||||
|
std::array<bool, 7> hasPassColor{};
|
||||||
|
std::array<std::array<u8, 4>, 7> passColors{};
|
||||||
|
std::array<uint32_t, 7> tcgMtxIdxs{};
|
||||||
|
tcgMtxIdxs.fill(-1);
|
||||||
|
uint32_t tcgMtxIdx = 0;
|
||||||
|
for (const auto& chunk : material.chunks) {
|
||||||
|
if (const auto& pass = chunk.get_if<Material::PASS>()) {
|
||||||
|
unsigned idx = Material::TexMapIdx(pass->type);
|
||||||
|
auto search = model.x1c_textures.find(pass->texId.toUint32());
|
||||||
|
if (search != model.x1c_textures.cend()) {
|
||||||
|
if (hsh::texture2d tex = search->second->GetBooTexture())
|
||||||
|
texs[idx] = tex;
|
||||||
|
}
|
||||||
|
texSources[idx] = MaterialTexCoordSource(pass->source);
|
||||||
|
normalize[idx] = pass->shouldNormalizeUv();
|
||||||
|
if (pass->uvAnimType != BlendMaterial::UVAnimType::Invalid)
|
||||||
|
tcgMtxIdxs[idx] = tcgMtxIdx;
|
||||||
|
tcgMtxIdx++;
|
||||||
|
alpha[idx] = pass->alpha;
|
||||||
|
} else if (const auto& clr = chunk.get_if<Material::CLR>()) {
|
||||||
|
passColors[Material::TexMapIdx(clr->type)] = {
|
||||||
|
static_cast<u8>(clr->color.simd[0] * 255.f),
|
||||||
|
static_cast<u8>(clr->color.simd[1] * 255.f),
|
||||||
|
static_cast<u8>(clr->color.simd[2] * 255.f),
|
||||||
|
static_cast<u8>(clr->color.simd[3] * 255.f),
|
||||||
|
};
|
||||||
|
hasPassColor[Material::TexMapIdx(clr->type)] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hsh::uniform_buffer_typeless vu = inst.m_geometryUniforms[surface.m_data.skinMtxBankIdx].get();
|
||||||
|
auto refu = inst.m_reflectUniforms[surface.selfIdx].get();
|
||||||
|
auto tcgu = inst.m_tcgUniforms[surface.m_data.matIdx].get();
|
||||||
|
auto fragu = inst.m_fragmentUniform.get();
|
||||||
|
auto vd = inst.GetBooVBO(model);
|
||||||
|
if (modelFlags.m_postType == EPostType::ThermalHot) {
|
||||||
|
texs[8] = g_Renderer->x220_sphereRamp.get();
|
||||||
|
} else if (modelFlags.m_postType == EPostType::MBShadow) {
|
||||||
|
// texs[8] = g_Renderer->m_ballShadowId.get_color(0);
|
||||||
|
texs[9] = g_Renderer->x220_sphereRamp.get();
|
||||||
|
texs[10] = g_Renderer->m_ballFade;
|
||||||
|
} else if (modelFlags.m_postType == EPostType::Disintegrate && CBooModel::g_disintegrateTexture) {
|
||||||
|
texs[8] = CBooModel::g_disintegrateTexture;
|
||||||
|
} else if (CBooModel::g_shadowMap) {
|
||||||
|
texs[8] = CBooModel::g_shadowMap;
|
||||||
|
}
|
||||||
|
binding.hsh_bind(
|
||||||
|
CModelShadersPipeline<vtxFmt.NSkinSlots, vtxFmt.NCol, vtxFmt.NUv, vtxFmt.NWeight, material.shaderType,
|
||||||
|
modelFlags.m_postType, CBooModel::g_shadowMap,
|
||||||
|
PassTraits<texSources[0], normalize[0], tcgMtxIdxs[0], alpha[0],
|
||||||
|
ColorValue<hasPassColor[0], passColors[0][0], passColors[0][1], passColors[0][2],
|
||||||
|
passColors[0][3]>>, // lightmap
|
||||||
|
PassTraits<texSources[1], normalize[1], tcgMtxIdxs[1], alpha[1],
|
||||||
|
ColorValue<hasPassColor[1], passColors[1][0], passColors[1][1], passColors[1][2],
|
||||||
|
passColors[1][3]>>, // diffuse
|
||||||
|
PassTraits<texSources[2], normalize[2], tcgMtxIdxs[2], alpha[2],
|
||||||
|
ColorValue<hasPassColor[2], passColors[2][0], passColors[2][1], passColors[2][2],
|
||||||
|
passColors[2][3]>>, // emissive
|
||||||
|
PassTraits<texSources[3], normalize[3], tcgMtxIdxs[3], alpha[3],
|
||||||
|
ColorValue<hasPassColor[3], passColors[3][0], passColors[3][1], passColors[3][2],
|
||||||
|
passColors[3][3]>>, // specular
|
||||||
|
PassTraits<texSources[4], normalize[4], tcgMtxIdxs[4], alpha[4],
|
||||||
|
ColorValue<hasPassColor[4], passColors[4][0], passColors[4][1], passColors[4][2],
|
||||||
|
passColors[4][3]>>, // extended specular
|
||||||
|
PassTraits<texSources[5], normalize[5], tcgMtxIdxs[5], alpha[5],
|
||||||
|
ColorValue<hasPassColor[5], passColors[5][0], passColors[5][1], passColors[5][2],
|
||||||
|
passColors[5][3]>>, // reflection
|
||||||
|
PassTraits<texSources[6], normalize[6], tcgMtxIdxs[6], alpha[6],
|
||||||
|
ColorValue<hasPassColor[6], passColors[6][0], passColors[6][1], passColors[6][2],
|
||||||
|
passColors[6][3]>>, // alpha
|
||||||
|
false, // cube reflection
|
||||||
|
material.blendMode, material.flags.flags, modelFlags.x0_blendMode, modelFlags.x2_flags,
|
||||||
|
gx_ColorUpdate, gx_AlphaUpdate, gx_DstAlpha, gx_CullMode>(
|
||||||
|
vu, fragu, tcgu, refu, texs[0], texs[1], texs[2], texs[3], texs[4], texs[5], texs[6], texs[7], texs[8],
|
||||||
|
texs[9], texs[10], texs[11], vd, model.m_staticIbo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
struct CCubeMaterial {
|
struct CCubeMaterial {
|
||||||
const u8* x0_data;
|
const u8* x0_data;
|
||||||
static u32 sReflectionType;
|
static u32 sReflectionType;
|
||||||
|
@ -1170,5 +1181,6 @@ struct CCubeMaterial {
|
||||||
// SetNumColorChans(finalNumColorChans);
|
// SetNumColorChans(finalNumColorChans);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace urde
|
} // namespace urde
|
||||||
|
|
|
@ -55,50 +55,46 @@ enum class EExtendedShader : uint8_t {
|
||||||
MAX
|
MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class EShaderType : uint8_t {
|
enum class EShaderType : uint8_t { DiffuseOnly, Normal, Dynamic, DynamicAlpha, DynamicCharacter };
|
||||||
DiffuseOnly,
|
|
||||||
Normal,
|
|
||||||
Dynamic,
|
|
||||||
DynamicAlpha,
|
|
||||||
DynamicCharacter
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class EPostType : uint8_t {
|
enum class EPostType : uint8_t { Normal, ThermalHot, ThermalCold, Solid, MBShadow, Disintegrate };
|
||||||
Normal,
|
|
||||||
ThermalHot,
|
struct ModelInstance;
|
||||||
ThermalCold,
|
|
||||||
Solid,
|
|
||||||
MBShadow,
|
|
||||||
Disintegrate
|
|
||||||
};
|
|
||||||
|
|
||||||
class CModelShaders {
|
class CModelShaders {
|
||||||
friend class CModel;
|
friend class CModel;
|
||||||
hsh::binding m_dataBind;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <uint32_t NCol, uint32_t NUv, uint32_t NWeight>
|
template <uint32_t NCol, uint32_t NUv, uint32_t NWeight>
|
||||||
struct VertData {
|
struct VertData {
|
||||||
hsh::float3 posIn;
|
hsh::float3 posIn;
|
||||||
hsh::float3 normIn;
|
hsh::float3 normIn;
|
||||||
std::array<hsh::float4, NCol> colIn;
|
// FIXME: compiler bug?
|
||||||
std::array<hsh::float2, NUv> uvIn;
|
// [[no_unique_address]] hsh::array<hsh::float4, NCol> colIn;
|
||||||
std::array<hsh::float4, NWeight> weightIn;
|
[[no_unique_address]] hsh::array<hsh::float2, NUv> uvIn;
|
||||||
|
[[no_unique_address]] hsh::array<hsh::float4, NWeight> weightIn;
|
||||||
};
|
};
|
||||||
|
static_assert(sizeof(VertData<0, 0, 0>) == 24, "VertData size incorrect");
|
||||||
|
static_assert(sizeof(VertData<0, 1, 0>) == 32, "VertData size incorrect");
|
||||||
|
static_assert(sizeof(VertData<0, 2, 0>) == 40, "VertData size incorrect");
|
||||||
|
static_assert(sizeof(VertData<0, 1, 1>) == 48, "VertData size incorrect");
|
||||||
|
|
||||||
template <uint32_t NSkinSlots>
|
template <uint32_t NSkinSlots>
|
||||||
struct VertUniform {
|
struct VertUniform {
|
||||||
std::array<hsh::float4x4, NSkinSlots> objs;
|
hsh::array<hsh::float4x4, NSkinSlots> objs [[no_unique_address]];
|
||||||
std::array<hsh::float4x4, NSkinSlots> objsInv;
|
hsh::array<hsh::float4x4, NSkinSlots> objsInv [[no_unique_address]];
|
||||||
hsh::float4x4 mv;
|
hsh::float4x4 mv;
|
||||||
hsh::float4x4 mvInv;
|
hsh::float4x4 mvInv;
|
||||||
hsh::float4x4 proj;
|
hsh::float4x4 proj;
|
||||||
};
|
};
|
||||||
|
static_assert(sizeof(VertUniform<0>) == 192, "VertUniform size incorrect");
|
||||||
|
static_assert(sizeof(VertUniform<1>) == 320, "VertUniform size incorrect");
|
||||||
|
|
||||||
struct TCGMatrix {
|
struct TCGMatrix {
|
||||||
hsh::float4x4 mtx;
|
hsh::float4x4 mtx;
|
||||||
hsh::float4x4 postMtx;
|
hsh::float4x4 postMtx;
|
||||||
};
|
};
|
||||||
|
using TCGMatrixUniform = std::array<CModelShaders::TCGMatrix, 8>;
|
||||||
|
|
||||||
struct ReflectMtx {
|
struct ReflectMtx {
|
||||||
hsh::float4x4 indMtx;
|
hsh::float4x4 indMtx;
|
||||||
|
@ -110,8 +106,8 @@ public:
|
||||||
alignas(16) hsh::float3 pos;
|
alignas(16) hsh::float3 pos;
|
||||||
alignas(16) hsh::float3 dir;
|
alignas(16) hsh::float3 dir;
|
||||||
alignas(16) hsh::float4 color;
|
alignas(16) hsh::float4 color;
|
||||||
alignas(16) hsh::float3 linAtt;
|
alignas(16) hsh::float3 linAtt{1.f, 0.f, 0.f};
|
||||||
alignas(16) hsh::float3 angAtt;
|
alignas(16) hsh::float3 angAtt{1.f, 0.f, 0.f};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FragmentUniform {
|
struct FragmentUniform {
|
||||||
|
@ -124,9 +120,22 @@ public:
|
||||||
void ActivateLights(const std::vector<CLight>& lts);
|
void ActivateLights(const std::vector<CLight>& lts);
|
||||||
};
|
};
|
||||||
|
|
||||||
hsh::binding& SetCurrent(const CModelFlags& modelFlags, const CBooSurface& surface, const CBooModel& model);
|
static void SetCurrent(hsh::binding& binding, const CModelFlags& modelFlags, const CBooModel& model,
|
||||||
|
const ModelInstance& inst, const CBooSurface& surface);
|
||||||
|
|
||||||
using Material = DataSpec::DNAMP1::HMDLMaterialSet::Material;
|
using Material = DataSpec::DNAMP1::HMDLMaterialSet::Material;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ModelInstance {
|
||||||
|
hsh::dynamic_owner<hsh::uniform_buffer<CModelShaders::FragmentUniform>> m_fragmentUniform;
|
||||||
|
std::vector<hsh::dynamic_owner<hsh::uniform_buffer<CModelShaders::TCGMatrixUniform>>> m_tcgUniforms;
|
||||||
|
std::vector<hsh::dynamic_owner<hsh::uniform_buffer<CModelShaders::ReflectMtx>>> m_reflectUniforms;
|
||||||
|
std::vector<hsh::dynamic_owner<hsh::uniform_buffer_typeless>> m_geometryUniforms;
|
||||||
|
std::vector<hsh::binding> m_shaderDataBindings;
|
||||||
|
mutable hsh::dynamic_owner<hsh::vertex_buffer_typeless> m_dynamicVbo;
|
||||||
|
|
||||||
|
hsh::vertex_buffer_typeless GetBooVBO(const CBooModel& model) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace urde
|
} // namespace urde
|
||||||
|
|
Loading…
Reference in New Issue