diff --git a/package/Shaders/Common/SharedData.hlsli b/package/Shaders/Common/SharedData.hlsli index 6b9a2378ec..28613f5616 100644 --- a/package/Shaders/Common/SharedData.hlsli +++ b/package/Shaders/Common/SharedData.hlsli @@ -235,6 +235,12 @@ namespace SharedData float otherEffectMult; }; + struct TerrainBlendingSettings + { + uint Enabled; + uint3 _padding; + }; + cbuffer FeatureData : register(b6) { GrassLightingSettings grassLightingSettings; @@ -251,6 +257,7 @@ namespace SharedData IBLSettings iblSettings; ExtendedTranslucencySettings extendedTranslucencySettings; LinearLightingSettings linearLightingSettings; + TerrainBlendingSettings terrainBlendingSettings; }; Texture2D DepthTexture : register(t17); diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index 32aa25d717..b0af696f3c 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -990,17 +990,18 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # endif # if defined(TERRAIN_BLENDING) - float depthSampled = TerrainBlending::TerrainBlendingMaskTexture[input.Position.xy].x; + float blendFactorTerrain = 0.0; + [flatten] if (SharedData::terrainBlendingSettings.Enabled) { + float depthSampled = TerrainBlending::TerrainBlendingMaskTexture[input.Position.xy].x; - float depthSampledLinear = SharedData::GetScreenDepth(depthSampled); - float depthPixelLinear = SharedData::GetScreenDepth(input.Position.z); + float depthSampledLinear = SharedData::GetScreenDepth(depthSampled); + float depthPixelLinear = SharedData::GetScreenDepth(input.Position.z); - float blendFactorTerrain = saturate((depthSampledLinear - depthPixelLinear) / 10.0); + blendFactorTerrain = saturate((depthSampledLinear - depthPixelLinear) / 10.0); - if (input.Position.z == depthSampled) - blendFactorTerrain = 1; - - blendFactorTerrain = saturate(blendFactorTerrain); + if (input.Position.z == depthSampled) + blendFactorTerrain = 1; + } # endif float2 uv = input.TexCoord0.xy; @@ -3160,7 +3161,9 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # if defined(DEFERRED) # if defined(TERRAIN_BLENDING) - psout.Diffuse.w = blendFactorTerrain; + [flatten] if (SharedData::terrainBlendingSettings.Enabled) { + psout.Diffuse.w = blendFactorTerrain; + } # endif psout.MotionVectors.zw = float2(0.0, psout.Diffuse.w); diff --git a/src/Deferred.cpp b/src/Deferred.cpp index 6d59e3791d..723cc4afff 100644 --- a/src/Deferred.cpp +++ b/src/Deferred.cpp @@ -427,7 +427,7 @@ void Deferred::DeferredPasses() albedo.SRV, normalRoughness.SRV, masks.SRV, - dynamicCubemaps.loaded || REL::Module::IsVR() ? (terrainBlending.loaded ? terrainBlending.blendedDepthTexture16->srv.get() : depth.depthSRV) : nullptr, + dynamicCubemaps.loaded || REL::Module::IsVR() ? (terrainBlending.loaded && terrainBlending.settings.Enabled ? terrainBlending.blendedDepthTexture16->srv.get() : depth.depthSRV) : nullptr, dynamicCubemaps.loaded ? reflectance.SRV : nullptr, dynamicCubemaps.loaded ? dynamicCubemaps.envTexture->srv.get() : nullptr, dynamicCubemaps.loaded ? dynamicCubemaps.envReflectionsTexture->srv.get() : nullptr, @@ -691,8 +691,9 @@ void Deferred::Hooks::Main_RenderWorld_BlendedDecals::thunk(RE::BSShaderAccumula if (globals::shaderCache->IsEnabled() && globals::state->inWorld) { auto& terrainBlending = globals::features::terrainBlending; // Defer terrain rendering until after everything else - if (terrainBlending.loaded) + if (terrainBlending.loaded && terrainBlending.settings.Enabled) { terrainBlending.RenderTerrainBlendingPasses(); + } } // Deferred blended decals diff --git a/src/FeatureBuffer.cpp b/src/FeatureBuffer.cpp index 2cdb610111..5bf884053d 100644 --- a/src/FeatureBuffer.cpp +++ b/src/FeatureBuffer.cpp @@ -11,6 +11,7 @@ #include "Features/LightLimitFix.h" #include "Features/LinearLighting.h" #include "Features/Skylighting.h" +#include "Features/TerrainBlending.h" #include "Features/TerrainShadows.h" #include "Features/TerrainVariation.h" #include "Features/WetnessEffects.h" @@ -49,5 +50,6 @@ std::pair GetFeatureBufferData(bool a_inWorld) globals::features::terrainVariation.settings, globals::features::ibl.settings, globals::features::extendedTranslucency.GetCommonBufferData(), - globals::features::linearLighting.GetCommonBufferData()); + globals::features::linearLighting.GetCommonBufferData(), + globals::features::terrainBlending.settings); } \ No newline at end of file diff --git a/src/Features/SubsurfaceScattering.cpp b/src/Features/SubsurfaceScattering.cpp index 70416cd2e8..9a912e64a3 100644 --- a/src/Features/SubsurfaceScattering.cpp +++ b/src/Features/SubsurfaceScattering.cpp @@ -244,7 +244,7 @@ void SubsurfaceScattering::DrawSSS() ID3D11ShaderResourceView* views[5]; views[0] = main.SRV; - views[1] = terrainBlending.loaded ? terrainBlending.blendedDepthTexture16->srv.get() : depth.depthSRV; + views[1] = terrainBlending.loaded && terrainBlending.settings.Enabled ? terrainBlending.blendedDepthTexture16->srv.get() : depth.depthSRV; views[2] = mask.SRV; views[3] = albedo.SRV; views[4] = normal.SRV; diff --git a/src/Features/TerrainBlending.cpp b/src/Features/TerrainBlending.cpp index 5c119c81dc..57c7df4404 100644 --- a/src/Features/TerrainBlending.cpp +++ b/src/Features/TerrainBlending.cpp @@ -4,6 +4,28 @@ #include "ShaderCache.h" #include "State.h" +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT( + TerrainBlending::Settings, + Enabled) + +void TerrainBlending::DrawSettings() +{ + ImGui::Checkbox("Enable Terrain Blending", (bool*)&settings.Enabled); + if (auto _tt = Util::HoverTooltipWrapper()) { + ImGui::Text("Enable seamless blending between terrain and objects."); + } +} + +void TerrainBlending::LoadSettings(json& o_json) +{ + settings = o_json; +} + +void TerrainBlending::SaveSettings(json& o_json) +{ + o_json = settings; +} + ID3D11VertexShader* TerrainBlending::GetTerrainVertexShader() { if (!terrainVertexShader) { @@ -211,7 +233,7 @@ void TerrainBlending::Hooks::Main_RenderDepth::thunk(bool a1, bool a2) singleton.averageEyePosition = Util::GetAverageEyePosition(); - if (shaderCache->IsEnabled()) { + if (shaderCache->IsEnabled() && singleton.settings.Enabled) { mainDepth.depthSRV = singleton.blendedDepthTexture->srv.get(); zPrepassCopy.depthSRV = singleton.blendedDepthTexture->srv.get(); @@ -241,7 +263,7 @@ void TerrainBlending::Hooks::BSBatchRenderer__RenderPassImmediately::thunk(RE::B auto& singleton = globals::features::terrainBlending; auto shaderCache = globals::shaderCache; - if (shaderCache->IsEnabled()) { + if (shaderCache->IsEnabled() && singleton.settings.Enabled) { if (singleton.renderDepth) { // Entering or exiting terrain depth section bool inTerrain = a_pass->shaderProperty && a_pass->shaderProperty->flags.all(RE::BSShaderProperty::EShaderPropertyFlag::kMultiTextureLandscape); @@ -290,8 +312,7 @@ void TerrainBlending::RenderTerrainBlendingPasses() auto stateUpdateFlags = globals::game::stateUpdateFlags; // Used to get the distance of the surface to the lowest depth - auto view = terrainDepth.depthSRV; - context->PSSetShaderResources(55, 1, &view); + context->PSSetShaderResources(55, 1, &terrainDepth.depthSRV); if (!terrainRenderPasses.empty() || !renderPasses.empty()) { GET_INSTANCE_MEMBER(alphaBlendMode, shadowState) diff --git a/src/Features/TerrainBlending.h b/src/Features/TerrainBlending.h index 4ba058db18..676e003a3a 100644 --- a/src/Features/TerrainBlending.h +++ b/src/Features/TerrainBlending.h @@ -20,6 +20,19 @@ struct TerrainBlending : Feature } virtual inline bool HasShaderDefine(RE::BSShader::Type) override { return true; } + struct Settings + { + uint32_t Enabled = true; + uint32_t pad[3]; + }; + STATIC_ASSERT_ALIGNAS_16(Settings); + + Settings settings; + + virtual void DrawSettings() override; + virtual void LoadSettings(json& o_json) override; + virtual void SaveSettings(json& o_json) override; + virtual void SetupResources() override; ID3D11VertexShader* GetTerrainVertexShader(); diff --git a/src/State.cpp b/src/State.cpp index 67ab0ecaf5..29792bb533 100644 --- a/src/State.cpp +++ b/src/State.cpp @@ -34,7 +34,7 @@ void State::Draw() if (weatherEditor.loaded) WeatherManager::GetSingleton()->UpdateFeatures(); - if (terrainBlending.loaded) + if (terrainBlending.loaded && terrainBlending.settings.Enabled) terrainBlending.TerrainShaderHacks(); if (cloudShadows.loaded) @@ -828,7 +828,7 @@ void State::UpdateSharedData([[maybe_unused]] bool a_inWorld, [[maybe_unused]] b const auto& depth = globals::game::renderer->GetDepthStencilData().depthStencils[RE::RENDER_TARGETS_DEPTHSTENCIL::kPOST_ZPREPASS_COPY]; auto& terrainBlending = globals::features::terrainBlending; - auto srv = (terrainBlending.loaded ? terrainBlending.blendedDepthTexture16->srv.get() : depth.depthSRV); + auto srv = (terrainBlending.loaded && terrainBlending.settings.Enabled ? terrainBlending.blendedDepthTexture16->srv.get() : depth.depthSRV); globals::d3d::context->PSSetShaderResources(17, 1, &srv); }