У меня есть плоскость SceneKit, которой назначен шейдер:
let scnNode = SCNNode()
let geom_plane = SCNPlane(width: 10.0, height: 10.0)
scnNode.geometry = geom_plane
Этой геометрии присваивается материал на основе шейдера.
Я создаю CIFilter и применяю его:
let bloomFilter = CIFilter(name:"CIBloom")!
bloomFilter.setValue(10.0, forKey: "inputIntensity")
bloomFilter.setValue(4.0, forKey: "inputRadius")
scnNode.filters = [bloomFilter]
Это приводит к тому, что материал на основе геометрии шейдера расцветает, как и должно быть.Обратите внимание, что никогда не указывался inputImage, и фильтр, кажется, автоматически знает, как использовать содержимое шейдера.
Теперь я хочу заменить этот фильтр своим собственным пользовательским шейдером Metal Kernel.Единственная справка по фильтру Custom Metal Kernel, которую я нашел до сих пор, описывает, как сделать фильтр следующим образом:
import CoreImage
class ScreenBloomFilter: CIFilter {
private let kernel: CIColorKernel
var inputImage: CIImage?
override init() {
let url = Bundle.main.url(forResource: "default", withExtension: "metallib")!
let data = try! Data(contentsOf: url)
kernel = try! CIColorKernel(functionName: "myColor", 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 }
return kernel.apply(extent: inputImage.extent, arguments: [inputImage])
}
}
Я использую этот фильтр вместо старого фильтра Блума:
scnNode.filters = [ScreenBloomFilter()]
Но это приводит к тому, что материал на основе шедера остается пустым.Это явно связано с тем, что не указан inputImage и фильтр возвращает nil.Мой вопросКак заставить мой новый фильтр Metal Kernel работать так же, как оригинальный фильтр, так как он не требует указания явного inputImage и просто автоматически знает, как работать с шейдером материала?