From 4935935dac35a5d584338a456f3f507451b76131 Mon Sep 17 00:00:00 2001 From: Jiaye Date: Tue, 17 Mar 2026 14:21:11 +0800 Subject: [PATCH 1/3] fix(water): use hdr water buffer --- package/Shaders/ISWaterBlend.hlsl | 27 +++++---------------------- src/Deferred.cpp | 4 ++++ 2 files changed, 9 insertions(+), 22 deletions(-) diff --git a/package/Shaders/ISWaterBlend.hlsl b/package/Shaders/ISWaterBlend.hlsl index 5ae303af10..056df78264 100644 --- a/package/Shaders/ISWaterBlend.hlsl +++ b/package/Shaders/ISWaterBlend.hlsl @@ -7,7 +7,7 @@ typedef VS_OUTPUT PS_INPUT; struct PS_OUTPUT { float3 Color: SV_Target0; - float4 Color1: SV_Target1; + float3 Color1: SV_Target1; }; #if defined(PSHADER) @@ -28,22 +28,6 @@ cbuffer PerGeometry : register(b2) float4 NearFar_Menu_DistanceFactor : packoffset(c0); }; -float3 LogToLinear(float3 logColor) -{ - const float linearRange = 14.0f; - const float linearGrey = 0.18f; - const float exposureGrey = 444.0f; - return exp2((logColor - exposureGrey / 1023.0) * linearRange) * linearGrey; -} - -float3 LinearToLog(float3 linearColor) -{ - const float linearRange = 14.0f; - const float linearGrey = 0.18f; - const float exposureGrey = 444.0f; - return saturate(log2(linearColor) / linearRange - log2(linearGrey) / linearRange + exposureGrey / 1023.0f); -} - PS_OUTPUT main(PS_INPUT input) { PS_OUTPUT psout; @@ -59,16 +43,15 @@ PS_OUTPUT main(PS_INPUT input) float2 motionScreenPosition = Stereo::ConvertToStereoUV(Stereo::ConvertFromStereoUV(input.TexCoord, eyeIndex) + motion, eyeIndex); float2 motionAdjustedScreenPosition = FrameBuffer::GetPreviousDynamicResolutionAdjustedScreenPosition(motionScreenPosition); - float4 waterHistory = - waterHistoryTex.Sample(waterHistorySampler, motionAdjustedScreenPosition).xyzw; - waterHistory.xyz = LogToLinear(waterHistory.xyz) - LogToLinear(0); + float3 waterHistory = + waterHistoryTex.Sample(waterHistorySampler, motionAdjustedScreenPosition).xyz; float3 finalColor = sourceColor; if ( # ifndef VR motionScreenPosition.x >= 0 && motionScreenPosition.y >= 0 && motionScreenPosition.x <= 1 && # endif - motionScreenPosition.y <= 1 && waterHistory.w == 1) { + motionScreenPosition.y <= 1 && any(waterHistory)) { float historyFactor = 0.95; if (NearFar_Menu_DistanceFactor.z == 0) { float depth = depthBufferTex.Sample(depthBufferSampler, adjustedScreenPosition).x; @@ -84,7 +67,7 @@ PS_OUTPUT main(PS_INPUT input) finalColor = lerp(sourceColor, waterHistory.xyz, historyFactor); } - psout.Color1 = float4(LinearToLog(finalColor + LogToLinear(0)), 1); + psout.Color1 = finalColor; psout.Color = finalColor; return psout; diff --git a/src/Deferred.cpp b/src/Deferred.cpp index a0a322500b..0106b7449d 100644 --- a/src/Deferred.cpp +++ b/src/Deferred.cpp @@ -109,6 +109,10 @@ void Deferred::SetupResources() SetupRenderTarget(NORMALROUGHNESS, texDesc, srvDesc, rtvDesc, uavDesc, DXGI_FORMAT_R10G10B10A2_UNORM, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE); // Masks SetupRenderTarget(MASKS, texDesc, srvDesc, rtvDesc, uavDesc, DXGI_FORMAT_R11G11B10_FLOAT, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE); + + // TAA Water Buffers + SetupRenderTarget(RE::RENDER_TARGETS::kWATER_1, texDesc, srvDesc, rtvDesc, uavDesc, DXGI_FORMAT_R11G11B10_FLOAT, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE); + SetupRenderTarget(RE::RENDER_TARGETS::kWATER_2, texDesc, srvDesc, rtvDesc, uavDesc, DXGI_FORMAT_R11G11B10_FLOAT, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE); } { From 83a1747aa9fea734308e9196ff7f509fcfe1f9f2 Mon Sep 17 00:00:00 2001 From: Jiaye Date: Tue, 17 Mar 2026 19:00:23 +0800 Subject: [PATCH 2/3] correct semantic --- src/Features/Upscaling.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Features/Upscaling.cpp b/src/Features/Upscaling.cpp index f189d8301d..375f99dd58 100644 --- a/src/Features/Upscaling.cpp +++ b/src/Features/Upscaling.cpp @@ -1039,10 +1039,8 @@ void Upscaling::ConfigureTAA() auto imageSpaceManager = RE::ImageSpaceManager::GetSingleton(); GET_INSTANCE_MEMBER(BSImagespaceShaderISTemporalAA, imageSpaceManager); - // CS TAA replaces vanilla TAA entirely, so disable water TAA (CS handles it). - // For FSR/DLSS, keep water TAA enabled since the upscaler needs the blend data. - bool* enableWaterTAA = reinterpret_cast(reinterpret_cast(BSImagespaceShaderISTemporalAA) + 0x38LL); - *enableWaterTAA = (upscaleMethod != UpscaleMethod::kTAA); + bool* disableWaterTAA = reinterpret_cast(reinterpret_cast(BSImagespaceShaderISTemporalAA) + 0x38LL); + *disableWaterTAA = (upscaleMethod == UpscaleMethod::kNONE); BSImagespaceShaderISTemporalAA->taaEnabled = true; } From 8c4ce132e7be4ff48f4c694e2afd227431164c16 Mon Sep 17 00:00:00 2001 From: jiayev Date: Wed, 18 Mar 2026 10:37:23 +0800 Subject: [PATCH 3/3] remove watertaa toggle we don't need anymore --- src/Features/Upscaling.cpp | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/Features/Upscaling.cpp b/src/Features/Upscaling.cpp index 375f99dd58..61774e99b6 100644 --- a/src/Features/Upscaling.cpp +++ b/src/Features/Upscaling.cpp @@ -1029,20 +1029,11 @@ void Upscaling::ConfigureTAA() { auto upscaleMethod = GetUpscaleMethod(); - // When no upscaling method is active, leave vanilla TAA state untouched. - // The original UpdateJitter (called after this) manages water TAA and jitter - // correctly for the non-upscaling case. Overriding here disables ISWaterBlend, - // removing the 95% temporal history blend that stabilizes water reflections. - if (upscaleMethod == UpscaleMethod::kNONE) - return; - auto imageSpaceManager = RE::ImageSpaceManager::GetSingleton(); GET_INSTANCE_MEMBER(BSImagespaceShaderISTemporalAA, imageSpaceManager); - bool* disableWaterTAA = reinterpret_cast(reinterpret_cast(BSImagespaceShaderISTemporalAA) + 0x38LL); - *disableWaterTAA = (upscaleMethod == UpscaleMethod::kNONE); - - BSImagespaceShaderISTemporalAA->taaEnabled = true; + // Force enable TAA if needed + BSImagespaceShaderISTemporalAA->taaEnabled = upscaleMethod != UpscaleMethod::kNONE; } void Upscaling::ConfigureUpscaling(RE::BSGraphics::State* a_viewport)