【问题标题】:How should I go about rendering text in Metal?我应该如何在 Metal 中渲染文本?
【发布时间】:2020-12-02 00:14:56
【问题描述】:

我只需要渲染二维文本,但我发现的示例(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!")
    }
}

【问题讨论】:

    标签: swift text rendering metal


    【解决方案1】:

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

    只需创建一个包含文本的CIImage 并使用CIContext 将文本呈现为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,或者使用更多的核心图像过滤器和混合技术在将文本图像渲染到视图之前对其进行着色。

    【讨论】:

    • 在这种情况下self 指的是什么?
    • 例如视图控制器。可以包含对您用于将文本呈现到视图中的CIContext 的引用。您可以使用self.ciContext = CIContext()init 上创建上下文本身。
    • 我明白了,但 render 不接受 View.currentDrawable! 因为它必须是 MTLTexture 但如果我接受 View.currentDrawable!.texture 它不起作用,因为它只是帧缓冲区跨度>
    • 对不起,我忘了。您可以在viewDidLoad() 中设置View.framebufferOnly = false
    • 我如何改变颜色,另外有没有办法在没有所有字符串文字的情况下做到这一点?
    【解决方案2】:

    我花了两天时间寻找最简单的实现,所以对我来说最好的是使用 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])
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-09-25
      • 2018-12-30
      • 1970-01-01
      • 2010-10-21
      • 2020-12-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多