ZaStoGram_desktop/Telegram/shaders/group_frame.frag
Ilya Fedin f9186bfab0 [qrhi] Restored the dither noise of the group call background.
The noise was a flat plus or minus 0.001 added to the whole tile, while
the OpenGL renderer adds up to plus or minus 0.004, modulated by
luminance so that dark areas get more of it, and only to the blurred
background. The noise texture encoding is back to the one that decoder
expects too, the values it holds reach beyond the [-1, 1] the previous
encoding assumed and were clipped.

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

85 lines
2.7 KiB
GLSL

#version 450
layout(location = 0) in vec2 v_texcoord;
layout(location = 1) in vec2 b_texcoord;
layout(location = 2) in vec2 v_position;
layout(location = 0) out vec4 fragColor;
layout(binding = 1) uniform sampler2D s_texture;
layout(binding = 2) uniform sampler2D b_texture;
layout(binding = 3) uniform sampler2D n_texture;
layout(std140, binding = 0) uniform Params {
vec2 viewport;
vec4 frameBg;
vec4 shadow;
float paused;
vec4 roundRect;
vec2 radiusOutline;
vec4 roundBg;
vec4 outlineFg;
};
const float noiseGrain = 0.002;
vec2 roundedCorner(vec2 fc) {
vec2 rectHalf = roundRect.zw / 2.0;
vec2 rectCenter = roundRect.xy + rectHalf;
vec2 fromRectCenter = abs(fc - rectCenter);
vec2 vectorRadius = radiusOutline.xx + vec2(0.5);
vec2 fromCenterWithRadius = fromRectCenter + vectorRadius;
vec2 fromRoundingCenter = max(fromCenterWithRadius, rectHalf) - rectHalf;
float rounded = length(fromRoundingCenter) - radiusOutline.x;
float outline = rounded + radiusOutline.y;
return vec2(
1.0 - smoothstep(0.0, 1.0, rounded),
1.0 - (smoothstep(0.0, 1.0, outline) * outlineFg.a));
}
float insideTexture() {
vec2 textureHalf = vec2(0.5, 0.5);
vec2 fromTextureCenter = abs(v_texcoord - textureHalf);
vec2 fromTextureEdge = max(fromTextureCenter, textureHalf) - textureHalf;
float outsideCheck = dot(fromTextureEdge, fromTextureEdge);
return step(outsideCheck, 0.0);
}
// Dithering the blurred background against the banding it shows.
vec4 background() {
// Plain blurred color, main() mixes it with frameBg by shadow.w.
vec4 result = texture(b_texture, b_texcoord);
float noiseClamped = texture(n_texture, v_position / 256.0).r;
float noiseIntensity = (noiseClamped * 4.0) - 2.0;
vec3 lumcoeff = vec3(0.299, 0.587, 0.114);
float luminance = dot(result.rgb, lumcoeff);
float lum = smoothstep(0.2, 0.0, luminance) + luminance;
vec3 noiseColor = mix(vec3(noiseIntensity), vec3(0.0), pow(lum, 4.0));
result.rgb = result.rgb + noiseColor * noiseGrain;
return result;
}
void main() {
vec2 fc = v_position;
float inside = insideTexture() * (1.0 - paused);
vec4 result;
float backgroundOpacity = shadow.w;
vec4 mainColor = texture(s_texture, v_texcoord);
result = mainColor * inside
+ (1.0 - inside) * (backgroundOpacity * background()
+ (1.0 - backgroundOpacity) * frameBg);
float shadowCoord = fc.y - roundRect.y;
float shadowValue = max(1.0 - (shadowCoord / shadow.x), 0.0);
float shadowShown = max(shadowValue * shadow.y, paused) * shadow.z;
result = vec4(result.rgb * (1.0 - shadowShown), result.a);
vec2 roundOutline = roundedCorner(fc);
result = result * roundOutline.y
+ vec4(outlineFg.rgb, 1.0) * (1.0 - roundOutline.y);
result = result * roundOutline.x + roundBg * (1.0 - roundOutline.x);
fragColor = result;
}