qq群里有兄弟讨论使用gles rgb转换yuv问题,刚刚好前段时间我花了两天时间抄袭修改过,代码简单粗暴,如下:
const GLchar *strVertexShaderRgb2Yuv =
"attribute vec4 position;\n"
"attribute vec4 inputTextureCoordinate;\n"
"\n"
"varying vec2 textureCoordinate;\n"
"\n"
"void main()\n"
"{\n"
" gl_Position = position;\n"
" textureCoordinate = inputTextureCoordinate.xy;\n"
"}\n";
const GLchar *strFragmentShaderRgb2Yuv =
"precision highp float;\n"
"\n"
"varying vec2 textureCoordinate;\n"
"\n"
"uniform sampler2D inputImageTexture;\n"
"uniform float uWidth;\n"
"uniform float uHeight;\n"
"\n"
"float cY(float x, float y)\n"
"{\n"
" vec4 c = texture2D(inputImageTexture, vec2(x, y));\n"
" return c.r * 0.257 + c.g * 0.504 + c.b * 0.098 + 0.0625;\n"
"}\n"
"\n"
"vec4 cC(float x, float y, float dx, float dy)\n"
"{\n"
" vec4 c0 = texture2D(inputImageTexture, vec2(x, y));\n"
" vec4 c1 = texture2D(inputImageTexture, vec2(x + dx, y));\n"
" vec4 c2 = texture2D(inputImageTexture, vec2(x, y + dy));\n"
" vec4 c3 = texture2D(inputImageTexture, vec2(x + dx, y + dy));\n"
" return (c0 + c1 + c2 + c3) / 4.0;\n"
"}\n"
"\n"
"float cU(float x, float y, float dx, float dy)\n"
"{\n"
" vec4 c = cC(x, y, dx, dy);\n"
" return -0.148 * c.r - 0.291 * c.g + 0.439 * c.b + 0.5000;\n"
"}\n"
"\n"
"float cV(float x, float y, float dx, float dy)\n"
"{\n"
" vec4 c = cC(x, y, dx, dy);\n"
" return 0.439 * c.r - 0.368 * c.g - 0.071 * c.b + 0.5000;\n"
"}\n"
"\n"
"vec4 calculateY(float x, float y, float dx, float dy)\n"
"{\n"
" vec4 c = vec4(0.0);\n"
" c[0] = cY(x, y);\n"
" c[1] = cY(x + 1.0 * dx, y);\n"
" c[2] = cY(x + 2.0 * dx, y);\n"
" c[3] = cY(x + 3.0 * dx, y);\n"
" return c;\n"
"}\n"
"\n"
"vec4 calculateU(float x, float y, float dx, float dy)\n"
"{\n"
" vec4 c = vec4(0.0);\n"
" c[0] = cU(x, y, dx, dy);\n"
" c[1] = cU(x + 2.0 * dx, y, dx, dy);\n"
" c[2] = cU(x + 4.0 * dx, y, dx, dy);\n"
" c[3] = cU(x + 6.0 * dx, y, dx, dy);\n"
" return c;\n"
"}\n"
"\n"
"vec4 calculateV(float x, float y, float dx, float dy)\n"
"{\n"
" vec4 c = vec4(0.0);\n"
" c[0] = cV(x, y, dx, dy);\n"
" c[1] = cV(x + 2.0 * dx, y, dx, dy);\n"
" c[2] = cV(x + 4.0 * dx, y, dx, dy);\n"
" c[3] = cV(x + 6.0 * dx, y, dx, dy);\n"
" return c;\n"
"}\n"
"\n"
"void main()\n"
"{\n"
" if (textureCoordinate.y > 0.375) {\n"
" return;\n"
" }\n"
"\n"
" float y4xSum = uWidth * uHeight / 4.0;\n"
" float u4xSum = uWidth * uHeight / 16.0;\n"
" float v4xSum = uWidth * uHeight / 16.0;\n"
" float yuv4xOffset = floor(textureCoordinate.y * uHeight) * uWidth + floor(textureCoordinate.x * uWidth);\n"
"\n"
" if (yuv4xOffset < y4xSum) {\n"
" float yOffset = yuv4xOffset * 4.0 + 1.0;\n"
" float yX = floor(mod(yOffset, uWidth));\n"
" float yY = floor(yOffset / uWidth);\n"
" yY = uHeight - yY;\n"
" gl_FragColor = calculateY(yX / uWidth, yY / uHeight, 1.0 / uWidth, 1.0 / uHeight);\n"
" } else if (yuv4xOffset < (y4xSum + u4xSum)) {\n"
" float uOffset = (yuv4xOffset - y4xSum) * 4.0 + 1.0;\n"
" float uX = floor(mod(uOffset, uWidth / 2.0)) * 2.0;\n"
" float uY = floor(uOffset / (uWidth / 2.0)) * 2.0;\n"
" uY = uHeight - uY - 1.0;\n"
" gl_FragColor = calculateU(uX / uWidth, uY / uHeight, 1.0 / uWidth, 1.0 / uHeight);\n"
" } else if (yuv4xOffset < (y4xSum + u4xSum + v4xSum)) {\n"
" float vOffset = (yuv4xOffset - y4xSum - u4xSum) * 4.0 + 1.0;\n"
" float vX = floor(mod(vOffset, uWidth / 2.0)) * 2.0;\n"
" float vY = floor(vOffset / (uWidth / 2.0)) * 2.0;\n"
" vY = uHeight - vY - 1.0;\n"
" gl_FragColor = calculateV(vX / uWidth, vY / uHeight, 1.0 / uWidth, 1.0 / uHeight);\n"
" }\n"
"}\n";
缺点
- 空间浪费:只用了 framebuffer 3/8
- 分辨率限制为8的倍数
- rgb到yuv的转换公式写死,不够灵活
参考文章:湖广午王的博客该链接已失效,可见(https://www.jishux.com/p/518a2b6653e09e43)
YUV to RGB Conversion