我正在使用opengl着色器进行rgb转换。但它只显示绿色和粉红色的颜色。我正在使用ffmpeg来解码电影。我是初学者,所以不知道如何解决它。 ffmpeg给我三个yuv的缓冲区。我直接将这些缓冲区分配给三个纹理。
以下是我正在使用的着色器。
static const char* VERTEX_SHADER =
"attribute vec4 vPosition; \n"
"attribute vec2 a_texCoord; \n"
"varying vec2 tc; \n"
"uniform mat4 u_mvpMat; \n"
"void main() \n"
"{ \n"
" gl_Position = u_mvpMat * vPosition; \n"
" tc = a_texCoord; \n"
"} \n";
static const char* YUV_FRAG_SHADER =
"#ifdef GL_ES \n"
"precision highp float; \n"
"#endif \n"
"varying vec2 tc; \n"
"uniform sampler2D TextureY; \n"
"uniform sampler2D TextureU; \n"
"uniform sampler2D TextureV; \n"
"uniform float imageWidth; \n"
"uniform float imageHeight; \n"
"void main(void) \n"
"{ \n"
"float nx, ny; \n"
"vec3 yuv; \n"
"vec3 rgb; \n"
"nx = tc.x; \n"
"ny = tc.y; \n"
"yuv.x = texture2D(TextureY, tc).r; \n"
"yuv.y = texture2D(TextureU, vec2(nx/2.0, ny/2.0)).r - 0.5; \n"
"yuv.z = texture2D(TextureV, vec2(nx/2.0, ny/2.0)).r - 0.5; \n"
// Using BT.709 which is the standard for HDTV
"rgb = mat3( 1, 1, 1, \n"
"0, -0.18732, 1.8556, \n"
"1.57481, -0.46813, 0)*yuv;\n"
// BT.601, which is the standard for SDTV is provided as a reference
//"rgb = mat3( 1, 1, 1, \n"
// "0, -0.34413, 1.772, \n"
// "1.402, -0.71414, 0) * yuv; \n"
"gl_FragColor = vec4(rgb, 1.0); \n"
"} \n";
输出:
我做错了什么?这个你能帮我吗。
谢谢。
更新
在调试ffmpeg解码时,我发现ffmpeg解码器给出了PIX_FMT_YUV420P输出格式。我是否需要进行一些调整以获得正确的图像颜色?
答案 0 :(得分:2)
我不确定这种转变:
"rgb = mat3( 1, 1, 1, \n"
"0, -0.18732, 1.8556, \n"
"1.57481, -0.46813, 0)*yuv;\n"
在GLSL using this page as reference中的矩阵*向量运算中刷新我的记忆时,我认为您需要转置系数矩阵,或者将yuv移动到操作的前面,即yuv * mat3(...)
。以mat3(...) * yuv
执行操作意味着:
r = y * 1 + u * 1 + v * 1
g = y * 0 + u * -0.18732 + v * 1.8556
b = y * 1.57481 + u * -0.46813 + v * 0
这些转换非常不正确。
作为另一个参考,这是一个小的,完整的样本GLSL着色器程序,它转换YUV - > RGB可能有一定的指导意义:http://www.fourcc.org/source/YUV420P-OpenGL-GLSLang.c