GPUImage写双输入的滤镜

今天主要来讲一下怎么用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];

猜你喜欢

转载自blog.csdn.net/u1031/article/details/50818694