mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
103 lines
3.6 KiB
Text
103 lines
3.6 KiB
Text
|
|
#version 450
|
||
|
|
// FSR 1.0 EASU (Edge Adaptive Spatial Upsampling) — Fragment Shader
|
||
|
|
// Based on AMD FidelityFX Super Resolution 1.0
|
||
|
|
// Implements edge-adaptive bilinear upsampling with directional filtering
|
||
|
|
|
||
|
|
layout(set = 0, binding = 0) uniform sampler2D uInput;
|
||
|
|
|
||
|
|
layout(push_constant) uniform FSRConstants {
|
||
|
|
vec4 con0; // inputSize.xy, 1/inputSize.xy
|
||
|
|
vec4 con1; // inputSize.xy / outputSize.xy, 0.5 * inputSize.xy / outputSize.xy
|
||
|
|
vec4 con2; // outputSize.xy, 1/outputSize.xy
|
||
|
|
vec4 con3; // sharpness, 0, 0, 0
|
||
|
|
} fsr;
|
||
|
|
|
||
|
|
layout(location = 0) in vec2 TexCoord;
|
||
|
|
layout(location = 0) out vec4 outColor;
|
||
|
|
|
||
|
|
// Fetch a texel with offset (in input pixels)
|
||
|
|
vec3 fsrFetch(vec2 p, vec2 off) {
|
||
|
|
return textureLod(uInput, (p + off + 0.5) * fsr.con0.zw, 0.0).rgb;
|
||
|
|
}
|
||
|
|
|
||
|
|
void main() {
|
||
|
|
// Undo the vertex shader Y flip (postprocess.vert flips for Vulkan overlay,
|
||
|
|
// but we need standard UV coords for texture sampling)
|
||
|
|
vec2 tc = vec2(TexCoord.x, 1.0 - TexCoord.y);
|
||
|
|
|
||
|
|
// Map output pixel to input space
|
||
|
|
vec2 pp = tc * fsr.con2.xy; // output pixel position
|
||
|
|
vec2 ip = pp * fsr.con1.xy - 0.5; // input pixel position (centered)
|
||
|
|
vec2 fp = floor(ip);
|
||
|
|
vec2 ff = ip - fp;
|
||
|
|
|
||
|
|
// 12-tap filter: 4x3 grid around the pixel
|
||
|
|
// b c
|
||
|
|
// e f g h
|
||
|
|
// i j k l
|
||
|
|
// n o
|
||
|
|
vec3 b = fsrFetch(fp, vec2( 0, -1));
|
||
|
|
vec3 c = fsrFetch(fp, vec2( 1, -1));
|
||
|
|
vec3 e = fsrFetch(fp, vec2(-1, 0));
|
||
|
|
vec3 f = fsrFetch(fp, vec2( 0, 0));
|
||
|
|
vec3 g = fsrFetch(fp, vec2( 1, 0));
|
||
|
|
vec3 h = fsrFetch(fp, vec2( 2, 0));
|
||
|
|
vec3 i = fsrFetch(fp, vec2(-1, 1));
|
||
|
|
vec3 j = fsrFetch(fp, vec2( 0, 1));
|
||
|
|
vec3 k = fsrFetch(fp, vec2( 1, 1));
|
||
|
|
vec3 l = fsrFetch(fp, vec2( 2, 1));
|
||
|
|
vec3 n = fsrFetch(fp, vec2( 0, 2));
|
||
|
|
vec3 o = fsrFetch(fp, vec2( 1, 2));
|
||
|
|
|
||
|
|
// Luma (use green channel as good perceptual approximation)
|
||
|
|
float bL = b.g, cL = c.g, eL = e.g, fL = f.g;
|
||
|
|
float gL = g.g, hL = h.g, iL = i.g, jL = j.g;
|
||
|
|
float kL = k.g, lL = l.g, nL = n.g, oL = o.g;
|
||
|
|
|
||
|
|
// Directional edge detection
|
||
|
|
// Compute gradients in 4 directions (N-S, E-W, NE-SW, NW-SE)
|
||
|
|
float dc = cL - jL;
|
||
|
|
float db = bL - kL;
|
||
|
|
float de = eL - hL;
|
||
|
|
float di = iL - lL;
|
||
|
|
|
||
|
|
// Length of the edge in each direction
|
||
|
|
float lenH = abs(eL - fL) + abs(fL - gL) + abs(iL - jL) + abs(jL - kL);
|
||
|
|
float lenV = abs(bL - fL) + abs(fL - jL) + abs(cL - gL) + abs(gL - kL);
|
||
|
|
|
||
|
|
// Determine dominant edge direction
|
||
|
|
float dirH = lenV / (lenH + lenV + 1e-7);
|
||
|
|
float dirV = lenH / (lenH + lenV + 1e-7);
|
||
|
|
|
||
|
|
// Bilinear weights
|
||
|
|
float w1 = (1.0 - ff.x) * (1.0 - ff.y);
|
||
|
|
float w2 = ff.x * (1.0 - ff.y);
|
||
|
|
float w3 = (1.0 - ff.x) * ff.y;
|
||
|
|
float w4 = ff.x * ff.y;
|
||
|
|
|
||
|
|
// Edge-aware sharpening: boost weights along edges
|
||
|
|
float sharpness = fsr.con3.x;
|
||
|
|
float edgeStr = max(abs(lenH - lenV) / (lenH + lenV + 1e-7), 0.0);
|
||
|
|
float sharp = mix(0.0, sharpness, edgeStr);
|
||
|
|
|
||
|
|
// Sharpen bilinear by pulling toward nearest texel
|
||
|
|
float maxW = max(max(w1, w2), max(w3, w4));
|
||
|
|
w1 = mix(w1, float(w1 == maxW), sharp * 0.25);
|
||
|
|
w2 = mix(w2, float(w2 == maxW), sharp * 0.25);
|
||
|
|
w3 = mix(w3, float(w3 == maxW), sharp * 0.25);
|
||
|
|
w4 = mix(w4, float(w4 == maxW), sharp * 0.25);
|
||
|
|
|
||
|
|
// Normalize
|
||
|
|
float wSum = w1 + w2 + w3 + w4;
|
||
|
|
w1 /= wSum; w2 /= wSum; w3 /= wSum; w4 /= wSum;
|
||
|
|
|
||
|
|
// Final color: weighted blend of the 4 nearest texels with edge awareness
|
||
|
|
vec3 color = f * w1 + g * w2 + j * w3 + k * w4;
|
||
|
|
|
||
|
|
// Optional: blend in some of the surrounding texels for anti-aliasing
|
||
|
|
float aa = 0.125 * edgeStr;
|
||
|
|
color = mix(color, (b + c + e + h + i + l + n + o) / 8.0, aa * 0.15);
|
||
|
|
|
||
|
|
outColor = vec4(clamp(color, 0.0, 1.0), 1.0);
|
||
|
|
}
|