mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-09-07 12:48:03 +00:00
97 lines
2.9 KiB
HLSL
97 lines
2.9 KiB
HLSL
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
// SPDX-FileCopyrightText: Copyright 2015 Niklas Haas
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
texture BackBufferTex : COLOR;
|
|
sampler BackBuffer { Texture = BackBufferTex; };
|
|
|
|
uniform float Threshold <
|
|
ui_type = "slider";
|
|
ui_label = "Threshold";
|
|
ui_tooltip = "How flat a neighbourhood must be before it gets smoothed. Raise it to catch wider bands, lower it to keep more detail.";
|
|
ui_min = 0.002; ui_max = 0.05; ui_step = 0.001;
|
|
> = 0.012;
|
|
|
|
uniform float Radius <
|
|
ui_type = "slider";
|
|
ui_label = "Radius";
|
|
ui_tooltip = "How far the sampling reaches, in pixels. Wider gradients need a larger radius.";
|
|
ui_min = 1.0; ui_max = 32.0; ui_step = 1.0;
|
|
> = 8.0;
|
|
|
|
uniform float Grain <
|
|
ui_type = "slider";
|
|
ui_label = "Dither";
|
|
ui_tooltip = "Noise added to break up whatever banding survives the smoothing.";
|
|
ui_min = 0.0; ui_max = 0.02; ui_step = 0.001;
|
|
> = 0.004;
|
|
|
|
void VS_PostProcess(in uint id : SV_VertexID, out float4 pos : SV_Position, out float2 uv : TEXCOORD)
|
|
{
|
|
uv = float2(0.0, 0.0);
|
|
if (id == 2)
|
|
{
|
|
uv.x = 2.0;
|
|
}
|
|
if (id == 1)
|
|
{
|
|
uv.y = 2.0;
|
|
}
|
|
pos = float4(uv * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
|
|
}
|
|
|
|
float Hash(float2 p)
|
|
{
|
|
float3 scattered = frac(float3(p.x, p.y, p.x) * 0.1031);
|
|
scattered += dot(scattered, scattered.yzx + 33.33);
|
|
return frac((scattered.x + scattered.y) * scattered.z);
|
|
}
|
|
|
|
float4 PS_Deband(float4 pos : SV_Position, float2 uv : TEXCOORD) : SV_Target
|
|
{
|
|
float2 texel = float2(BUFFER_RCP_WIDTH, BUFFER_RCP_HEIGHT);
|
|
|
|
float3 centre = tex2D(BackBuffer, uv).rgb;
|
|
float base = Hash(pos.xy) * 6.2831853;
|
|
|
|
float3 total = float3(0.0, 0.0, 0.0);
|
|
float3 deviation = float3(0.0, 0.0, 0.0);
|
|
|
|
for (int ring = 1; ring <= 2; ++ring)
|
|
{
|
|
float angle = base + float(ring) * 2.3999632;
|
|
float reach = Radius * float(ring) * 0.5;
|
|
float2 along = float2(cos(angle), sin(angle)) * reach;
|
|
float2 across = float2(-along.y, along.x);
|
|
|
|
float3 s0 = tex2D(BackBuffer, uv + along * texel).rgb;
|
|
float3 s1 = tex2D(BackBuffer, uv - along * texel).rgb;
|
|
float3 s2 = tex2D(BackBuffer, uv + across * texel).rgb;
|
|
float3 s3 = tex2D(BackBuffer, uv - across * texel).rgb;
|
|
|
|
total += s0 + s1 + s2 + s3;
|
|
deviation = max(deviation, max(max(abs(s0 - centre), abs(s1 - centre)),
|
|
max(abs(s2 - centre), abs(s3 - centre))));
|
|
}
|
|
|
|
float3 average = total * 0.125;
|
|
float3 flatness = float3(1.0, 1.0, 1.0) -
|
|
smoothstep(Threshold * 0.5, Threshold, deviation);
|
|
float3 result = lerp(centre, average, flatness);
|
|
|
|
float dither = (Hash(pos.xy + float2(71.3, 41.7)) - 0.5) * Grain;
|
|
|
|
return float4(saturate(result + dither), 1.0);
|
|
}
|
|
|
|
technique Deband
|
|
{
|
|
pass
|
|
{
|
|
VertexShader = VS_PostProcess;
|
|
PixelShader = PS_Deband;
|
|
}
|
|
}
|