Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/110.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 在OpenGLES中组合多个着色器_Ios_Opengl Es_Filter_Shader - Fatal编程技术网

Ios 在OpenGLES中组合多个着色器

Ios 在OpenGLES中组合多个着色器,ios,opengl-es,filter,shader,Ios,Opengl Es,Filter,Shader,我有一个接收YUV频道的代码,我正在使用OpenGLES绘制它们。基本上,我有一个将它们组合在一起的着色器 我想在结果中添加一个锐化过滤器(使用以下示例:) 我不确定如何在实际结果上运行另一个着色器(因为我希望在上一个着色器将所有通道组合到单个帧后运行它) 我当前的代码如下所示: glUniform1i(texLum, 0); glUniform1i(texU, 1); glUniform1i(texV, 2);

我有一个接收YUV频道的代码,我正在使用OpenGLES绘制它们。基本上,我有一个将它们组合在一起的着色器

我想在结果中添加一个锐化过滤器(使用以下示例:)

我不确定如何在实际结果上运行另一个着色器(因为我希望在上一个着色器将所有通道组合到单个帧后运行它)

我当前的代码如下所示:

            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]);
我想我需要在最后一行(gldrawerelements)之前添加新的着色器,但我不确定如何调用它

我的着色器如下所示:

    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是保存通道的纹理。

锐化是卷积滤波器,因此它读取九个输入值以产生一个输出值。因此,如果您有另一个着色器,该着色器应该出现在它之前,并且一次操作一个像素,那么可以分两步运行它们(首先是YUV变换,然后是锐化),以消除重复计算,即使这不是将着色器组合为闭合框的最简单方法

如果您想实时组合它们,请将YUV转换分解为一个单独的函数,并让锐化过滤器调用该函数,而不是
texture2D
。GL着色器编译器对可以链接在一起以精确生成已编译程序的源文件的数量没有任何限制,因此您可以按照通常的编程路线进行函数重用

如果希望运行其中一个,请运行另一个,然后使用中间渲染到纹理阶段。进行YUV变换,然后切换缓冲区并将其输出用作锐化的输入

实际上,前者可能比后者快,因为YUV变换可能是一种快速运算(例如,如果是YUV到RGB,那么它是一个矩阵乘法),而内存速度和需要进行相当剧烈的状态更改可能非常昂贵。如果性能是一个问题,您可能需要分析

编辑:所以,从您当前的主目录中,您可以将其调整为(在此处键入,请原谅错误):

然后在锐化过滤器中,将调用
texture2D(,coord)
替换为调用
yuvTexture2D(coord)
,要么将片段包含在锐化着色器的源代码列表中,要么将其链接到程序中。关于切换到使用矩阵方法,我想您会想要(为了便于键入,我将把它格式化为字符串常量以外的格式):


锐化是一种卷积滤波器,因此它读取九个输入值以产生一个输出值。因此,如果您有另一个着色器,该着色器应该出现在它之前,并且一次操作一个像素,那么可以分两步运行它们(首先是YUV变换,然后是锐化),以消除重复计算,即使这不是将着色器组合为闭合框的最简单方法

如果您想实时组合它们,请将YUV转换分解为一个单独的函数,并让锐化过滤器调用该函数,而不是
texture2D
。GL着色器编译器对可以链接在一起以精确生成已编译程序的源文件的数量没有任何限制,因此您可以按照通常的编程路线进行函数重用

如果希望运行其中一个,请运行另一个,然后使用中间渲染到纹理阶段。进行YUV变换,然后切换缓冲区并将其输出用作锐化的输入

实际上,前者可能比后者快,因为YUV变换可能是一种快速运算(例如,如果是YUV到RGB,那么它是一个矩阵乘法),而内存速度和需要进行相当剧烈的状态更改可能非常昂贵。如果性能是一个问题,您可能需要分析

编辑:所以,从您当前的主目录中,您可以将其调整为(在此处键入,请原谅错误):

然后在锐化过滤器中,将调用
texture2D(,coord)
替换为调用
yuvTexture2D(coord)
,要么将片段包含在锐化着色器的源代码列表中,要么将其链接到程序中。关于切换到使用矩阵方法,我想您会想要(为了便于键入,我将把它格式化为字符串常量以外的格式):


我已经为我的着色器添加了代码。你能告诉我如何组合过滤器吗?我有点困惑,因为我的代码一次只能处理1个像素,我不知道如何将其转换为矩阵操作。@Gilad-我可以谈谈将颜色处理操作和卷积分解为两个单独着色器的好处,这两个着色器将在两个过程中执行。对于Sobel边缘检测过滤器,它从3x3区域中提取值,首先将图像转换为其亮度值,然后获取该亮度图像并在其上运行卷积运算,与使用单个着色器在一次过程中执行这两个操作相比,iPhone 4的速度提高了10倍。除非内存有问题,否则我强烈建议将此过程分为两个过程,一个用于YUV->RGB,另一个用于锐化。@BradLarson我同意。我尝试了这两种方法,最终决定采用两个阶段。它生成了一个更易于维护的代码,而且速度更快。我已经为我的着色器添加了代码。你能告诉我如何组合过滤器吗?我有点困惑,因为我的代码一次只能处理1个像素,我不知道如何将其转换为矩阵操作。@Gilad-我可以谈谈将颜色处理操作和卷积分解为两个单独着色器的好处,这两个着色器将在两个过程中执行。对于Sobel边缘检测滤波器,它从3x3区域提取值,首先将图像转换为其亮度值,然后获取该亮度图像并在其上运行卷积,得到
"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
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;
}