如何查看系统CIFilter默认实现及自定义MSL过渡滤镜问题排查
自定义CIFilter过渡滤镜开发问题排查
更新:根据@FrankSchlegel的回复,核心问题结论:无法查看系统原生CIFilter的内部实现逻辑。
我想知道是否可以查看部分默认CIFilter的实现,比如CIDissolveTransition、CISwipeTransition这类过渡滤镜?我需要开发自定义过渡滤镜,想尽可能参考一些Metal Shading Language的实现示例,但目前网上只能找到普通Metal管线的过渡滤镜实现,找不到基于MSL的相关示例。
更新1:淡入淡出滤镜代码移植问题
以下是我想要移植到MSL的淡入淡出滤镜示例代码:
#include <metal_stdlib> using namespace metal; #include "../../Vender/Render/Base/OperationShaderTypes.h" struct TwoInputVertexIO { float4 position [[position]]; float2 textureCoordinate [[user(texturecoord)]]; float2 textureCoordinate2 [[user(texturecoord2)]]; }; typedef struct { float tweenFactor; } FadeTransitionUniform; fragment half4 fadeTransition(TwoInputVertexIO fragmentInput [[stage_in]], texture2d<half> inputTexture [[texture(0)]], texture2d<half> inputTexture2 [[texture(1)]], constant FadeTransitionUniform& uniform [[ buffer(1) ]]) { constexpr sampler quadSampler; half4 textureColor = inputTexture.sample(quadSampler, fragmentInput.textureCoordinate); half4 textureColor2 = inputTexture2.sample(quadSampler, fragmentInput.textureCoordinate2); return half4(mix(textureColor.rgb, textureColor2.rgb, textureColor2.a * half(uniform.tweenFactor)), textureColor.a); }
以下是我移植失败的代码版本:
float4 fadeTransition(sampler fromTexture, sampler toTexture, float time) { float2 uv = fromTexture.coord(); float4 textureColor = fromTexture.sample(uv); float4 textureColor2 = toTexture.sample(uv); return float4(mix(textureColor.rgb, textureColor2.rgb, textureColor2.a * float(time)), textureColor.a); }
目前这段代码没有任何效果,我猜测是没有添加constexpr sampler quadSampler对应的等效逻辑导致的。
更新2:CIKernel相关代码
以下是我初始化CIKernel的代码:
import CoreImage class TestTransitionFilter: CIFilter { private let kernel: CIKernel @objc dynamic var inputImage: CIImage? @objc dynamic var inputImage2: CIImage? @objc dynamic var inputTime: CGFloat = 0 override init() { let url = Bundle.main.url(forResource: "default", withExtension: "metallib")! let data = try! Data(contentsOf: url) kernel = try! CIKernel(functionName: "fadeTransition", fromMetalLibraryData: data) super.init() } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } func outputImage() -> CIImage? { guard let inputImage = inputImage else {return nil} guard let inputImage2 = inputImage2 else {return nil} return kernel.apply(extent: inputImage.extent, roiCallback: { (index, rect) in return rect.insetBy(dx: -1, dy: -1) }, arguments: [inputImage, inputImage2, inputTime]) } }
以下是我调用该滤镜的代码:
public class TestTransition: NoneTransition { override public func renderImage(foregroundImage: CIImage, backgroundImage: CIImage, forTweenFactor tween: Float64, renderSize: CGSize) -> CIImage { // 这段代码可正常运行 /* if let crossDissolveFilter = CIFilter(name: "CIFlashTransition") { crossDissolveFilter.setValue(backgroundImage, forKey: "inputImage") crossDissolveFilter.setValue(CIVector(x: backgroundImage.extent.width / 2.0, y: backgroundImage.extent.height / 2.0), forKey: "inputCenter") crossDissolveFilter.setValue(foregroundImage, forKey: "inputTargetImage") crossDissolveFilter.setValue(tween, forKey: "inputTime") if let outputImage = crossDissolveFilter.outputImage { return outputImage } }*/ // 这段代码无效果 let filter = TestTransitionFilter() filter.inputImage = backgroundImage filter.inputImage2 = foregroundImage filter.inputTime = CGFloat(tween) if let outputImage = filter.outputImage { return outputImage } return super.renderImage(foregroundImage: foregroundImage, backgroundImage: backgroundImage, forTweenFactor: tween, renderSize: renderSize) } }
最终排查结果
最终更新:经过两天排查找到了问题的根本原因:调用CIKernel的位置写的是filter.outputImage,而不是filter.outputImage()。
内容的提问来源于stack exchange,提问作者SmartTree
相关产品推荐
相关产品推荐

