Files
oak-editor/app/shaders/yuv2rgb.frag
T

75 lines
1.8 KiB
GLSL

uniform sampler2D y_channel;
uniform sampler2D u_channel;
uniform sampler2D v_channel;
uniform int bits_per_pixel;
uniform bool full_range;
uniform int yuv_crv;
uniform int yuv_cgu;
uniform int yuv_cgv;
uniform int yuv_cbu;
uniform int interlacing;
uniform int pixel_height;
in vec2 ove_texcoord;
out vec4 frag_color;
void main()
{
vec2 real_coord = ove_texcoord;
if (interlacing != 0) {
float field_height = float(pixel_height / 2);
real_coord.y = floor(real_coord.y * field_height) + 0.25;
if (interlacing == 2) {
real_coord.y += 0.5;
}
real_coord.y /= field_height;
}
// Sample YUV planes
vec3 yuv;
yuv.r = texture(y_channel, real_coord).r;
yuv.g = texture(u_channel, real_coord).r;
yuv.b = texture(v_channel, real_coord).r;
// Pixels will have come in aligned to 16-bit regardless of their actual bit depth, so they must
// be scaled as if they were actually 16-bit
if (bits_per_pixel == 10) {
yuv *= 64.0;
} else if (bits_per_pixel == 12) {
yuv *= 16.0;
}
// Convert YUV limited range from 16-235 to 0-255
yuv.r -= 0.0625; // 16/256
yuv.r *= 1.1643; // 255/219
// Convert 0.0-1.0 to -0.5-0.5
yuv.g = yuv.g - 0.5;
yuv.b = yuv.b - 0.5;
// Use coefficients to weigh YUV into RGB
float crv = float(yuv_crv) / 65536.0;
float cgu = float(yuv_cgu) / 65536.0;
float cgv = float(yuv_cgv) / 65536.0;
float cbu = float(yuv_cbu) / 65536.0;
vec4 rgba;
rgba.r = yuv.r + crv * yuv.b;
rgba.g = yuv.r - cgu * yuv.g - cgv * yuv.b;
rgba.b = yuv.r + cbu * yuv.g;
// If the expected value is full range, transform to full range here
if (full_range) {
rgba.rgb /= 1.1643;
rgba.rgb += 0.0625;
}
// Currently this shader is only used for RGB textures, so just set alpha to 1
rgba.a = 1.0;
frag_color = rgba;
}