我有一个代码,我收到YUV频道,我正在使用OpenGLES绘制它们。基本上,我有一个将它们组合在一起的着色器。
我想在结果中添加锐化过滤器(使用以下示例:http://igortrindade.wordpress.com/2010/04/23/fun-with-opengl-and-shaders/)
我不确定如何在实际结果上运行另一个着色器(因为我想在之前的着色器将所有通道组合到单个帧之后运行它。)
我当前的代码如下:
glUniform1i(texLum, 0);
glUniform1i(texU, 1);
glUniform1i(texV, 2);
glEnableVertexAttribArray(positionLoc);
glVertexAttribPointer(positionLoc,
4,
GL_FLOAT,
GL_FALSE,
0,
&vertices[0]);
glEnableVertexAttribArray(texCoordLoc);
glVertexAttribPointer(texCoordLoc,
2,
GL_FLOAT,
GL_FALSE,
0,
&texCoords[0]);
glDrawElements(GL_TRIANGLES, sizeof(indices)/sizeof(indices[0]), GL_UNSIGNED_BYTE, &indices[0]);
我想我需要在最后一行(glDrawElements)之前添加新的着色器,但我不确定如何调用它。
我的着色器看起来像这样:
static char const *frag =
"uniform lowp sampler2D texLum; \n"
"uniform lowp sampler2D texU; \n"
"uniform lowp sampler2D texV; \n"
"varying mediump vec2 texCoordAtFrag; \n"
"void main() { \n"
" lowp float Y = texture2D(texLum, texCoordAtFrag).r; \n"
" lowp float U = texture2D(texU, texCoordAtFrag).r; \n"
" lowp float V = texture2D(texV, texCoordAtFrag).r; \n"
" lowp float R = 1.164 * (Y - 16.0 / 256.0) + 1.596 * (V - 0.5); \n"
" lowp float G = 1.164 * (Y - 16.0 / 256.0) - 0.813 * (V - 0.5) - 0.391 * (U - 0.5); \n"
" lowp float B = 1.164 * (Y - 16.0 / 256.0) + 2.018 * (U - 0.5); \n"
" gl_FragColor = vec4(R,G,B,1); \n"
"}\r\n";
static char const *vert =
"varying mediump vec2 texCoordAtFrag; \n"
"attribute vec4 Position; \n"
"attribute vec2 TexCoord; \n"
"void main() { \n"
" texCoordAtFrag = TexCoord; \n"
" gl_Position = Position; \n"
"}\r\n";
texLum,texU,texV是持有频道的纹理。
答案 0 :(得分:1)
Sharpen是一个卷积滤波器,因此它读取九个输入值以产生一个输出值。因此,如果你有另一个应该在它之前出现的着色器并且一次操作一个像素,那么就可以通过两个步骤运行它们(YUV变换优先,锐化第二个),以便消除重复计算,甚至如果它不是将着色器组合为封闭盒子的最简单方法。
如果要实时组合它们,请将YUV转换分解为单独的函数,并使用锐化过滤器调用而不是texture2D
。 GL着色器编译器对源文件的数量没有任何限制,您可以将它们链接在一起以精确地编译已编译的程序,以便您可以按照通常的编程路径进行函数重用。
如果您更喜欢运行另一个,则运行另一个,然后使用中间渲染到纹理阶段。执行YUV转换,然后切换缓冲区并使用它的输出作为锐化的输入。
实际上前者实际上可能比后者更快,因为YUV变换可能是一个快速操作(例如,它是YUV到RGB然后是一个矩阵乘法),而内存速度和需要进行相当大的改变国家可能相当昂贵。如果性能受到关注,您可能需要分析一下。
编辑:所以,从您当前的主要内容,你可以适应它(在这里输入,我去,请原谅错误):
"uniform lowp sampler2D texLum; \n"
"uniform lowp sampler2D texU; \n"
"uniform lowp sampler2D texV; \n"
"varying mediump vec2 texCoordAtFrag; \n"
"lowp vec4 yuvTexture2D(mediump vec2 coord) { \n"
" lowp float Y = texture2D(texLum, coord).r; \n"
" lowp float U = texture2D(texU, coord).r; \n"
" lowp float V = texture2D(texV, coord).r; \n"
" lowp float R = 1.164 * (Y - 16.0 / 256.0) + 1.596 * (V - 0.5); \n"
" lowp float G = 1.164 * (Y - 16.0 / 256.0) - 0.813 * (V - 0.5) - 0.391 * (U - 0.5); \n"
" lowp float B = 1.164 * (Y - 16.0 / 256.0) + 2.018 * (U - 0.5); \n"
" return vec4(R,G,B,1.0); \n"
"}\r\n
然后在您的锐化过滤器中,您通过调用texture2D(<whatever>, coord)
将调用替换为yuvTexture2D(coord)
,将片段包含在锐化着色器的源列表中或将其链接到程序中。关于切换到使用矩阵方法,我猜你想要(除了作为一个字符串常量,我打算将其格式化,以便于输入):
uniform lowp sampler2D texLum;
uniform lowp sampler2D texU;
uniform lowp sampler2D texV;
varying mediump vec2 texCoordAtFrag;
const mediump mat4 yuvToRgb =
mat4( 1.164, 1.164, 1.164, -0.07884,
2.018, -0.391, 0.0, 1.153216,
0.0, -0.813, 1.596, 0.53866,
0.0, 0.0, 0.0, 1.0);
lowp vec4 yuvTexture2D(mediump vec2 coord) {
lowp vec4 yuv =
vec4(
texture2D(texLum, coord).r,
texture2D(texU, coord).r,
texture2D(texV, coord).r,
1.0)
return yuvToRgb * yuv;
}