The fragment shaders converted gl_FragCoord.y to the bottom-left based system of the rectangle uniforms unconditionally, which only holds for Vulkan, Metal and D3D, where gl_FragCoord.y counts from the top. On OpenGL it counts from the bottom, so the media viewer and PiP fades, the content rounding and the incoming call shadow came out mirrored there. The conversion is now driven by a fragCoordYUp uniform, kept at offset 8 in every block that needs it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
33 lines
1,009 B
GLSL
33 lines
1,009 B
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(std140, binding = 0) uniform Params {
|
|
vec2 viewport;
|
|
// 1.0 when gl_FragCoord.y counts from the bottom (OpenGL).
|
|
float fragCoordYUp;
|
|
vec3 shadow;
|
|
};
|
|
|
|
void main() {
|
|
float fragY = (fragCoordYUp > 0.0)
|
|
? gl_FragCoord.y
|
|
: (viewport.y - gl_FragCoord.y);
|
|
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);
|
|
float shadowCoord = shadow.y - fragY;
|
|
float shadowValue = clamp(shadowCoord / shadow.x, 0.0, 1.0);
|
|
float shadowShown = shadowValue * shadow.z;
|
|
fragColor = vec4(min(result.rgb, vec3(1.0)) * (1.0 - shadowShown), result.a);
|
|
}
|