From bbbe40939894f80d002820c9a21d55e1e7a6b43d Mon Sep 17 00:00:00 2001 From: FlayaN Date: Thu, 5 Oct 2023 14:40:15 +0200 Subject: [PATCH] refactor: move opt in for shaders to virtual feature function (#117) --- src/Feature.h | 3 + src/Features/ExtendedMaterials.cpp | 10 + src/Features/ExtendedMaterials.h | 3 + src/Features/GrassCollision.cpp | 10 + src/Features/GrassCollision.h | 3 + src/Features/LightLimitFix.cpp | 11 + src/Features/LightLimitFix.h | 3 + src/Features/RainWetnessEffects.cpp | 10 + src/Features/RainWetnessEffects.h | 3 + src/Features/ScreenSpaceShadows.cpp | 12 ++ src/Features/ScreenSpaceShadows.h | 3 + src/Features/WaterBlending.cpp | 10 + src/Features/WaterBlending.h | 3 + src/Menu.cpp | 4 - src/ShaderCache.cpp | 320 +++++++++++----------------- 15 files changed, 213 insertions(+), 195 deletions(-) diff --git a/src/Feature.h b/src/Feature.h index 183e52052..3dd4652a9 100644 --- a/src/Feature.h +++ b/src/Feature.h @@ -7,6 +7,9 @@ struct Feature virtual std::string GetName() = 0; virtual std::string GetShortName() = 0; + virtual std::string_view GetShaderDefineName() { return ""; } + + virtual bool HasShaderDefine(RE::BSShader::Type) { return false; } virtual void SetupResources() = 0; virtual void Reset() = 0; diff --git a/src/Features/ExtendedMaterials.cpp b/src/Features/ExtendedMaterials.cpp index d87271603..642b5a20a 100644 --- a/src/Features/ExtendedMaterials.cpp +++ b/src/Features/ExtendedMaterials.cpp @@ -236,4 +236,14 @@ void ExtendedMaterials::Load(json& o_json) void ExtendedMaterials::Save(json& o_json) { o_json[GetName()] = settings; +} + +bool ExtendedMaterials::HasShaderDefine(RE::BSShader::Type shaderType) +{ + switch (shaderType) { + case RE::BSShader::Type::Lighting: + return true; + default: + return false; + } } \ No newline at end of file diff --git a/src/Features/ExtendedMaterials.h b/src/Features/ExtendedMaterials.h index 4bbdd8d26..134ceb036 100644 --- a/src/Features/ExtendedMaterials.h +++ b/src/Features/ExtendedMaterials.h @@ -13,6 +13,9 @@ struct ExtendedMaterials : Feature virtual inline std::string GetName() { return "Complex Parallax Materials"; } virtual inline std::string GetShortName() { return "ComplexParallaxMaterials"; } + inline std::string_view GetShaderDefineName() override { return "COMPLEX_PARALLAX_MATERIALS"; } + + bool HasShaderDefine(RE::BSShader::Type shaderType) override; struct Settings { diff --git a/src/Features/GrassCollision.cpp b/src/Features/GrassCollision.cpp index 7bdada71a..8e9d9a10e 100644 --- a/src/Features/GrassCollision.cpp +++ b/src/Features/GrassCollision.cpp @@ -335,4 +335,14 @@ void GrassCollision::SetupResources() void GrassCollision::Reset() { updatePerFrame = true; +} + +bool GrassCollision::HasShaderDefine(RE::BSShader::Type shaderType) +{ + switch (shaderType) { + case RE::BSShader::Type::Grass: + return true; + default: + return false; + } } \ No newline at end of file diff --git a/src/Features/GrassCollision.h b/src/Features/GrassCollision.h index ffc955e6e..e6ae80136 100644 --- a/src/Features/GrassCollision.h +++ b/src/Features/GrassCollision.h @@ -13,6 +13,9 @@ struct GrassCollision : Feature virtual inline std::string GetName() { return "Grass Collision"; } virtual inline std::string GetShortName() { return "GrassCollision"; } + inline std::string_view GetShaderDefineName() override { return "GRASS_COLLISION"; } + + bool HasShaderDefine(RE::BSShader::Type shaderType) override; struct Settings { diff --git a/src/Features/LightLimitFix.cpp b/src/Features/LightLimitFix.cpp index 60de734c2..9938c794b 100644 --- a/src/Features/LightLimitFix.cpp +++ b/src/Features/LightLimitFix.cpp @@ -957,4 +957,15 @@ void LightLimitFix::UpdateLights() context->CSSetShaderResources(0, ARRAYSIZE(null_srvs), null_srvs); ID3D11UnorderedAccessView* null_uavs[3] = { nullptr }; context->CSSetUnorderedAccessViews(0, ARRAYSIZE(null_uavs), null_uavs, nullptr); +} + +bool LightLimitFix::HasShaderDefine(RE::BSShader::Type shaderType) +{ + switch (shaderType) { + case RE::BSShader::Type::Lighting: + case RE::BSShader::Type::Grass: + return true; + default: + return false; + } } \ No newline at end of file diff --git a/src/Features/LightLimitFix.h b/src/Features/LightLimitFix.h index 5ca5cb6d3..0e6e44643 100644 --- a/src/Features/LightLimitFix.h +++ b/src/Features/LightLimitFix.h @@ -24,6 +24,9 @@ struct LightLimitFix : Feature } virtual inline std::string GetName() { return "Light Limit Fix"; } virtual inline std::string GetShortName() { return "LightLimitFix"; } + inline std::string_view GetShaderDefineName() override { return "LIGHT_LIMIT_FIX"; } + + bool HasShaderDefine(RE::BSShader::Type shaderType) override; struct LightData { diff --git a/src/Features/RainWetnessEffects.cpp b/src/Features/RainWetnessEffects.cpp index e5614462d..4ab31d609 100644 --- a/src/Features/RainWetnessEffects.cpp +++ b/src/Features/RainWetnessEffects.cpp @@ -346,4 +346,14 @@ void RainWetnessEffects::Load(json& o_json) void RainWetnessEffects::Save(json& o_json) { o_json[GetName()] = settings; +} + +bool RainWetnessEffects::HasShaderDefine(RE::BSShader::Type shaderType) +{ + switch (shaderType) { + case RE::BSShader::Type::Lighting: + return true; + default: + return false; + } } \ No newline at end of file diff --git a/src/Features/RainWetnessEffects.h b/src/Features/RainWetnessEffects.h index cdffbf878..f330c87ba 100644 --- a/src/Features/RainWetnessEffects.h +++ b/src/Features/RainWetnessEffects.h @@ -14,6 +14,9 @@ struct RainWetnessEffects : Feature virtual inline std::string GetName() { return "Rain Wetness Effects"; } virtual inline std::string GetShortName() { return "RainWetnessEffects"; } + inline std::string_view GetShaderDefineName() override { return "RAIN_WETNESS_EFFECTS"; } + + bool HasShaderDefine(RE::BSShader::Type shaderType) override; struct Settings { diff --git a/src/Features/ScreenSpaceShadows.cpp b/src/Features/ScreenSpaceShadows.cpp index 9addd1ba1..10b2c5c8c 100644 --- a/src/Features/ScreenSpaceShadows.cpp +++ b/src/Features/ScreenSpaceShadows.cpp @@ -509,4 +509,16 @@ void ScreenSpaceShadows::SetupResources() void ScreenSpaceShadows::Reset() { renderedScreenCamera = false; +} + +bool ScreenSpaceShadows::HasShaderDefine(RE::BSShader::Type shaderType) +{ + switch (shaderType) { + case RE::BSShader::Type::Lighting: + case RE::BSShader::Type::Grass: + case RE::BSShader::Type::DistantTree: + return true; + default: + return false; + } } \ No newline at end of file diff --git a/src/Features/ScreenSpaceShadows.h b/src/Features/ScreenSpaceShadows.h index d060eccb0..332930b35 100644 --- a/src/Features/ScreenSpaceShadows.h +++ b/src/Features/ScreenSpaceShadows.h @@ -13,6 +13,9 @@ struct ScreenSpaceShadows : Feature virtual inline std::string GetName() { return "Screen-Space Shadows"; } virtual inline std::string GetShortName() { return "ScreenSpaceShadows"; } + inline std::string_view GetShaderDefineName() override { return "SCREEN_SPACE_SHADOWS"; } + + bool HasShaderDefine(RE::BSShader::Type shaderType) override; struct Settings { diff --git a/src/Features/WaterBlending.cpp b/src/Features/WaterBlending.cpp index 0d688a749..f218f12be 100644 --- a/src/Features/WaterBlending.cpp +++ b/src/Features/WaterBlending.cpp @@ -123,4 +123,14 @@ void WaterBlending::Load(json& o_json) void WaterBlending::Save(json& o_json) { o_json[GetName()] = settings; +} + +bool WaterBlending::HasShaderDefine(RE::BSShader::Type shaderType) +{ + switch (shaderType) { + case RE::BSShader::Type::Water: + return true; + default: + return false; + } } \ No newline at end of file diff --git a/src/Features/WaterBlending.h b/src/Features/WaterBlending.h index 6dba2ffaf..603285f45 100644 --- a/src/Features/WaterBlending.h +++ b/src/Features/WaterBlending.h @@ -14,6 +14,9 @@ struct WaterBlending : Feature virtual inline std::string GetName() { return "Water Blending"; } virtual inline std::string GetShortName() { return "WaterBlending"; } + inline std::string_view GetShaderDefineName() override { return "WATER_BLENDING"; } + + bool HasShaderDefine(RE::BSShader::Type shaderType) override; struct Settings { diff --git a/src/Menu.cpp b/src/Menu.cpp index 02a8291a0..af76930e5 100644 --- a/src/Menu.cpp +++ b/src/Menu.cpp @@ -8,11 +8,7 @@ #include "State.h" #include "Feature.h" -#include "Features/ExtendedMaterials.h" #include "Features/LightLimitFix/ParticleLights.h" -#include "Features/RainWetnessEffects.h" -#include "Features/ScreenSpaceShadows.h" -#include "Features/WaterBlending.h" #define SETTING_MENU_TOGGLEKEY "Toggle Key" #define SETTING_MENU_SKIPKEY "Skip Compilation Key" diff --git a/src/ShaderCache.cpp b/src/ShaderCache.cpp index ec74ebf10..002428c3c 100644 --- a/src/ShaderCache.cpp +++ b/src/ShaderCache.cpp @@ -7,12 +7,7 @@ #include #include -#include "Features/ExtendedMaterials.h" -#include "Features/GrassCollision.h" -#include "Features/LightLimitFix.h" -#include "Features/RainWetnessEffects.h" -#include "Features/ScreenSpaceShadows.h" -#include "Features/WaterBlending.h" +#include "Feature.h" #include "State.h" namespace SIE @@ -57,32 +52,19 @@ namespace SIE const auto technique = static_cast(GetTechnique(descriptor)); - if (technique == ShaderCache::LightingShaderTechniques::Outline) { - defines[0] = { "OUTLINE", nullptr }; - ++defines; - } - - if (ScreenSpaceShadows::GetSingleton()->loaded) { - defines[0] = { "SCREEN_SPACE_SHADOWS", nullptr }; - ++defines; - } + int lastIndex = 0; - if (ExtendedMaterials::GetSingleton()->loaded) { - defines[0] = { "COMPLEX_PARALLAX_MATERIALS", nullptr }; - ++defines; - } - - if (LightLimitFix::GetSingleton()->loaded) { - defines[0] = { "LIGHT_LIMIT_FIX", nullptr }; - ++defines; + if (technique == ShaderCache::LightingShaderTechniques::Outline) { + defines[lastIndex++] = { "OUTLINE", nullptr }; } - if (RainWetnessEffects::GetSingleton()->loaded) { - defines[0] = { "RAIN_WETNESS_EFFECTS", nullptr }; - ++defines; + for (auto* feature : Feature::GetFeatureList()) { + if (feature->loaded && feature->HasShaderDefine(RE::BSShader::Type::Lighting)) { + defines[lastIndex++] = { feature->GetShaderDefineName().data(), nullptr }; + } } - VanillaGetLightingShaderDefines(descriptor, defines); + VanillaGetLightingShaderDefines(descriptor, defines + lastIndex); } enum class BloodSplatterShaderTechniques @@ -93,14 +75,20 @@ namespace SIE static void GetBloodSplaterShaderDefines(uint32_t descriptor, D3D_SHADER_MACRO* defines) { + int lastIndex = 0; if (descriptor == static_cast(BloodSplatterShaderTechniques::Splatter)) { - defines[0] = { "SPLATTER", nullptr }; - ++defines; + defines[lastIndex++] = { "SPLATTER", nullptr }; } else if (descriptor == static_cast(BloodSplatterShaderTechniques::Flare)) { - defines[0] = { "FLARE", nullptr }; - ++defines; + defines[lastIndex++] = { "FLARE", nullptr }; + } + + for (auto* feature : Feature::GetFeatureList()) { + if (feature->loaded && feature->HasShaderDefine(RE::BSShader::Type::BloodSplatter)) { + defines[lastIndex++] = { feature->GetShaderDefineName().data(), nullptr }; + } } - defines[0] = { nullptr, nullptr }; + + defines[lastIndex] = { nullptr, nullptr }; } enum class DistantTreeShaderTechniques @@ -117,21 +105,21 @@ namespace SIE static void GetDistantTreeShaderDefines(uint32_t descriptor, D3D_SHADER_MACRO* defines) { const auto technique = descriptor & 1; + int lastIndex = 0; if (technique == static_cast(DistantTreeShaderTechniques::Depth)) { - defines[0] = { "RENDER_DEPTH", nullptr }; - ++defines; + defines[lastIndex++] = { "RENDER_DEPTH", nullptr }; } if (descriptor & static_cast(DistantTreeShaderFlags::AlphaTest)) { - defines[0] = { "DO_ALPHA_TEST", nullptr }; - ++defines; + defines[lastIndex++] = { "DO_ALPHA_TEST", nullptr }; } - if (ScreenSpaceShadows::GetSingleton()->loaded) { - defines[0] = { "SCREEN_SPACE_SHADOWS", nullptr }; - ++defines; + for (auto* feature : Feature::GetFeatureList()) { + if (feature->loaded && feature->HasShaderDefine(RE::BSShader::Type::DistantTree)) { + defines[lastIndex++] = { feature->GetShaderDefineName().data(), nullptr }; + } } - defines[0] = { nullptr, nullptr }; + defines[lastIndex] = { nullptr, nullptr }; } enum class SkyShaderTechniques @@ -150,71 +138,69 @@ namespace SIE static void GetSkyShaderDefines(uint32_t descriptor, D3D_SHADER_MACRO* defines) { const auto technique = static_cast(descriptor); + int lastIndex = 0; switch (technique) { case SkyShaderTechniques::SunOcclude: { - defines[0] = { "OCCLUSION", nullptr }; - ++defines; + defines[lastIndex++] = { "OCCLUSION", nullptr }; break; } case SkyShaderTechniques::SunGlare: { - defines[0] = { "TEX", nullptr }; - defines[1] = { "DITHER", nullptr }; - defines += 2; + defines[lastIndex++] = { "TEX", nullptr }; + defines[lastIndex++] = { "DITHER", nullptr }; break; } case SkyShaderTechniques::MoonAndStarsMask: { - defines[0] = { "TEX", nullptr }; - defines[1] = { "MOONMASK", nullptr }; - defines += 2; + defines[lastIndex++] = { "TEX", nullptr }; + defines[lastIndex++] = { "MOONMASK", nullptr }; break; } case SkyShaderTechniques::Stars: { - defines[0] = { "HORIZFADE", nullptr }; - ++defines; + defines[lastIndex++] = { "HORIZFADE", nullptr }; break; } case SkyShaderTechniques::Clouds: { - defines[0] = { "TEX", nullptr }; - defines[1] = { "CLOUDS", nullptr }; - defines += 2; + defines[lastIndex++] = { "TEX", nullptr }; + defines[lastIndex++] = { "CLOUDS", nullptr }; break; } case SkyShaderTechniques::CloudsLerp: { - defines[0] = { "TEX", nullptr }; - defines[1] = { "CLOUDS", nullptr }; - defines[2] = { "TEXLERP", nullptr }; - defines += 3; + defines[lastIndex++] = { "TEX", nullptr }; + defines[lastIndex++] = { "CLOUDS", nullptr }; + defines[lastIndex++] = { "TEXLERP", nullptr }; break; } case SkyShaderTechniques::CloudsFade: { - defines[0] = { "TEX", nullptr }; - defines[1] = { "CLOUDS", nullptr }; - defines[2] = { "TEXFADE", nullptr }; - defines += 3; + defines[lastIndex++] = { "TEX", nullptr }; + defines[lastIndex++] = { "CLOUDS", nullptr }; + defines[lastIndex++] = { "TEXFADE", nullptr }; break; } case SkyShaderTechniques::Texture: { - defines[0] = { "TEX", nullptr }; - ++defines; + defines[lastIndex++] = { "TEX", nullptr }; break; } case SkyShaderTechniques::Sky: { - defines[0] = { "DITHER", nullptr }; - ++defines; + defines[lastIndex++] = { "DITHER", nullptr }; break; } } - defines[0] = { nullptr, nullptr }; + for (auto* feature : Feature::GetFeatureList()) { + if (feature->loaded && feature->HasShaderDefine(RE::BSShader::Type::Sky)) { + defines[lastIndex++] = { feature->GetShaderDefineName().data(), nullptr }; + } + } + + defines[lastIndex] = { nullptr, nullptr }; } enum class GrassShaderTechniques @@ -230,31 +216,21 @@ namespace SIE static void GetGrassShaderDefines(uint32_t descriptor, D3D_SHADER_MACRO* defines) { const auto technique = descriptor & 0b1111; + int lastIndex = 0; if (technique == static_cast(GrassShaderTechniques::RenderDepth)) { - defines[0] = { "RENDER_DEPTH", nullptr }; - ++defines; + defines[lastIndex++] = { "RENDER_DEPTH", nullptr }; } if (descriptor & static_cast(GrassShaderFlags::AlphaTest)) { - defines[0] = { "DO_ALPHA_TEST", nullptr }; - ++defines; - } - - if (GrassCollision::GetSingleton()->loaded) { - defines[0] = { "GRASS_COLLISION", nullptr }; - ++defines; - } - - if (ScreenSpaceShadows::GetSingleton()->loaded) { - defines[0] = { "SCREEN_SPACE_SHADOWS", nullptr }; - ++defines; + defines[lastIndex++] = { "DO_ALPHA_TEST", nullptr }; } - if (LightLimitFix::GetSingleton()->loaded) { - defines[0] = { "LIGHT_LIMIT_FIX", nullptr }; - ++defines; + for (auto* feature : Feature::GetFeatureList()) { + if (feature->loaded && feature->HasShaderDefine(RE::BSShader::Type::Grass)) { + defines[lastIndex++] = { feature->GetShaderDefineName().data(), nullptr }; + } } - defines[0] = { nullptr, nullptr }; + defines[lastIndex] = { nullptr, nullptr }; } enum class ParticleShaderTechniques @@ -270,43 +246,45 @@ namespace SIE static void GetParticleShaderDefines(uint32_t descriptor, D3D_SHADER_MACRO* defines) { const auto technique = static_cast(descriptor); + int lastIndex = 0; switch (technique) { case ParticleShaderTechniques::ParticlesGryColor: { - defines[0] = { "GRAYSCALE_TO_COLOR", nullptr }; - ++defines; + defines[lastIndex++] = { "GRAYSCALE_TO_COLOR", nullptr }; break; } case ParticleShaderTechniques::ParticlesGryAlpha: { - defines[0] = { "GRAYSCALE_TO_ALPHA", nullptr }; - ++defines; + defines[lastIndex++] = { "GRAYSCALE_TO_ALPHA", nullptr }; break; } case ParticleShaderTechniques::ParticlesGryColorAlpha: { - defines[0] = { "GRAYSCALE_TO_COLOR", nullptr }; - defines[1] = { "GRAYSCALE_TO_ALPHA", nullptr }; - defines += 2; + defines[lastIndex++] = { "GRAYSCALE_TO_COLOR", nullptr }; + defines[lastIndex++] = { "GRAYSCALE_TO_ALPHA", nullptr }; break; } case ParticleShaderTechniques::EnvCubeSnow: { - defines[0] = { "ENVCUBE", nullptr }; - defines[1] = { "SNOW", nullptr }; - defines += 2; + defines[lastIndex++] = { "ENVCUBE", nullptr }; + defines[lastIndex++] = { "SNOW", nullptr }; break; } case ParticleShaderTechniques::EnvCubeRain: { - defines[0] = { "ENVCUBE", nullptr }; - defines[1] = { "RAIN", nullptr }; - defines += 2; + defines[lastIndex++] = { "ENVCUBE", nullptr }; + defines[lastIndex++] = { "RAIN", nullptr }; break; } } - defines[0] = { nullptr, nullptr }; + for (auto* feature : Feature::GetFeatureList()) { + if (feature->loaded && feature->HasShaderDefine(RE::BSShader::Type::Particle)) { + defines[lastIndex++] = { feature->GetShaderDefineName().data(), nullptr }; + } + } + + defines[lastIndex] = { nullptr, nullptr }; } enum class EffectShaderFlags @@ -341,192 +319,152 @@ namespace SIE static void GetEffectShaderDefines(uint32_t descriptor, D3D_SHADER_MACRO* defines) { + int lastIndex = 0; if (descriptor & static_cast(EffectShaderFlags::Vc)) { - defines[0] = { "VC", nullptr }; - ++defines; + defines[lastIndex++] = { "VC", nullptr }; } if (descriptor & static_cast(EffectShaderFlags::TexCoord)) { - defines[0] = { "TEXCOORD", nullptr }; - ++defines; + defines[lastIndex++] = { "TEXCOORD", nullptr }; } if (descriptor & static_cast(EffectShaderFlags::TexCoordIndex)) { - defines[0] = { "TEXCOORD_INDEX", nullptr }; - ++defines; + defines[lastIndex++] = { "TEXCOORD_INDEX", nullptr }; } if (descriptor & static_cast(EffectShaderFlags::Skinned)) { - defines[0] = { "SKINNED", nullptr }; - ++defines; + defines[lastIndex++] = { "SKINNED", nullptr }; } if (descriptor & static_cast(EffectShaderFlags::Normals)) { - defines[0] = { "NORMALS", nullptr }; - ++defines; + defines[lastIndex++] = { "NORMALS", nullptr }; } if (descriptor & static_cast(EffectShaderFlags::BinormalTangent)) { - defines[0] = { "BINORMAL_TANGENT", nullptr }; - ++defines; + defines[lastIndex++] = { "BINORMAL_TANGENT", nullptr }; } if (descriptor & static_cast(EffectShaderFlags::Texture)) { - defines[0] = { "TEXTURE", nullptr }; - ++defines; + defines[lastIndex++] = { "TEXTURE", nullptr }; } if (descriptor & static_cast(EffectShaderFlags::IndexedTexture)) { - defines[0] = { "INDEXED_TEXTURE", nullptr }; - ++defines; + defines[lastIndex++] = { "INDEXED_TEXTURE", nullptr }; } if (descriptor & static_cast(EffectShaderFlags::Falloff)) { - defines[0] = { "FALLOFF", nullptr }; - ++defines; + defines[lastIndex++] = { "FALLOFF", nullptr }; } if (descriptor & static_cast(EffectShaderFlags::AddBlend)) { - defines[0] = { "ADDBLEND", nullptr }; - ++defines; + defines[lastIndex++] = { "ADDBLEND", nullptr }; } if (descriptor & static_cast(EffectShaderFlags::MultBlend)) { - defines[0] = { "MULTBLEND", nullptr }; - ++defines; + defines[lastIndex++] = { "MULTBLEND", nullptr }; } if (descriptor & static_cast(EffectShaderFlags::Particles)) { - defines[0] = { "PARTICLES", nullptr }; - ++defines; + defines[lastIndex++] = { "PARTICLES", nullptr }; } if (descriptor & static_cast(EffectShaderFlags::StripParticles)) { - defines[0] = { "STRIP_PARTICLES", nullptr }; - ++defines; + defines[lastIndex++] = { "STRIP_PARTICLES", nullptr }; } if (descriptor & static_cast(EffectShaderFlags::Blood)) { - defines[0] = { "BLOOD", nullptr }; - ++defines; + defines[lastIndex++] = { "BLOOD", nullptr }; } if (descriptor & static_cast(EffectShaderFlags::Membrane)) { - defines[0] = { "MEMBRANE", nullptr }; - ++defines; + defines[lastIndex++] = { "MEMBRANE", nullptr }; } if (descriptor & static_cast(EffectShaderFlags::Lighting)) { - defines[0] = { "LIGHTING", nullptr }; - ++defines; + defines[lastIndex++] = { "LIGHTING", nullptr }; } if (descriptor & static_cast(EffectShaderFlags::ProjectedUv)) { - defines[0] = { "PROJECTED_UV", nullptr }; - ++defines; + defines[lastIndex++] = { "PROJECTED_UV", nullptr }; } if (descriptor & static_cast(EffectShaderFlags::Soft)) { - defines[0] = { "SOFT", nullptr }; - ++defines; + defines[lastIndex++] = { "SOFT", nullptr }; } if (descriptor & static_cast(EffectShaderFlags::GrayscaleToColor)) { - defines[0] = { "GRAYSCALE_TO_COLOR", nullptr }; - ++defines; + defines[lastIndex++] = { "GRAYSCALE_TO_COLOR", nullptr }; } if (descriptor & static_cast(EffectShaderFlags::GrayscaleToAlpha)) { - defines[0] = { "GRAYSCALE_TO_ALPHA", nullptr }; - ++defines; + defines[lastIndex++] = { "GRAYSCALE_TO_ALPHA", nullptr }; } if (descriptor & static_cast(EffectShaderFlags::IgnoreTexAlpha)) { - defines[0] = { "IGNORE_TEX_ALPHA", nullptr }; - ++defines; + defines[lastIndex++] = { "IGNORE_TEX_ALPHA", nullptr }; } if (descriptor & static_cast(EffectShaderFlags::MultBlendDecal)) { - defines[0] = { "MULTBLEND_DECAL", nullptr }; - ++defines; + defines[lastIndex++] = { "MULTBLEND_DECAL", nullptr }; } if (descriptor & static_cast(EffectShaderFlags::AlphaTest)) { - defines[0] = { "ALPHA_TEST", nullptr }; - ++defines; + defines[lastIndex++] = { "ALPHA_TEST", nullptr }; } if (descriptor & static_cast(EffectShaderFlags::SkyObject)) { - defines[0] = { "SKY_OBJECT", nullptr }; - ++defines; + defines[lastIndex++] = { "SKY_OBJECT", nullptr }; } if (descriptor & static_cast(EffectShaderFlags::MsnSpuSkinned)) { - defines[0] = { "MSN_SPU_SKINNED", nullptr }; - ++defines; + defines[lastIndex++] = { "MSN_SPU_SKINNED", nullptr }; } if (descriptor & static_cast(EffectShaderFlags::MotionVectorsNormals)) { - defines[0] = { "MOTIONVECTORS_NORMALS", nullptr }; - ++defines; + defines[lastIndex++] = { "MOTIONVECTORS_NORMALS", nullptr }; } - defines[0] = { nullptr, nullptr }; + defines[lastIndex] = { nullptr, nullptr }; } static void GetWaterShaderDefines(uint32_t descriptor, D3D_SHADER_MACRO* defines) { - defines[0] = { "WATER", nullptr }; - defines[1] = { "FOG", nullptr }; - defines += 2; + int lastIndex = 0; + defines[lastIndex++] = { "WATER", nullptr }; + defines[lastIndex++] = { "FOG", nullptr }; if (descriptor & static_cast(ShaderCache::WaterShaderFlags::Vc)) { - defines[0] = { "VC", nullptr }; - ++defines; + defines[lastIndex++] = { "VC", nullptr }; } if (descriptor & static_cast(ShaderCache::WaterShaderFlags::NormalTexCoord)) { - defines[0] = { "NORMAL_TEXCOORD", nullptr }; - ++defines; + defines[lastIndex++] = { "NORMAL_TEXCOORD", nullptr }; } if (descriptor & static_cast(ShaderCache::WaterShaderFlags::Reflections)) { - defines[0] = { "REFLECTIONS", nullptr }; - ++defines; + defines[lastIndex++] = { "REFLECTIONS", nullptr }; } if (descriptor & static_cast(ShaderCache::WaterShaderFlags::Refractions)) { - defines[0] = { "REFRACTIONS", nullptr }; - ++defines; + defines[lastIndex++] = { "REFRACTIONS", nullptr }; } if (descriptor & static_cast(ShaderCache::WaterShaderFlags::Depth)) { - defines[0] = { "DEPTH", nullptr }; - ++defines; + defines[lastIndex++] = { "DEPTH", nullptr }; } if (descriptor & static_cast(ShaderCache::WaterShaderFlags::Interior)) { - defines[0] = { "INTERIOR", nullptr }; - ++defines; + defines[lastIndex++] = { "INTERIOR", nullptr }; } if (descriptor & static_cast(ShaderCache::WaterShaderFlags::Wading)) { - defines[0] = { "WADING", nullptr }; - ++defines; + defines[lastIndex++] = { "WADING", nullptr }; } if (descriptor & static_cast(ShaderCache::WaterShaderFlags::VertexAlphaDepth)) { - defines[0] = { "VERTEX_ALPHA_DEPTH", nullptr }; - ++defines; + defines[lastIndex++] = { "VERTEX_ALPHA_DEPTH", nullptr }; } if (descriptor & static_cast(ShaderCache::WaterShaderFlags::Cubemap)) { - defines[0] = { "CUBEMAP", nullptr }; - ++defines; + defines[lastIndex++] = { "CUBEMAP", nullptr }; } if (descriptor & static_cast(ShaderCache::WaterShaderFlags::Flowmap)) { - defines[0] = { "FLOWMAP", nullptr }; - ++defines; + defines[lastIndex++] = { "FLOWMAP", nullptr }; } if (descriptor & static_cast(ShaderCache::WaterShaderFlags::BlendNormals)) { - defines[0] = { "BLEND_NORMALS", nullptr }; - ++defines; + defines[lastIndex++] = { "BLEND_NORMALS", nullptr }; } const auto technique = (descriptor >> 11) & 0xF; if (technique == static_cast(ShaderCache::WaterShaderTechniques::Underwater)) { - defines[0] = { "UNDERWATER", nullptr }; - ++defines; + defines[lastIndex++] = { "UNDERWATER", nullptr }; } else if (technique == static_cast(ShaderCache::WaterShaderTechniques::Lod)) { - defines[0] = { "LOD", nullptr }; - ++defines; + defines[lastIndex++] = { "LOD", nullptr }; } else if (technique == static_cast(ShaderCache::WaterShaderTechniques::Stencil)) { - defines[0] = { "STENCIL", nullptr }; - ++defines; + defines[lastIndex++] = { "STENCIL", nullptr }; } else if (technique == static_cast(ShaderCache::WaterShaderTechniques::Simple)) { - defines[0] = { "SIMPLE", nullptr }; - ++defines; + defines[lastIndex++] = { "SIMPLE", nullptr }; } else if (technique < 8) { static constexpr std::array numLightDefines = { { "0", "1", "2", "3", "4", "5", "6", "7" } }; - defines[0] = { "SPECULAR", nullptr }; - defines[1] = { "NUM_SPECULAR_LIGHTS", numLightDefines[technique] }; - defines += 2; + defines[lastIndex++] = { "SPECULAR", nullptr }; + defines[lastIndex++] = { "NUM_SPECULAR_LIGHTS", numLightDefines[technique] }; } - if (WaterBlending::GetSingleton()->loaded) { - defines[0] = { "WATER_BLENDING", nullptr }; - ++defines; + for (auto* feature : Feature::GetFeatureList()) { + if (feature->loaded && feature->HasShaderDefine(RE::BSShader::Type::Water)) { + defines[lastIndex++] = { feature->GetShaderDefineName().data(), nullptr }; + } } - defines[0] = { nullptr, nullptr }; + defines[lastIndex] = { nullptr, nullptr }; } static void GetShaderDefines(RE::BSShader::Type type, uint32_t descriptor,