1

我有一个接收 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 是保存通道的纹理。

4

1 回答 1

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;
}
于 2012-04-12T21:50:59.087 回答