231 lines
9.2 KiB
GLSL
231 lines
9.2 KiB
GLSL
#version 130
|
|
|
|
in vec4 posPos;
|
|
|
|
uniform sampler2D tex0; // 0
|
|
//uniform float vx_offset;
|
|
uniform vec2 dt;
|
|
uniform float FXAA_SPAN_MAX = 8.;
|
|
uniform float FXAA_REDUCE_MUL = 1. / 8.;
|
|
|
|
#define FxaaInt2 ivec2
|
|
//#define vec2 vec2
|
|
|
|
vec3 FxaaPixelShader(vec4 posPos, // Output of FxaaVertexShader interpolated across screen.
|
|
sampler2D tex, // Input texture.
|
|
vec2 rcpFrame) { // Constant {1.0/frameWidth, 1.0/frameHeight}.
|
|
/*---------------------------------------------------------*/
|
|
// #define FXAA_REDUCE_MIN (1. / 128.)
|
|
#define FXAA_REDUCE_MIN (1. / 128.)
|
|
//#define FXAA_REDUCE_MUL (1.0/8.0)
|
|
//#define FXAA_SPAN_MAX 8.0
|
|
/*---------------------------------------------------------*/
|
|
vec3 rgbNW = texture2D(tex, posPos.zw).xyz;
|
|
vec3 rgbNE = textureOffset(tex, posPos.zw, ivec2(1, 0)).xyz;
|
|
vec3 rgbSW = textureOffset(tex, posPos.zw, ivec2(0, 1)).xyz;
|
|
vec3 rgbSE = textureOffset(tex, posPos.zw, ivec2(1, 1)).xyz;
|
|
vec3 rgbM = texture2D(tex, posPos.xy).xyz;
|
|
/*---------------------------------------------------------*/
|
|
vec3 luma = vec3(0.299, 0.587, 0.114);
|
|
float lumaNW = dot(rgbNW, luma);
|
|
float lumaNE = dot(rgbNE, luma);
|
|
float lumaSW = dot(rgbSW, luma);
|
|
float lumaSE = dot(rgbSE, luma);
|
|
float lumaM = dot(rgbM, luma);
|
|
/*---------------------------------------------------------*/
|
|
float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
|
|
float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
|
|
/*---------------------------------------------------------*/
|
|
vec2 dir;
|
|
dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
|
|
dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));
|
|
/*---------------------------------------------------------*/
|
|
float dirReduce = max(
|
|
(lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL),
|
|
FXAA_REDUCE_MIN);
|
|
float rcpDirMin = 1. / (min(abs(dir.x), abs(dir.y)) + dirReduce);
|
|
dir = min(vec2( FXAA_SPAN_MAX, FXAA_SPAN_MAX),
|
|
max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),
|
|
dir * rcpDirMin)) * rcpFrame.xy;
|
|
/*--------------------------------------------------------*/
|
|
vec3 rgbA = (1. / 2.) * (
|
|
texture2D(tex, posPos.xy + dir * (1. / 3. - 0.5)).xyz +
|
|
texture2D(tex, posPos.xy + dir * (2. / 3. - 0.5)).xyz);
|
|
vec3 rgbB = rgbA * (1. / 2.) + (1. / 4.) * (
|
|
texture2D(tex, posPos.xy + dir * (0. / 3. - 0.5)).xyz +
|
|
texture2D(tex, posPos.xy + dir * (3. / 3. - 0.5)).xyz);
|
|
float lumaB = dot(rgbB, luma);
|
|
if ((lumaB < lumaMin) || (lumaB > lumaMax)) return rgbA;
|
|
return rgbB;
|
|
}
|
|
|
|
|
|
vec3 Fxaa3PixelShader (
|
|
// {xy} = center of pixel
|
|
vec4 pos,
|
|
// {xyzw} = not used on FXAA3 Quality
|
|
//vec4 posPos,
|
|
// {rgb_} = color in linear or perceptual color space
|
|
// {__a} = luma in perceptual color space (not linear)
|
|
sampler2D tex,
|
|
// This must be from a constant/uniform.
|
|
// {x_} = 1.0/screenWidthInPixels
|
|
// {_y} = 1.0/screenHeightInPixels
|
|
vec2 rcpFrame
|
|
// {xyzw} = not used on FXAA3 Quality
|
|
//vec4 rcpFrameOpt
|
|
) {
|
|
/*--------------------------------------------------------------------------*/
|
|
//#if (FXAA_GATHER4_ALPHA == 1)
|
|
/*vec4 luma4A = FxaaTexOffAlpha4(tex, pos.xy, FxaaInt2(-1, -1), rcpFrame.xy);
|
|
#if (FXAA_DISCARD == 0)
|
|
vec4 rgbyM = texture2D(tex, pos.xy);
|
|
#endif
|
|
vec4 luma4B = FxaaTexAlpha4(tex, pos.xy, rcpFrame.xy);
|
|
float lumaNE = textureOffset(tex, pos.xy, ivec(1, -1)).w;
|
|
float lumaSW = textureOffset(tex, pos.xy, ivec(-1, 1)).w;
|
|
float lumaNW = luma4A.w;
|
|
float lumaN = luma4A.z;
|
|
float lumaW = luma4A.x;
|
|
float lumaM = luma4A.y;
|
|
float lumaE = luma4B.z;
|
|
float lumaS = luma4B.x;
|
|
float lumaSE = luma4B.y;*/
|
|
//#else
|
|
vec3 luma = vec3(0.299, 0.587, 0.114);
|
|
float lumaN = dot(textureLodOffset(tex, pos.xy, 0., ivec2(0, -1)).rgb, luma);
|
|
float lumaW = dot(textureLodOffset(tex, pos.xy, 0., ivec2(-1, 0)).rgb, luma);
|
|
vec4 rgbyM = texture2D(tex, pos.xy);
|
|
float lumaE = dot(textureLodOffset(tex, pos.xy, 0., ivec2( 1, 0)).rgb, luma);
|
|
float lumaS = dot(textureLodOffset(tex, pos.xy, 0., ivec2( 0, 1)).rgb, luma);
|
|
float lumaM = dot(rgbyM.rgb, luma);
|
|
//#endif
|
|
/*--------------------------------------------------------------------------*/
|
|
float rangeMin = min(lumaM, min(min(lumaN, lumaW), min(lumaS, lumaE)));
|
|
float rangeMax = max(lumaM, max(max(lumaN, lumaW), max(lumaS, lumaE)));
|
|
float range = rangeMax - rangeMin;
|
|
//return vec4(range);
|
|
/*--------------------------------------------------------------------------*/
|
|
#define FXAA_QUALITY_EDGE_THRESHOLD_MIN (1.0/12.0)
|
|
#define FXAA_QUALITY_EDGE_THRESHOLD (1.0/6.0)
|
|
if(range < max(FXAA_QUALITY_EDGE_THRESHOLD_MIN, rangeMax * FXAA_QUALITY_EDGE_THRESHOLD))
|
|
/*#if (FXAA_DISCARD == 1)
|
|
FxaaDiscard;
|
|
#else*/
|
|
return rgbyM.rgb;
|
|
//return vec3(0);
|
|
//#endif
|
|
/*--------------------------------------------------------------------------*/
|
|
//#if (FXAA_GATHER4_ALPHA == 0)
|
|
float lumaNW = dot(textureLodOffset(tex, pos.xy, 0., ivec2(-1,-1)).rgb, luma);
|
|
float lumaNE = dot(textureLodOffset(tex, pos.xy, 0., ivec2( 1,-1)).rgb, luma);
|
|
float lumaSW = dot(textureLodOffset(tex, pos.xy, 0., ivec2(-1, 1)).rgb, luma);
|
|
float lumaSE = dot(textureLodOffset(tex, pos.xy, 0., ivec2( 1, 1)).rgb, luma);
|
|
//#endif
|
|
/*--------------------------------------------------------------------------*/
|
|
#define FXAA_QUALITY_SUBPIX_CAP (3.0/4.0)
|
|
//#define FXAA_QUALITY_SUBPIX_CAP 0
|
|
#define FXAA_QUALITY_SUBPIX_TRIM (1.0/4.0)
|
|
#define FXAA_QUALITY_SUBPIX_TRIM_SCALE (1.0/(1.0 - FXAA_QUALITY_SUBPIX_TRIM))
|
|
/*--------------------------------------------------------------------------*/
|
|
float lumaL = (lumaN + lumaW + lumaE + lumaS) * 0.25;
|
|
float rangeL = abs(lumaL - lumaM);
|
|
float blendL = clamp((rangeL / range) - FXAA_QUALITY_SUBPIX_TRIM, 0., 1.) * FXAA_QUALITY_SUBPIX_TRIM_SCALE;
|
|
blendL = min(FXAA_QUALITY_SUBPIX_CAP, blendL);
|
|
/*--------------------------------------------------------------------------*/
|
|
float edgeVert =
|
|
abs(lumaNW + (-2.0 * lumaN) + lumaNE) +
|
|
10.0 * abs(lumaW + (-2.0 * lumaM) + lumaE ) +
|
|
abs(lumaSW + (-2.0 * lumaS) + lumaSE);
|
|
float edgeHorz =
|
|
abs(lumaNW + (-2.0 * lumaW) + lumaSW) +
|
|
10.0 * abs(lumaN + (-2.0 * lumaM) + lumaS ) +
|
|
abs(lumaNE + (-2.0 * lumaE) + lumaSE);
|
|
//return vec3(edgeHorz);
|
|
//float edgeVert = abs(lumaS - lumaN);
|
|
//float edgeHorz = abs(lumaE - lumaW);
|
|
bool horzSpan = edgeHorz >= edgeVert;
|
|
/*--------------------------------------------------------------------------*/
|
|
float lengthSign = horzSpan ? -rcpFrame.y : -rcpFrame.x;
|
|
//if (edgeHorz == edgeVert) ;//lengthSign = 0.;
|
|
if(!horzSpan) {
|
|
lumaN = lumaW;
|
|
lumaS = lumaE;
|
|
}
|
|
float gradientN = abs(lumaN - lumaM);
|
|
float gradientS = abs(lumaS - lumaM);
|
|
lumaN = (lumaN + lumaM) * 0.5;
|
|
lumaS = (lumaS + lumaM) * 0.5;
|
|
/*--------------------------------------------------------------------------*/
|
|
bool pairN = gradientN >= gradientS;
|
|
if(!pairN) {
|
|
lumaN = lumaS;
|
|
gradientN = gradientS;
|
|
lengthSign = -lengthSign;
|
|
}
|
|
vec2 posN;
|
|
posN = pos.xy + (horzSpan ? vec2(0.0, lengthSign * 0.5) : vec2(lengthSign * 0.5, 0.0));
|
|
//posN.x = pos.x + (horzSpan ? 0.0 : lengthSign * 0.5);
|
|
//posN.y = pos.y + (horzSpan ? lengthSign * 0.5 : 0.0);
|
|
/*--------------------------------------------------------------------------*/
|
|
#define FXAA_SEARCH_STEPS 8
|
|
#define FXAA_SEARCH_THRESHOLD (1.0/8.0)
|
|
/*--------------------------------------------------------------------------*/
|
|
gradientN *= FXAA_SEARCH_THRESHOLD;
|
|
/*--------------------------------------------------------------------------*/
|
|
vec2 posP = posN;
|
|
vec2 offNP = horzSpan ? vec2(rcpFrame.x, 0.0) : vec2(0.0, rcpFrame.y);
|
|
float lumaEndN = 0.;
|
|
float lumaEndP = 0.;
|
|
bool doneN = false;
|
|
bool doneP = false;
|
|
posN += offNP * (-1.5);
|
|
posP += offNP * ( 1.5);
|
|
for(int i = 0; i < FXAA_SEARCH_STEPS; i++) {
|
|
lumaEndN = dot(texture2DLod(tex, posN.xy, 0.).rgb, luma);
|
|
lumaEndP = dot(texture2DLod(tex, posP.xy, 0.).rgb, luma);
|
|
bool doneN2 = abs(lumaEndN - lumaN) >= gradientN;
|
|
bool doneP2 = abs(lumaEndP - lumaN) >= gradientN;
|
|
if(doneN2 && !doneN) posN += offNP;
|
|
if(doneP2 && !doneP) posP -= offNP;
|
|
if(doneN2 && doneP2) break;
|
|
doneN = doneN2;
|
|
doneP = doneP2;
|
|
if(!doneN) posN -= offNP * 2.0;
|
|
if(!doneP) posP += offNP * 2.0;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
float dstN = horzSpan ? pos.x - posN.x : pos.y - posN.y;
|
|
float dstP = horzSpan ? posP.x - pos.x : posP.y - pos.y;
|
|
/*--------------------------------------------------------------------------*/
|
|
bool directionN = dstN < dstP;
|
|
lumaEndN = directionN ? lumaEndN : lumaEndP;
|
|
/*--------------------------------------------------------------------------*/
|
|
if(((lumaM - lumaN) < 0.0) == ((lumaEndN - lumaN) < 0.0))
|
|
lengthSign = 0.0;
|
|
/*--------------------------------------------------------------------------*/
|
|
float spanLength = (dstP + dstN);
|
|
dstN = directionN ? dstN : dstP;
|
|
float subPixelOffset = 0.5 + (dstN * (-1.0/spanLength));
|
|
subPixelOffset += blendL * (1.0/8.0);
|
|
subPixelOffset *= lengthSign;
|
|
vec3 rgbF = texture2DLod(tex, pos.xy + (horzSpan ? vec2(0., subPixelOffset) : vec2(subPixelOffset, 0.)), 0.).xyz;
|
|
/*--------------------------------------------------------------------------*/
|
|
/*#if (FXAA_LINEAR == 1)
|
|
lumaL *= lumaL;
|
|
#endif*/
|
|
float lumaF = dot(rgbF, vec3(0.299, 0.587, 0.114)) + (1.0/(65536.0*256.0));
|
|
float lumaB = mix(lumaF, lumaL, blendL);
|
|
float scale = min(4.0, lumaB/lumaF);
|
|
rgbF *= scale;
|
|
return vec3(rgbF);//, lumaM.rgb);
|
|
//, lumaM.rgb);
|
|
}
|
|
|
|
|
|
void main() {
|
|
gl_FragColor.rgb = Fxaa3PixelShader(posPos, tex0, dt);
|
|
}
|
|
|
|
|