本案例的目的是理解如何用Metal实现去雾效果滤镜,类似于UV过滤器;


Demo

  • HarbethDemo地址

实操代码

// 去雾效果滤镜
let filter = C7Haze.init(distance: 0.5, slope: 0.5)// 方案1:
ImageView.image = try? BoxxIO(element: originImage, filters: [filter, filter2, filter3]).output()// 方案2:
ImageView.image = originImage.filtering(filter, filter2, filter3)// 方案3:
ImageView.image = originImage ->> filter ->> filter2 ->> filter3

效果对比图

  • 不同参数下效果
distance: 0.25, slope: 0.25 distance: 0.25, slope: 0.5 distance: 0.4, slope: 0.5

实现原理

  • 过滤器

这款滤镜采用并行计算编码器设计.compute(kernel: "C7Haze"),参数因子[distance, slope]

对外开放参数

  • distance: 应用颜色的强度;
  • slope: 颜色变化量;
/// 去雾,类似于UV过滤器
public struct C7Haze: C7FilterProtocol {/// Strength of the color applied.public var distance: Float = 0/// Amount of color change.public var slope: Float = 0public var modifier: Modifier {return .compute(kernel: "C7Haze")}public var factors: [Float] {return [distance, slope]}public init(distance: Float = 0, slope: Float = 0) {self.distance = distanceself.slope = slope}
}
  • 着色器

归一化y乘以颜色变化量,加上强度,得到像素颜色(inColor - dd * white) / (1.0h - dd)

kernel void C7Haze(texture2d<half, access::write> outputTexture [[texture(0)]],texture2d<half, access::read> inputTexture [[texture(1)]],constant float *hazeDistance [[buffer(0)]],constant float *slope [[buffer(1)]],uint2 grid [[thread_position_in_grid]]) {const half4 inColor = inputTexture.read(grid);const half4 white = half4(1.0h);const half dd = half(grid.y) / half(inputTexture.get_height()) * half(*slope) + half(*hazeDistance);const half4 outColor = half4((inColor - dd * white) / (1.0h - dd));outputTexture.write(outColor, grid);
}

Harbeth功能清单

最后