【问题标题】:Metal only draws to a portion of the view and inquiry about layersMetal仅绘制视图的一部分并查询图层
【发布时间】:2018-06-02 18:41:33
【问题描述】:

我正在按照基本金属教程的设置,并尝试渲染一个统一颜色的空白屏幕。

由于某种原因,我遇到了 Metal 仅绘制到屏幕的一部分的问题。

我设置了一个单视图应用程序并将 MainStoryboard 的视图附加到我正在创建的类中。我将其背景颜色设置为绿色。

这是课程

class MBEMetalView: UIView {

    var device:MTLDevice?
    var MTLLayer:CAMetalLayer?

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        device = MTLCreateSystemDefaultDevice()

        //The book said to cast the layer to a CAMetalLayer 
        //but that causes a crash in the redraw method because
        //failed assertion `No rendertargets set in RenderPassDescriptor.'
        //So we do this.. which might be wasteful?
        MTLLayer = CAMetalLayer()
        MTLLayer?.device = device
        MTLLayer?.pixelFormat = MTLPixelFormat.bgra8Unorm
        MTLLayer?.framebufferOnly = true
        MTLLayer?.frame = frame
        layer.addSublayer(MTLLayer!)
    }

    override func didMoveToWindow() {
        redraw()
    }

    func redraw() {
        var drawable = MTLLayer?.nextDrawable()
        var texture = drawable?.texture

        var passDescriptor = MTLRenderPassDescriptor()
        passDescriptor.colorAttachments[0].texture = texture
        passDescriptor.colorAttachments[0].loadAction = MTLLoadAction.clear
        passDescriptor.colorAttachments[0].storeAction = MTLStoreAction.store
        passDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(0, 1, 0, 1)


        var commandQueue = device?.makeCommandQueue()
        var commandBuffer = commandQueue?.makeCommandBuffer()
        var commandEncoder = commandBuffer?.makeRenderCommandEncoder(descriptor: passDescriptor)
        commandEncoder?.endEncoding()

        if let drawOn = drawable {
            commandBuffer?.present(drawOn)
            commandBuffer?.commit()
        }
    }

}

该类应该将整个屏幕渲染为绿色,但事实并非如此,它只填充了 iPhone 6s plus 的这张图片所示的一部分(红色是视图的背景,而不是 Metal 正在绘制的内容)。

这个结果让人想起几个问题:

  1. 为什么 Metal 只渲染到屏幕的一部分
  2. 我正在关注的教程是在 Objective-C 中进行的,他们能够将继承的 UIView 的层转换为 CAMetal 层 而不是创建一个新层(这允许他们删除 .addSublayer 行)。但是,当我尝试这个时,我遇到了崩溃 在 cmets 中显示?这是为什么呢?
  3. 像 iPhone X 这样具有安全区域的设备会如何影响传入的帧?我需要额外的东西来画吗 在安全区域之外?我在哪里可以得到保险箱的尺寸 以编程方式显示我视图框架中的区域(以防新设备 发布)

【问题讨论】:

    标签: ios swift metal


    【解决方案1】:

    您在init(coder) 中设置了CAMetalLayer 的框架并且从不更改它。但在init(coder) 中,最终的帧大小尚不清楚(它只是使用您此时在Interface Builder 中设置的任何大小,但还不是设备大小)。在didMoveToWindow() 中,还将金属层的框架设置为其最终大小。 (或者也许在layoutSubviews()。)

    【讨论】:

    • 感谢您的回答。您是否也可以尝试回答问题的第二和第三部分?您回答的问题中最重要的部分,但我仍有一些问题挥之不去
    • 我不知道第 3 部分的答案(还没有在 iPhone X 上使用 Metal 进行任何绘图)。对于第 2 部分,我需要查看导致问题的实际完整代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-06
    • 1970-01-01
    相关资源
    最近更新 更多