179 lines
4.5 KiB
Plaintext
179 lines
4.5 KiB
Plaintext
/*
|
|
FSR - [RCAS] ROBUST CONTRAST ADAPTIVE SHARPENING
|
|
Ported from https://www.shadertoy.com/view/stXSWB, MIT license
|
|
*/
|
|
|
|
#pragma parameter FSR_SHARPENING "FSR RCAS Sharpening Amount (Lower = Sharper)" 0.6 0.0 2.0 0.1
|
|
|
|
#if defined(VERTEX)
|
|
|
|
#if __VERSION__ >= 130
|
|
#define COMPAT_VARYING out
|
|
#define COMPAT_ATTRIBUTE in
|
|
#define COMPAT_TEXTURE texture
|
|
#else
|
|
#define COMPAT_VARYING varying
|
|
#define COMPAT_ATTRIBUTE attribute
|
|
#define COMPAT_TEXTURE texture2D
|
|
#endif
|
|
|
|
#ifdef GL_ES
|
|
#define COMPAT_PRECISION mediump
|
|
#else
|
|
#define COMPAT_PRECISION
|
|
#endif
|
|
|
|
COMPAT_ATTRIBUTE vec4 VertexCoord;
|
|
COMPAT_ATTRIBUTE vec4 COLOR;
|
|
COMPAT_ATTRIBUTE vec4 TexCoord;
|
|
COMPAT_VARYING vec4 COL0;
|
|
COMPAT_VARYING vec4 TEX0;
|
|
|
|
uniform mat4 MVPMatrix;
|
|
uniform COMPAT_PRECISION int FrameDirection;
|
|
uniform COMPAT_PRECISION int FrameCount;
|
|
uniform COMPAT_PRECISION vec2 OutputSize;
|
|
uniform COMPAT_PRECISION vec2 TextureSize;
|
|
uniform COMPAT_PRECISION vec2 InputSize;
|
|
|
|
void main()
|
|
{
|
|
gl_Position = MVPMatrix * VertexCoord;
|
|
COL0 = COLOR;
|
|
TEX0.xy = TexCoord.xy;
|
|
}
|
|
|
|
#elif defined(FRAGMENT)
|
|
|
|
#if __VERSION__ >= 130
|
|
#define COMPAT_VARYING in
|
|
#define COMPAT_TEXTURE texture
|
|
out vec4 FragColor;
|
|
#else
|
|
#define COMPAT_VARYING varying
|
|
#define FragColor gl_FragColor
|
|
#define COMPAT_TEXTURE texture2D
|
|
#endif
|
|
|
|
#ifdef GL_ES
|
|
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
|
precision highp float;
|
|
#else
|
|
precision mediump float;
|
|
#endif
|
|
#define COMPAT_PRECISION mediump
|
|
#else
|
|
#define COMPAT_PRECISION
|
|
#endif
|
|
|
|
uniform COMPAT_PRECISION int FrameDirection;
|
|
uniform COMPAT_PRECISION int FrameCount;
|
|
uniform COMPAT_PRECISION vec2 OutputSize;
|
|
uniform COMPAT_PRECISION vec2 TextureSize;
|
|
uniform COMPAT_PRECISION vec2 InputSize;
|
|
uniform sampler2D Texture;
|
|
COMPAT_VARYING vec4 TEX0;
|
|
|
|
// compatibility #defines
|
|
#define Source Texture
|
|
#define vTexCoord TEX0.xy
|
|
|
|
#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
|
|
#define outsize vec4(OutputSize, 1.0 / OutputSize)
|
|
|
|
#ifdef PARAMETER_UNIFORM
|
|
uniform COMPAT_PRECISION float FSR_SHARPENING;
|
|
#else
|
|
#define FSR_SHARPENING 0.6
|
|
#endif
|
|
|
|
#define FSR_RCAS_LIMIT (0.25-(1.0/16.0))
|
|
//#define FSR_RCAS_DENOISE
|
|
|
|
// Input callback prototypes that need to be implemented by calling shader
|
|
vec4 FsrRcasLoadF(vec2 p);
|
|
//------------------------------------------------------------------------------------------------------------------------------
|
|
void FsrRcasCon(
|
|
out float con,
|
|
// The scale is {0.0 := maximum, to N>0, where N is the number of stops (halving) of the reduction of sharpness}.
|
|
float sharpness
|
|
){
|
|
// Transform from stops to linear value.
|
|
con = exp2(-sharpness);
|
|
}
|
|
|
|
vec3 FsrRcasF(
|
|
vec2 ip, // Integer pixel position in output.
|
|
float con
|
|
)
|
|
{
|
|
// Constant generated by RcasSetup().
|
|
// Algorithm uses minimal 3x3 pixel neighborhood.
|
|
// b
|
|
// d e f
|
|
// h
|
|
vec2 sp = vec2(ip);
|
|
vec3 b = FsrRcasLoadF(sp + vec2( 0,-1)).rgb;
|
|
vec3 d = FsrRcasLoadF(sp + vec2(-1, 0)).rgb;
|
|
vec3 e = FsrRcasLoadF(sp).rgb;
|
|
vec3 f = FsrRcasLoadF(sp+vec2( 1, 0)).rgb;
|
|
vec3 h = FsrRcasLoadF(sp+vec2( 0, 1)).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.
|
|
#ifdef FSR_RCAS_DENOISE
|
|
lobe *= nz;
|
|
#endif
|
|
// Resolve, which needs the medium precision rcp approximation to avoid visible tonality changes.
|
|
return (lobe * (b + d + h + f) + e) / (4. * lobe + 1.);
|
|
}
|
|
|
|
|
|
vec4 FsrRcasLoadF(vec2 p) {
|
|
return COMPAT_TEXTURE(Source,p/OutputSize.xy);
|
|
}
|
|
|
|
void main()
|
|
{
|
|
vec2 fragCoord = vTexCoord.xy * OutputSize.xy;
|
|
|
|
// Set up constants
|
|
float con;
|
|
FsrRcasCon(con, FSR_SHARPENING);
|
|
|
|
// Perform RCAS pass
|
|
vec3 col = FsrRcasF(fragCoord, con);
|
|
|
|
FragColor = vec4(col,1);
|
|
}
|
|
|
|
#endif
|