0

我只需要渲染二维文本,但我发现的示例(MetalByExample.com 的文本渲染)是在 Objective-C 中的,非常混乱,并且可能有很多垃圾(完整功能不需要的代码或步骤)。我应该如何在 Metal 中渲染简单的文本?这在 SwiftUI 中是微不足道的,但我如何在 Metal 中做到这一点?我知道这个问题有点含糊,但是关于如何在 Metal 中呈现简单文本的有用资源很少。给定这个起始代码,我怎么能渲染一个简单的 hello world 文本?

import Cocoa
import MetalKit
class ViewController: NSViewController {
    private let Device = MTLCreateSystemDefaultDevice()!
    private var CommandQue: MTLCommandQueue!, Pipeline: MTLRenderPipelineState!
    private var View: MTKView {
        return view as! MTKView
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        View.delegate = self
        View.device = Device
        CommandQue = Device.makeCommandQueue()
        let PipelineDescriptor = MTLRenderPipelineDescriptor()
        let Library = Device.makeDefaultLibrary()!
        PipelineDescriptor.vertexFunction = Library.makeFunction(name: "V")
        PipelineDescriptor.fragmentFunction = Library.makeFunction(name: "T")
        Pipeline = try? Device.makeRenderPipelineState(descriptor: PipelineDescriptor)
    }
}
extension ViewController: MTKViewDelegate {
    func mtkView(_ _: MTKView, drawableSizeWillChange Size: CGSize) {
        View.draw()
    }
    func draw(in _: MTKView) {
        let CommandBuffer = CommandQue.makeCommandBuffer()!, CommandEncoder = CommandBuffer.makeRenderCommandEncoder(descriptor: View.currentRenderPassDescriptor!)!
        CommandEncoder.setRenderPipelineState(Pipeline!)
        
        // Render
        
        CommandEncoder.endEncoding()
        CommandBuffer.present(View.currentDrawable!)
        CommandBuffer.commit()
    }
}

基本上我怎么能在 Metal 中复制这个简单的 SwiftUI?我不是要“为我编写此代码”,但我想要一些关于从哪里开始的指示?

struct ContentView: View {
    var body: some View {
        Text("Hello, World!")
    }
}
4

2 回答 2

2

您可以为此使用 Core Image CITextImageGenerator。(也有CIAttributedTextImageGenerator属性文本。)

只需创建CIImage包含文本的 a 并使用 aCIContext将文本渲染为 a MTLTexture(或直接渲染到视图中):

// Render
let textImage = CIFilter(name: "CITextImageGenerator", parameters: [
    "inputText": "Hello World!",
    "inputFontName": "HelveticaNeue",
    "inputFontSize": 40,
    "inputScaleFactor": 2.0
]).outputImage!

// Note: create the CIContext once and re-use it
self.ciContext.render(textImage, to: View.currentDrawable!, commandBuffer: CommandBuffer, bounds: textImage.extent colorSpace: CGColorSpaceCreateDeviceRGB())

从 macOS 10.15 开始,您还可以import CoreImage.CIFilterBuiltins使用新的基于协议的 Core Image 接口:

let textImageGenerator = CIFilter.textImageGenerator()
textImageGenerator.text = "Hello World!"
// ...
let textImage = textImageGenerator.outputImage!

如果你想改变文本的颜色,你可以使用CIAttributedTextImageGenerator属性字符串或使用更多的核心图像过滤器和混合技术来着色文本图像,然后再将其渲染到视图中。

于 2020-12-02T07:10:48.433 回答
0

我花了两天时间寻找最简单的实现,所以对我来说最好的是使用 Alloy pod并将 UILabel 转换为 cgImage

func createImage() -> UIImage {
            UIGraphicsBeginImageContextWithOptions(
                CGSize(width: self.frame.width, height: self.frame.height), true, 1)
            self.layer.render(in: UIGraphicsGetCurrentContext()!)
            let image = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            return image!
        }

然后到 mtltexture

context = try! MTLContext(device: Device.shared.device)

let texture = try! context.texture(from: cgImage!,
                                            srgb: false,
                                           usage: [.shaderRead, .shaderWrite])
于 2021-09-03T00:46:31.027 回答