GPUImage写双输入的滤镜

来源:互联网 发布:网络电视怎样看中央台 编辑:程序博客网 时间:2024/06/08 14:49

今天主要来讲一下怎么用GPUImage来手撸一个双输入(blend)的滤镜。

那么先说一下为什么要自己手撸多输入的滤镜:

  1. 双输入的滤镜其实是三输入(也就是多个输入端滤镜)的简单版,让大家比较容易上手。

  2. 在实际上写app的时候,往往一个滤镜效果是不能满足需求的,而像:0.5的亮度+0.87的透明度+柔光混合+RGB调整,这种分开做都比较简单,但是合并起来则会使代码变得超长超恶心的效果才是需求,当然可以是利用现成的GPUImage的Filter来叠加达到效果,教程请看:用GPUImage做难一点点的效果 但是这里我们用一个fsh文件来写,那么代码量就大大滴减少了。

双输入的滤镜可以通过GPUImageTwoInputFilter来实现,只要实现了叠加的算法就可以了。

_downSoftLightBlendFilter = [[GPUImageTwoInputFilter alloc] initWithFragmentShaderFromFile:@"customBlendShader"];

customBlendShader.fsh 代码如下:

varying highp vec2 textureCoordinate;varying highp vec2 textureCoordinate2;uniform sampler2D inputImageTexture;uniform sampler2D inputImageTexture2;void main(){    //base就是add的target,overlay就是第二个,均用vec4来表示像素    mediump vec4 base = texture2D(inputImageTexture, textureCoordinate);    mediump vec4 overlay = texture2D(inputImageTexture2, textureCoordinate2);    //为了防止第一个加入的图片(底图),有一些空白的像素点(指的是黑色,并不是白色)    lowp float alphaDivisor = base.a + step(base.a, 0.0); // Protect against a divide-by-zero blacking out things in the output    //这个是柔光混合的算法:    //(2*A-1)*(B-B*B)+B    //(2*A-1)*(sqrt(B)-B)+B    //overlay > vec4(0.5)  --> (2*A-1)*(B-B*B)+B    //overlay <= vec4(0.5) --> (2*A-1)*(sqrt(B)-B)+B    if (max(overlay, vec4(0.5)) == vec4(0.5)){        gl_FragColor = (vec4(2) * overlay - vec4(1)) * (sqrt(base) - base) + base;    }else {       gl_FragColor = (vec4(2) * overlay - vec4(1)) * (base - base * base) + base;    }}

当然你也可以做别的一些操作,比如 先柔光混合,再让亮度+0.5:

varying highp vec2 textureCoordinate;varying highp vec2 textureCoordinate2;uniform sampler2D inputImageTexture;uniform sampler2D inputImageTexture2;void main(){    //base就是add的target,overlay就是第二个,均用vec4来表示像素    mediump vec4 base = texture2D(inputImageTexture, textureCoordinate);    mediump vec4 overlay = texture2D(inputImageTexture2, textureCoordinate2);    //为了防止第一个加入的图片(底图),有一些空白的像素点(指的是黑色,并不是白色)    lowp float alphaDivisor = base.a + step(base.a, 0.0); // Protect against a divide-by-zero blacking out things in the output    //这个是柔光混合的算法:    //(2*A-1)*(B-B*B)+B    //(2*A-1)*(sqrt(B)-B)+B    //overlay > vec4(0.5)  --> (2*A-1)*(B-B*B)+B    //overlay <= vec4(0.5) --> (2*A-1)*(sqrt(B)-B)+B    mediump vec4 mixColor;    if (max(overlay, vec4(0.5)) == vec4(0.5)){        mixColor = (vec4(2) * overlay - vec4(1)) * (sqrt(base) - base) + base;    }else {       mixColor = (vec4(2) * overlay - vec4(1)) * (base - base * base) + base;    }    gl_FragColor = vec4((mixColor.rgb + vec3(0.5)), mixColor.w);}

这样基本就能做只使用两张图片混合(例如加上水印)的所有滤镜效果了。

用法也是非常简单,直接当成是GPUImageTwoInputFilter来用就好。

    _downGPUImageView = [[GPUImageView alloc] initWithFrame:_imgViewDown.frame];    [self.view addSubview:_downGPUImageView];    UIImage *demoImg = [UIImage imageNamed:@"demo.jpg"];    _downGPUImagePicture = [[GPUImagePicture alloc] initWithImage:demoImg];    _downSoftLightBlendFilter = [[GPUImageTwoInputFilter alloc] initWithFragmentShaderFromFile:@"customBlendShader"];    [_downGPUImagePicture addTarget:_downSoftLightBlendFilter];    [_downBlendPicture addTarget:_downSoftLightBlendFilter];    [_downSoftLightBlendFilter addTarget:_downGPUImageView];
0 0