【发布时间】:2023-03-29 21:34:01
【问题描述】:
我对@987654323@/Metal 很陌生,我正在尝试理解一些基本概念。
在我们的应用程序中,我们使用CIFilter 过滤视频。我看到了一个 2017 年的 WWDC 视频,解释说你可以用 Metal 包装 CIFilter 并将其用作常规过滤器。
我正在尝试了解如何将此 OpenGL 视频效果转换为 Metal,以便我可以将其用作未来效果的参考点。
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
float amount = sin(iTime) * 0.1;
// uv coords
vec2 uv = fragCoord / iResolution.xy;
amount *= 0.3;
float split = 1. - fract(iTime / 2.);
float scanOffset = 0.01;
vec2 uv1 = vec2(uv.x + amount, uv.y);
vec2 uv2 = vec2(uv.x, uv.y + amount);
if (uv.y > split) {
uv.x += scanOffset;
uv1.x += scanOffset;
uv2.x += scanOffset;
}
float r = texture(iChannel0, uv1).r;
float g = texture(iChannel0, uv).g;
float b = texture(iChannel0, uv2).b;
fragColor = vec4(r, g, b, 1.);
}
产生:
将OpenGL 代码转换为Metal 后,我使用CIFilter 包装器将其与AVPlayerItem 一起使用:
class MetalFilter: CIFilter {
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private let kernel: CIKernel
var inputImage: CIImage?
override init() {
let url = Bundle.main.url(forResource: "default", withExtension: "metallib")!
let data = try! Data(contentsOf: url)
kernel = try! CIKernel(functionName: "vhs", fromMetalLibraryData: data)
super.init()
}
func outputImage() -> CIImage? {
guard let inputImage = inputImage else {return nil}
let sourceSize = inputImage.extent.size
let outputImage = kernel.apply(extent: CGRect(x: 0, y: 0, width: sourceSize.width, height: sourceSize.height), roiCallback: { index, destRect in
return destRect
}, arguments: [inputImage, NSNumber(value: Float(1.0 / sourceSize.width)), NSNumber(value: Float(1.0 / sourceSize.height)), NSNumber(value: 60.0)])
return outputImage
}
}
任何帮助将不胜感激!
【问题讨论】:
-
到目前为止,您的
MetalFilter实现似乎还可以。你在纠结什么? -
@FrankSchlegel 嘿,弗兰克,感谢您的回复。我试图了解如何将 OpenGL 过滤器代码转换为 Metal(filename.metal 文件)。是否有关于如何执行此操作的指南?
标签: swift opengl shader metal cifilter