-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsharpen.gdshader
94 lines (88 loc) · 2.67 KB
/
sharpen.gdshader
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
/*
* SOURCE: https://www.shadertoy.com/view/stXSWB
*
* FidelityFX Super Resolution scales up a low resolution
* image, while adding fine detail.
*
* It works in two passes. This is ONLY the second, sharpening pass
*
* MIT Open License
*
* https://gpuopen.com/fsr
*
* For sharpening with a full resolution render buffer,
* FidelityFX CAS is a better option.
* https://www.shadertoy.com/view/ftsXzM
*
* For readability and compatibility, these optimisations have been removed:
* * Fast approximate inverse and inversesqrt
* * textureGather fetches (not WebGL compatible)
* * Multiplying by reciprocal instead of division
*
* Apologies to AMD for the numerous slowdowns and errors I have introduced.
*
*/
shader_type canvas_item;
/***** RCAS *****/
const float FSR_RCAS_LIMIT = (0.25-(1.0/16.0));
const bool FSR_RCAS_DENOISE = false;
uniform bool enabled = true;
void fragment()
{
// Set up constants
float con;
float sharpness = 2.0;
con = exp2(-sharpness);
// Perform RCAS pass
// Constant generated by RcasSetup().
// Algorithm uses minimal 3x3 pixel neighborhood.
// b
// d e f
// h
if(enabled == true){
vec2 off_mult = TEXTURE_PIXEL_SIZE * 1.0;
vec2 sp = UV;//vec2(ip);
vec3 b = texture(TEXTURE, sp + vec2( 0,-1)*off_mult).rgb;
vec3 d = texture(TEXTURE, + vec2(-1, 0)*off_mult).rgb;
vec3 e = texture(TEXTURE, sp).rgb;
vec3 f = texture(TEXTURE, sp+vec2( 1, 0)*off_mult).rgb;
vec3 h = texture(TEXTURE, sp+vec2( 0, 1)*off_mult).rgb;
// Luma times 2.
float bL = b.g + .5 * (b.b + b.r);
float dL = d.g + .5 * (d.b + d.r);
float eL = e.g + .5 * (e.b + e.r);
float fL = f.g + .5 * (f.b + f.r);
float hL = h.g + .5 * (h.b + h.r);
// Noise detection.
float nz = .25 * (bL + dL + fL + hL) - eL;
nz=clamp(
abs(nz)
/(
max(max(bL,dL),max(eL,max(fL,hL)))
-min(min(bL,dL),min(eL,min(fL,hL)))
),
0., 1.
);
nz=1.-.5*nz;
// Min and max of ring.
vec3 mn4 = min(b, min(f, h));
vec3 mx4 = max(b, max(f, h));
// Immediate constants for peak range.
vec2 peakC = vec2(1., -4.);
// Limiters, these need to be high precision RCPs.
vec3 hitMin = mn4 / (4. * mx4);
vec3 hitMax = (peakC.x - mx4) / (4.* mn4 + peakC.y);
vec3 lobeRGB = max(-hitMin, hitMax);
float lobe = max(
-FSR_RCAS_LIMIT,
min(max(lobeRGB.r, max(lobeRGB.g, lobeRGB.b)), 0.)
)*con;
// Apply noise removal.
if (FSR_RCAS_DENOISE) {
lobe *= nz;
}
// Resolve, which needs the medium precision rcp approximation to avoid visible tonality changes.
vec3 col = (lobe * (b + d + h + f) + e) / (4. * lobe + 1.);
COLOR.rgb = col;
}
}