forked from crosire/reshade-shaders
-
Notifications
You must be signed in to change notification settings - Fork 0
/
LumaSharpen.fx
185 lines (149 loc) · 7.9 KB
/
LumaSharpen.fx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
/**
* LumaSharpen version 1.5.0
* by Christian Cann Schuldt Jensen ~ CeeJay.dk
*
* It blurs the original pixel with the surrounding pixels and then subtracts this blur to sharpen the image.
* It does this in luma to avoid color artifacts and allows limiting the maximum sharpning to avoid or lessen halo artifacts.
* This is similar to using Unsharp Mask in Photoshop.
*/
uniform float sharp_strength <
ui_type = "drag";
ui_min = 0.1; ui_max = 3.0;
ui_tooltip = "Strength of the sharpening";
> = 0.65;
uniform float sharp_clamp <
ui_type = "drag";
ui_min = 0.0; ui_max = 1.0; ui_step = 0.005;
ui_tooltip = "Limits maximum amount of sharpening a pixel receives";
> = 0.035;
uniform int pattern <
ui_type = "combo";
ui_items = "Fast\0Normal\0Wider\0Pyramid shaped\0";
ui_tooltip = "Choose a sample pattern";
> = 1;
uniform float offset_bias <
ui_type = "drag";
ui_min = 0.0; ui_max = 6.0;
ui_tooltip = "Offset bias adjusts the radius of the sampling pattern. I designed the pattern for offset_bias 1.0, but feel free to experiment.";
> = 1.0;
uniform bool show_sharpen <
ui_tooltip = "Visualize the strength of the sharpen (multiplied by 4 to see it better)";
> = false;
#include "ReShade.fxh"
/*-----------------------------------------------------------.
/ Developer settings /
'-----------------------------------------------------------*/
#define CoefLuma float3(0.2126, 0.7152, 0.0722) // BT.709 & sRBG luma coefficient (Monitors and HD Television)
//#define CoefLuma float3(0.299, 0.587, 0.114) // BT.601 luma coefficient (SD Television)
//#define CoefLuma float3(1.0/3.0, 1.0/3.0, 1.0/3.0) // Equal weight coefficient
/*-----------------------------------------------------------.
/ Main code /
'-----------------------------------------------------------*/
float3 LumaSharpenPass(float4 position : SV_Position, float2 tex : TEXCOORD0) : SV_Target
{
// -- Get the original pixel --
float3 ori = tex2D(ReShade::BackBuffer, tex).rgb; // ori = original pixel
// -- Combining the strength and luma multipliers --
float3 sharp_strength_luma = (CoefLuma * sharp_strength); //I'll be combining even more multipliers with it later on
/*-----------------------------------------------------------.
/ Sampling patterns /
'-----------------------------------------------------------*/
float3 blur_ori;
// [ NW, , NE ] Each texture lookup (except ori)
// [ ,ori, ] samples 4 pixels
// [ SW, , SE ]
// -- Pattern 1 -- A (fast) 7 tap gaussian using only 2+1 texture fetches.
if (pattern == 0)
{
// -- Gaussian filter --
// [ 1/9, 2/9, ] [ 1 , 2 , ]
// [ 2/9, 8/9, 2/9] = [ 2 , 8 , 2 ]
// [ , 2/9, 1/9] [ , 2 , 1 ]
blur_ori = tex2D(ReShade::BackBuffer, tex + (ReShade::PixelSize / 3.0) * offset_bias).rgb; // North West
blur_ori += tex2D(ReShade::BackBuffer, tex + (-ReShade::PixelSize / 3.0) * offset_bias).rgb; // South East
//blur_ori += tex2D(ReShade::BackBuffer, tex + (ReShade::PixelSize / 3.0) * offset_bias); // North East
//blur_ori += tex2D(ReShade::BackBuffer, tex + (-ReShade::PixelSize / 3.0) * offset_bias); // South West
blur_ori /= 2; //Divide by the number of texture fetches
sharp_strength_luma *= 1.5; // Adjust strength to aproximate the strength of pattern 2
}
// -- Pattern 2 -- A 9 tap gaussian using 4+1 texture fetches.
if (pattern == 1)
{
// -- Gaussian filter --
// [ .25, .50, .25] [ 1 , 2 , 1 ]
// [ .50, 1, .50] = [ 2 , 4 , 2 ]
// [ .25, .50, .25] [ 1 , 2 , 1 ]
blur_ori = tex2D(ReShade::BackBuffer, tex + float2(ReShade::PixelSize.x, -ReShade::PixelSize.y) * 0.5 * offset_bias).rgb; // South East
blur_ori += tex2D(ReShade::BackBuffer, tex - ReShade::PixelSize * 0.5 * offset_bias).rgb; // South West
blur_ori += tex2D(ReShade::BackBuffer, tex + ReShade::PixelSize * 0.5 * offset_bias).rgb; // North East
blur_ori += tex2D(ReShade::BackBuffer, tex - float2(ReShade::PixelSize.x, -ReShade::PixelSize.y) * 0.5 * offset_bias).rgb; // North West
blur_ori *= 0.25; // ( /= 4) Divide by the number of texture fetches
}
// -- Pattern 3 -- An experimental 17 tap gaussian using 4+1 texture fetches.
if (pattern == 2)
{
// -- Gaussian filter --
// [ , 4 , 6 , , ]
// [ ,16 ,24 ,16 , 4 ]
// [ 6 ,24 , ,24 , 6 ]
// [ 4 ,16 ,24 ,16 , ]
// [ , , 6 , 4 , ]
blur_ori = tex2D(ReShade::BackBuffer, tex + ReShade::PixelSize * float2(0.4, -1.2) * offset_bias).rgb; // South South East
blur_ori += tex2D(ReShade::BackBuffer, tex - ReShade::PixelSize * float2(1.2, 0.4) * offset_bias).rgb; // West South West
blur_ori += tex2D(ReShade::BackBuffer, tex + ReShade::PixelSize * float2(1.2, 0.4) * offset_bias).rgb; // East North East
blur_ori += tex2D(ReShade::BackBuffer, tex - ReShade::PixelSize * float2(0.4, -1.2) * offset_bias).rgb; // North North West
blur_ori *= 0.25; // ( /= 4) Divide by the number of texture fetches
sharp_strength_luma *= 0.51;
}
// -- Pattern 4 -- A 9 tap high pass (pyramid filter) using 4+1 texture fetches.
if (pattern == 3)
{
// -- Gaussian filter --
// [ .50, .50, .50] [ 1 , 1 , 1 ]
// [ .50, , .50] = [ 1 , , 1 ]
// [ .50, .50, .50] [ 1 , 1 , 1 ]
blur_ori = tex2D(ReShade::BackBuffer, tex + float2(0.5 * ReShade::PixelSize.x, -ReShade::PixelSize.y * offset_bias)).rgb; // South South East
blur_ori += tex2D(ReShade::BackBuffer, tex + float2(offset_bias * -ReShade::PixelSize.x, 0.5 * -ReShade::PixelSize.y)).rgb; // West South West
blur_ori += tex2D(ReShade::BackBuffer, tex + float2(offset_bias * ReShade::PixelSize.x, 0.5 * ReShade::PixelSize.y)).rgb; // East North East
blur_ori += tex2D(ReShade::BackBuffer, tex + float2(0.5 * -ReShade::PixelSize.x, ReShade::PixelSize.y * offset_bias)).rgb; // North North West
//blur_ori += (2 * ori); // Probably not needed. Only serves to lessen the effect.
blur_ori /= 4.0; //Divide by the number of texture fetches
sharp_strength_luma *= 0.666; // Adjust strength to aproximate the strength of pattern 2
}
/*-----------------------------------------------------------.
/ Sharpen /
'-----------------------------------------------------------*/
// -- Calculate the sharpening --
float3 sharp = ori - blur_ori; //Subtracting the blurred image from the original image
#if 0 //older CeeJay 1.4 code (included here because the new code while faster can be difficult to understand)
// -- Adjust strength of the sharpening --
float sharp_luma = dot(sharp, sharp_strength_luma); //Calculate the luma and adjust the strength
// -- Clamping the maximum amount of sharpening to prevent halo artifacts --
sharp_luma = clamp(sharp_luma, -sharp_clamp, sharp_clamp); //TODO Try a curve function instead of a clamp
#else //new code
// -- Adjust strength of the sharpening and clamp it--
float4 sharp_strength_luma_clamp = float4(sharp_strength_luma * (0.5 / sharp_clamp),0.5); //Roll part of the clamp into the dot
//sharp_luma = saturate((0.5 / sharp_clamp) * sharp_luma + 0.5); //scale up and clamp
float sharp_luma = saturate(dot(float4(sharp,1.0), sharp_strength_luma_clamp)); //Calculate the luma, adjust the strength, scale up and clamp
sharp_luma = (sharp_clamp * 2.0) * sharp_luma - sharp_clamp; //scale down
#endif
// -- Combining the values to get the final sharpened pixel --
float3 outputcolor = ori + sharp_luma; // Add the sharpening to the the original.
/*-----------------------------------------------------------.
/ Returning the output /
'-----------------------------------------------------------*/
if (show_sharpen)
{
//outputcolor = abs(sharp * 4.0);
outputcolor = saturate(0.5 + (sharp_luma * 4.0)).rrr;
}
return saturate(outputcolor);
}
technique LumaSharpen
{
pass
{
VertexShader = PostProcessVS;
PixelShader = LumaSharpenPass;
}
}