uniform sampler2D luma; uniform sampler2D chroma; uniform vec2 size; uniform vec2 srcSize; uniform vec4 crop; uniform float alpha; uniform int matrix; uniform int range; uniform vec2 chromaOff; out vec4 outColor; float noise(vec2 p) { return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453); } const float PI = 3.1415926535893; float sinc(float x) { x *= PI; return abs(x) < 1e-6 ? 1.0 : sin(x) / x; } float lanczos(float x) { if (abs(x) >= 3.0) return 0.0; return sinc(x) * sinc(x / 3.0); } float hermite(float x) { float a = abs(x); if (a >= 1.0) return 0.0; return 1.0 - 3.0 * a * a + 2.0 * a * a * a; } vec4 resample(sampler2D tex, vec2 plane, vec2 dest, vec2 uv) { vec2 pt = 1.0 / plane; float wx[6]; float wy[6]; vec2 base; int upx = dest.x >= plane.x ? 1 : 0; int tx = upx == 1 ? 6 : 2; float fsx = max(1.0, plane.x / dest.x); float f = fract(uv.x * plane.x - 0.5); base.x = uv.x - f * pt.x - pt.x * (float(tx) * 0.5 - 1.0); float sx = 0.0; for (int i = 0; i < 6; ++i) { if (i >= tx) { wx[i] = 0.0; continue; } float x = f - (float(i) - float(tx) * 0.5 + 1.0); wx[i] = upx == 1 ? lanczos(x / fsx) : hermite(x / fsx); sx += wx[i]; } if (sx != 0.0) for (int i = 0; i < 6; ++i) wx[i] /= sx; int upy = dest.y >= plane.y ? 1 : 0; int ty = upy == 1 ? 6 : 2; float fsy = max(1.0, plane.y / dest.y); f = fract(uv.y * plane.y - 0.5); base.y = uv.y - f * pt.y - pt.y * (float(ty) * 0.5 - 1.0); float sy = 0.0; for (int i = 0; i < 6; ++i) { if (i >= ty) { wy[i] = 0.0; continue; } float y = f - (float(i) - float(ty) * 0.5 + 1.0); wy[i] = upy == 1 ? lanczos(y / fsy) : hermite(y / fsy); sy += wy[i]; } if (sy != 0.0) for (int i = 0; i < 6; ++i) wy[i] /= sy; vec4 col = vec4(0.0); for (int i = 0; i < 6; ++i) { if (wx[i] == 0.0) continue; for (int j = 0; j < 6; ++j) { if (wy[j] == 0.0) continue; vec2 c = base + vec2(float(i) * pt.x, float(j) * pt.y); col += (wx[i] * wy[j]) * texture(tex, c); } } return col; } void main() { vec2 p = vec2(gl_FragCoord.x, size.y - gl_FragCoord.y) / size; vec2 uv = crop.xy + p * crop.zw; float Yv = resample(luma, srcSize, size, uv).r; vec2 ch = resample(chroma, srcSize * 0.5, size, uv + chromaOff).rg; vec3 yuv; if (range == 0) { yuv = vec3((Yv - 16.0 / 255.0) / (219.0 / 255.0), (ch.r - 128.0 / 255.0) / (224.0 / 255.0), (ch.g - 128.0 / 255.0) / (224.0 / 255.0)); } else { yuv = vec3(Yv, ch.r - 0.5, ch.g - 0.5); } mat3 m = matrix == 1 ? mat3(1.0, 1.0, 1.0, 0.0, -0.187324, 1.855600, 1.574800, -0.468124, 0.0) : mat3(1.0, 1.0, 1.0, 0.0, -0.344136, 1.772000, 1.402000, -0.714136, 0.0); vec3 rgb = m * yuv; rgb += (noise(gl_FragCoord.xy) - 0.5) / 255.0; outColor = vec4(clamp(rgb, 0.0, 1.0), alpha); }