ZaStoGram_desktop/Telegram/shaders/pip_yuv420.frag
Ilya Fedin a57aa0f0d5 [qrhi] Fixed the PiP shadow nine-slice mapping.
The thresholds separating the corners from the stretched edges were
computed as fractions of the shadow atlas, but compared against a
coordinate normalized by the window size, so on a 480x270 window the
corner regions took 213 pixels instead of 24 and the sampling ran far
outside the atlas, into the clamp. Ported the mapping from the OpenGL
renderer, which builds the atlas coordinate in pixels.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-11 16:50:36 +03:00

75 lines
2.3 KiB
GLSL

#version 450
layout(location = 0) in vec2 v_texcoord;
layout(location = 0) out vec4 fragColor;
layout(binding = 1) uniform sampler2D y_texture;
layout(binding = 2) uniform sampler2D u_texture;
layout(binding = 3) uniform sampler2D v_texture;
layout(binding = 4) uniform sampler2D h_texture;
layout(std140, binding = 0) uniform Params {
vec2 viewport;
// 1.0 when gl_FragCoord.y counts from the bottom (OpenGL).
float fragCoordYUp;
vec4 roundRect;
float roundRadius;
vec4 fadeColor;
vec2 h_size;
vec4 h_extend;
vec4 h_components;
};
float roundedCorner(vec2 fc) {
vec2 rectHalf = roundRect.zw / 2.0;
vec2 rectCenter = roundRect.xy + rectHalf;
vec2 fromRectCenter = abs(fc - rectCenter);
vec2 vectorRadius = vec2(roundRadius + 0.5);
vec2 fromCenterWithRadius = fromRectCenter + vectorRadius;
vec2 fromRoundingCenter = max(fromCenterWithRadius, rectHalf) - rectHalf;
float rounded = length(fromRoundingCenter) - roundRadius;
return 1.0 - smoothstep(0.0, 1.0, rounded);
}
float shadow(vec2 fc) {
// Nine-slice sampling of the shadow atlas, the same mapping the OpenGL
// renderer uses: the corners are taken pixel to pixel, the edges are
// sampled at the middle of the atlas and stretch.
vec2 origin = roundRect.xy - vec2(h_extend.x, h_extend.w);
vec2 size = roundRect.zw
+ vec2(h_extend.x + h_extend.z, h_extend.y + h_extend.w);
vec2 corner = h_components.xy;
vec2 inside = fc - origin;
vec2 fromOther = inside + h_size - size;
vec2 uv = vec2(
(inside.x < corner.x)
? inside.x
: (fromOther.x > h_size.x - corner.x)
? fromOther.x
: (0.5 * h_size.x),
(inside.y < corner.y)
? inside.y
: (fromOther.y > h_size.y - corner.y)
? fromOther.y
: (0.5 * h_size.y));
return texture(h_texture, uv / h_size).a;
}
void main() {
float fragY = (fragCoordYUp > 0.0)
? gl_FragCoord.y
: (viewport.y - gl_FragCoord.y);
vec2 fc = vec2(gl_FragCoord.x, fragY);
float y = texture(y_texture, v_texcoord).r - 0.0625;
float u = texture(u_texture, v_texcoord).r - 0.5;
float v = texture(v_texture, v_texcoord).r - 0.5;
vec4 result = vec4(
1.164 * y + 1.596 * v,
1.164 * y - 0.392 * u - 0.813 * v,
1.164 * y + 2.017 * u,
1.0);
result = result * (1.0 - fadeColor.a) + fadeColor;
float corner = roundedCorner(fc);
float shadowValue = shadow(fc);
fragColor = result * corner + vec4(0.0, 0.0, 0.0, shadowValue) * (1.0 - corner);
}