mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-08 08:31:13 +00:00
63 lines
2.3 KiB
Swift
63 lines
2.3 KiB
Swift
import Foundation
|
|
import Metal
|
|
import simd
|
|
import CoreImage
|
|
|
|
final class StickerOutlineRenderPass: RenderPass {
|
|
var value: simd_float1 = 0.0
|
|
|
|
var context: CIContext?
|
|
var maskFilter: CIFilter?
|
|
|
|
private var outputTexture: MTLTexture?
|
|
|
|
func setup(device: MTLDevice, library: MTLLibrary) {
|
|
self.context = CIContext(mtlDevice: device, options: [.workingColorSpace : CGColorSpaceCreateDeviceRGB()])
|
|
}
|
|
|
|
func process(input: MTLTexture, device: MTLDevice, commandBuffer: MTLCommandBuffer) -> MTLTexture? {
|
|
guard self.value > 0.005, let context = self.context else {
|
|
return input
|
|
}
|
|
|
|
if self.maskFilter == nil {
|
|
self.maskFilter = CIFilter(name: "CIMorphologyMaximum")
|
|
}
|
|
if self.outputTexture == nil {
|
|
let textureDescriptor = MTLTextureDescriptor()
|
|
textureDescriptor.textureType = .type2D
|
|
textureDescriptor.width = input.width
|
|
textureDescriptor.height = input.height
|
|
textureDescriptor.pixelFormat = input.pixelFormat
|
|
textureDescriptor.storageMode = .private
|
|
textureDescriptor.usage = [.shaderRead, .shaderWrite, .renderTarget]
|
|
guard let texture = device.makeTexture(descriptor: textureDescriptor) else {
|
|
return nil
|
|
}
|
|
self.outputTexture = texture
|
|
texture.label = "outlineOutputTexture"
|
|
}
|
|
guard let maskFilter = self.maskFilter, let image = CIImage(mtlTexture: input) else {
|
|
return input
|
|
}
|
|
|
|
maskFilter.setValue(self.value * 30, forKey: kCIInputRadiusKey)
|
|
maskFilter.setValue(image, forKey: kCIInputImageKey)
|
|
|
|
guard let eroded = maskFilter.outputImage, let outputTexture = self.outputTexture else {
|
|
return input
|
|
}
|
|
|
|
if #available(iOS 13.0, *) {
|
|
let colorized = CIBlendKernel.sourceAtop.apply(foreground: .white, background: eroded)!.cropped(to: eroded.extent)
|
|
let resultImage = image.composited(over: colorized)
|
|
|
|
let renderDestination = CIRenderDestination(mtlTexture: outputTexture, commandBuffer: commandBuffer)
|
|
_ = try? context.startTask(toRender: resultImage, to: renderDestination)
|
|
return outputTexture
|
|
} else {
|
|
return input
|
|
}
|
|
}
|
|
}
|