Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
b293838
fix(UI): Background Blur with Upscaling
Dlizzio Feb 3, 2026
b531feb
style: 🎨 apply pre-commit.ci formatting
pre-commit-ci[bot] Feb 3, 2026
e733d16
Merge branch 'dev' into background-blur-with-upscaling
Dlizzio Feb 4, 2026
97dde7c
respect rounded corners
Dlizzio Feb 4, 2026
de06aa6
style: 🎨 apply pre-commit.ci formatting
pre-commit-ci[bot] Feb 4, 2026
ba49883
added dither
Dlizzio Feb 4, 2026
fc0fce0
Merge branch 'background-blur-with-upscaling' of https://github.com/D…
Dlizzio Feb 4, 2026
45253b7
style: 🎨 apply pre-commit.ci formatting
pre-commit-ci[bot] Feb 4, 2026
b8279ac
fix dither
Dlizzio Feb 4, 2026
792bf03
Merge branch 'background-blur-with-upscaling' of https://github.com/D…
Dlizzio Feb 4, 2026
fd752a1
style: 🎨 apply pre-commit.ci formatting
pre-commit-ci[bot] Feb 4, 2026
c2ee3a2
fix dither again
Dlizzio Feb 4, 2026
903f327
respect corners of UI over HUD with upscaling
Dlizzio Feb 4, 2026
8fdd168
style: 🎨 apply pre-commit.ci formatting
pre-commit-ci[bot] Feb 4, 2026
bb4b8ca
remove redundancy and consolidate
Dlizzio Feb 4, 2026
a14454b
Merge branch 'dev' into background-blur-with-upscaling
Dlizzio Feb 5, 2026
01deb8a
Merge branch 'dev' into background-blur-with-upscaling
Dlizzio Feb 6, 2026
59868a4
performance and consolidation
Dlizzio Feb 6, 2026
52c00d2
remove fast path dither
Dlizzio Feb 6, 2026
9c83ad5
Merge branch 'dev' into background-blur-with-upscaling
Dlizzio Feb 7, 2026
4c5ff1d
Merge branch 'dev' into background-blur-with-upscaling
Dlizzio Feb 7, 2026
8e1cc05
Merge branch 'dev' into background-blur-with-upscaling
Dlizzio Feb 9, 2026
d84bf39
enable blur by default & fullscreen blur for weather editor
Dlizzio Feb 9, 2026
7120077
Merge branch 'dev' into background-blur-with-upscaling
Dlizzio Feb 9, 2026
e1f0398
style: 🎨 apply pre-commit.ci formatting
pre-commit-ci[bot] Feb 9, 2026
b97b9b4
remove weather editor specific changes
Dlizzio Feb 9, 2026
2122d1d
disable blur on loading screens without upscaling
Dlizzio Feb 9, 2026
6016e01
ignore framegen with load screen fix
Dlizzio Feb 9, 2026
a9a2c5a
magic numbers and constants
Dlizzio Feb 9, 2026
a9a44ea
lambda and helper functions
Dlizzio Feb 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package/SKSE/Plugins/CommunityShaders/Themes/Default.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"ShowFooter": true,
"CenterHeader": true,
"TooltipHoverDelay": 0.5,
"BackgroundBlurEnabled": false,
"BackgroundBlurEnabled": true,
"Palette": {
"Background": [0.03, 0.03, 0.03, 0.39216],
"Text": [1.0, 1.0, 1.0, 1.0],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"UseMonochromeIcons": true,
"CenterHeader": true,
"TooltipHoverDelay": 0.5,
"BackgroundBlurEnabled": false,
"BackgroundBlurEnabled": true,
"Palette": {
"Background": [0.25, 0.05, 0.05, 0.9],
"Text": [1.0, 0.85, 0.85, 1.0],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"ShowFooter": false,
"CenterHeader": true,
"TooltipHoverDelay": 0.5,
"BackgroundBlurEnabled": false,
"BackgroundBlurEnabled": true,
"Palette": {
"Background": [0.15, 0.12, 0.08, 0.9],
"Text": [0.9, 0.75, 0.5, 1.0],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"UseMonochromeIcons": false,
"CenterHeader": true,
"TooltipHoverDelay": 0.5,
"BackgroundBlurEnabled": false,
"BackgroundBlurEnabled": true,
"Palette": {
"Background": [0.0, 0.0, 0.0, 0.95],
"Text": [1.0, 1.0, 1.0, 1.0],
Expand Down
2 changes: 1 addition & 1 deletion package/SKSE/Plugins/CommunityShaders/Themes/Light.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"ShowFooter": false,
"CenterHeader": true,
"TooltipHoverDelay": 0.5,
"BackgroundBlurEnabled": false,
"BackgroundBlurEnabled": true,
"Palette": {
"Background": [0.98, 0.98, 0.98, 0.9],
"Text": [0.08, 0.08, 0.08, 1.0],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"UseMonochromeIcons": true,
"CenterHeader": true,
"TooltipHoverDelay": 0.5,
"BackgroundBlurEnabled": false,
"BackgroundBlurEnabled": true,
"Palette": {
"Background": [0.05, 0.15, 0.25, 0.9],
"Text": [0.9, 0.95, 1.0, 1.0],
Expand Down
142 changes: 142 additions & 0 deletions package/Shaders/Menu/BackgroundBlurComposite.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
// Composite Blur Pass Shader with Rounded Rectangle Mask
// Part of the BackgroundBlur system - applies blurred texture with rounded corners

cbuffer WindowBuffer : register(b1)
{
float4 WindowRect; // x = minX, y = minY, z = maxX, w = maxY (in pixels)
float4 WindowParams; // x = cornerRadius, y = screenWidth, z = screenHeight, w = unused
};

SamplerState LinearSampler : register(s0);
Texture2D InputTexture : register(t0);

static const float TWO_PI = 6.28318530718f;
static const int NUM_JITTER_SAMPLES = 4;
static const float DOWNSAMPLE_FACTOR = 8.0f;
static const float CLIP_EPSILON = 0.001f;

struct VS_OUTPUT
{
float4 Position : SV_POSITION;
float2 TexCoord : TEXCOORD0;
};

VS_OUTPUT VS_Main(uint vertexID : SV_VertexID)
{
VS_OUTPUT output;
output.TexCoord = float2((vertexID << 1) & 2, vertexID & 2);
output.Position = float4(output.TexCoord * 2.0f - 1.0f, 0.0f, 1.0f);
output.Position.y = -output.Position.y;
return output;
}

// High quality 2D hash - returns two independent random values in [0,1]
// Uses different prime multipliers to avoid correlation between x and y
float2 Hash22(float2 p)
{
// Two independent hashes using different constants
float3 p3 = frac(float3(p.xyx) * float3(0.1031f, 0.1030f, 0.0973f));
p3 += dot(p3, p3.yzx + 33.33f);
return frac((p3.xx + p3.yz) * p3.zy);
}

// Soft sampling with blurred dithering - takes 4 samples with jittered offsets
// and averages them to smooth out the noise while still breaking up blocky pixels
float4 SampleWithSoftening(float2 uv, float2 pixelPos, float2 texelSize)
{
// Get base random offset for this pixel
float2 noise = Hash22(pixelPos);

// Rotated grid offsets (45 degree rotation for better coverage)
// This creates a smooth disc-like sampling pattern
static const float2 offsets[NUM_JITTER_SAMPLES] = {
float2(-0.25f, -0.25f),
float2( 0.25f, -0.25f),
float2(-0.25f, 0.25f),
float2( 0.25f, 0.25f)
};

// Random rotation angle based on pixel position
float angle = noise.x * TWO_PI;
float s, c;
sincos(angle, s, c);
float2x2 rotation = float2x2(c, -s, s, c);

// Sample 4 points with rotated jittered offsets and average
float4 result = 0;
[unroll]
for (int i = 0; i < NUM_JITTER_SAMPLES; i++)
{
float2 jitter = mul(rotation, offsets[i]) * texelSize;
result += InputTexture.Sample(LinearSampler, uv + jitter);
}

return result / (float)NUM_JITTER_SAMPLES;
}

// Compute signed distance to a rounded rectangle
// Returns negative inside, positive outside
float RoundedRectSDF(float2 pixelPos, float2 rectMin, float2 rectMax, float radius)
{
// Center of the rectangle
float2 rectCenter = (rectMin + rectMax) * 0.5f;
float2 rectHalfSize = (rectMax - rectMin) * 0.5f;

// Clamp radius to not exceed half the smallest dimension
radius = min(radius, min(rectHalfSize.x, rectHalfSize.y));

// Distance from center
float2 p = abs(pixelPos - rectCenter) - rectHalfSize + radius;

// SDF for rounded rectangle
return length(max(p, 0.0f)) + min(max(p.x, p.y), 0.0f) - radius;
}

float4 PS_Main(VS_OUTPUT input) : SV_TARGET
{
// Convert UV to pixel coordinates
float2 pixelPos = input.TexCoord * float2(WindowParams.y, WindowParams.z);

// Get window bounds and corner radius
float2 rectMin = WindowRect.xy;
float2 rectMax = WindowRect.zw;
float cornerRadius = WindowParams.x;

// Calculate signed distance to rounded rectangle
float sdf = RoundedRectSDF(pixelPos, rectMin, rectMax, cornerRadius);

// Create smooth edge (anti-aliased)
// Negative = inside, positive outside
// Use 1.0 pixel transition for smooth edge
float alpha = saturate(-sdf);

// Early out if completely outside
if (alpha <= 0.0f)
{
discard;
}

float2 blurTexelSize = DOWNSAMPLE_FACTOR / float2(WindowParams.y, WindowParams.z);

// Sample with soft dithering to hide blocky pixels from the downsampled blur
float4 blurColor = SampleWithSoftening(input.TexCoord, pixelPos, blurTexelSize);

// Apply rounded corner mask to alpha
// The blur strength is applied via blend state, so just use the rounded mask here
blurColor.a = alpha;

return blurColor;
}

// Clear shader entry point - outputs transparent black inside rounded rect only
// Used to clear UI buffer (HUD) in the exact same shape as the blur
float4 PS_Clear(VS_OUTPUT input) : SV_TARGET
{
float2 pixelPos = input.TexCoord * float2(WindowParams.y, WindowParams.z);
float sdf = RoundedRectSDF(pixelPos, WindowRect.xy, WindowRect.zw, WindowParams.x);

// Discard pixels outside rounded rect to preserve HUD in corners
clip(-sdf - CLIP_EPSILON);

return float4(0.0f, 0.0f, 0.0f, 0.0f);
}
8 changes: 8 additions & 0 deletions src/Features/Upscaling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1541,6 +1541,14 @@ IDXGISwapChain* Upscaling::GetProxySwapChain()
return dx12SwapChain.GetSwapChainProxy();
}

Upscaling::BlurResources Upscaling::GetBlurResources() const
{
if (d3d12SwapChainActive) {
return dx12SwapChain.GetBlurResources();
}
return {};
}

void Upscaling::Upscale()
{
auto upscaleMethod = GetUpscaleMethod();
Expand Down
5 changes: 5 additions & 0 deletions src/Features/Upscaling.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,11 @@ struct Upscaling : Feature
void CreateProxyInterop();
IDXGISwapChain* GetProxySwapChain();

using BlurResources = DX12SwapChain::BlurResources;

// Get all D3D11 resources needed for background blur when D3D12 swap chain is active
BlurResources GetBlurResources() const;

private:
struct Main_UpdateJitter
{
Expand Down
15 changes: 15 additions & 0 deletions src/Features/Upscaling/DX12SwapChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,21 @@ void DX12SwapChain::SetUIBuffer()
}
}

DX12SwapChain::BlurResources DX12SwapChain::GetBlurResources() const
{
BlurResources res;
if (swapChainBufferWrapped) {
res.backbufferTex = swapChainBufferWrapped->resource11;
res.backbufferRTV = swapChainBufferWrapped->rtv;
res.backbufferSRV = swapChainBufferWrapped->srv;
}
if (uiBufferWrapped) {
res.uiBufferSRV = uiBufferWrapped->srv;
res.uiBufferRTV = uiBufferWrapped->rtv;
}
return res;
}

void DX12SwapChain::CreateSharedResources()
{
auto renderer = globals::game::renderer;
Expand Down
13 changes: 13 additions & 0 deletions src/Features/Upscaling/DX12SwapChain.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,19 @@ class DX12SwapChain

void SetUIBuffer();

// Resources needed by BackgroundBlur when D3D12 swap chain is active
struct BlurResources
{
ID3D11Texture2D* backbufferTex = nullptr;
ID3D11RenderTargetView* backbufferRTV = nullptr;
ID3D11ShaderResourceView* backbufferSRV = nullptr;
ID3D11ShaderResourceView* uiBufferSRV = nullptr;
ID3D11RenderTargetView* uiBufferRTV = nullptr;
};

// Get all resources needed for background blur in one call
BlurResources GetBlurResources() const;

// D3D12 interop resource management
void CreateSharedResources();
};
16 changes: 8 additions & 8 deletions src/Menu.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,14 +248,14 @@ class Menu
return roles;
}();

bool UseSimplePalette = false; // DEPRECATED: No longer affects behavior. UI now shows both Simple and Advanced controls.
bool ShowActionIcons = true; // whether to show action buttons as icons
bool UseMonochromeIcons = false; // whether to use monochrome (white) action icons with text color tinting
bool UseMonochromeLogo = false; // whether to use monochrome CS logo
bool ShowFooter = true; // whether to show the footer with game version/GPU info
bool CenterHeader = false; // whether to center the header title and logo
float TooltipHoverDelay = 0.5f; // tooltip hover delay in seconds
bool BackgroundBlurEnabled = false; // enable background blur effect
bool UseSimplePalette = false; // DEPRECATED: No longer affects behavior. UI now shows both Simple and Advanced controls.
bool ShowActionIcons = true; // whether to show action buttons as icons
bool UseMonochromeIcons = false; // whether to use monochrome (white) action icons with text color tinting
bool UseMonochromeLogo = false; // whether to use monochrome CS logo
bool ShowFooter = true; // whether to show the footer with game version/GPU info
bool CenterHeader = false; // whether to center the header title and logo
float TooltipHoverDelay = 0.5f; // tooltip hover delay in seconds
bool BackgroundBlurEnabled = true; // enable background blur effect
// Scrollbar opacity settings
struct ScrollbarOpacitySettings
{
Expand Down
Loading