MTKView总是将背景颜色渲染为红色。

3

我想在Mac应用程序中使用MTKView。在初始化MTKView之后,它在我的MacBook Pro上出现了红色,而不是预期的清晰颜色,并且在macOS Mojave 10.14.6的iMac上呈现黑色背景。

我尝试将metalView的pixelFormat(MTLPixelFormat.bgra8Unorm)更改为MTLPixelFormat.rgba16Float或其他格式,但背景颜色仍然不正确。

MTLTexture创建函数为MTLTextureDescriptor.texture2DDescriptor(pixelFormat:metalView.colorPixelFormat, width: Int(metalView.frame.size.width), height: Int(metalView.frame.size.height), mipmapped: false)

这可能与.metal文件有关,但我不理解它。

我已经将项目发布到Github。这里


import Cocoa
import MetalKit
import simd

struct Vertex {
    var position: vector_float4
    var textCoord: vector_float2

    init(position: CGPoint, textCoord: CGPoint) {
        self.position = [Float(position.x), Float(position.y), 0 ,1]
        self.textCoord = [Float(textCoord.x), Float(textCoord.y)]
    }
}

class Matrix {

    private(set) var m: [Float]

    static var identity = Matrix()

    private init() {
        m = [1, 0, 0, 0,
             0, 1, 0, 0,
             0, 0, 1, 0,
             0, 0, 0, 1
        ]
    }

    @discardableResult
    func translation(x: Float, y: Float, z: Float) -> Matrix {
        m[12] = x
        m[13] = y
        m[14] = z
        return self
    }

    @discardableResult
    func scaling(x: Float, y: Float, z: Float)  -> Matrix  {
        m[0] = x
        m[5] = y
        m[10] = z
        return self
    }
}

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate, MTKViewDelegate {

    @IBOutlet weak var window: NSWindow!

    @IBOutlet weak var metalView: MTKView!

    private var commandQueue: MTLCommandQueue?

    private var pipelineState: MTLRenderPipelineState!
    private var render_target_vertex: MTLBuffer!
    private var render_target_uniform: MTLBuffer!

    func applicationDidFinishLaunching(_ aNotification: Notification) {
        // Insert code here to initialize your application

        metalView.device = MTLCreateSystemDefaultDevice()
        metalView.delegate = self

        commandQueue = metalView.device?.makeCommandQueue()

        setupTargetUniforms()

        do {
            try setupPiplineState()
        } catch {
            fatalError("Metal initialize failed: \(error.localizedDescription)")
        }
    }

    private func setupTargetUniforms() {
        let size = metalView.frame.size
        let w = size.width, h = size.height
        let vertices = [
            Vertex(position: CGPoint(x: 0 , y: 0), textCoord: CGPoint(x: 0, y: 0)),
            Vertex(position: CGPoint(x: w , y: 0), textCoord: CGPoint(x: 1, y: 0)),
            Vertex(position: CGPoint(x: 0 , y: h), textCoord: CGPoint(x: 0, y: 1)),
            Vertex(position: CGPoint(x: w , y: h), textCoord: CGPoint(x: 1, y: 1)),
        ]
        render_target_vertex = metalView.device?.makeBuffer(bytes: vertices, length: MemoryLayout<Vertex>.stride * vertices.count, options: .cpuCacheModeWriteCombined)

        let metrix = Matrix.identity
        metrix.scaling(x: 2 / Float(size.width), y: -2 / Float(size.height), z: 1)
        metrix.translation(x: -1, y: 1, z: 0)
        render_target_uniform = metalView.device?.makeBuffer(bytes: metrix.m, length: MemoryLayout<Float>.size * 16, options: [])
    }

    private func setupPiplineState() throws {

        let library = try metalView.device?.makeDefaultLibrary(bundle: Bundle.main)
        let vertex_func = library?.makeFunction(name: "vertex_render_target")
        let fragment_func = library?.makeFunction(name: "fragment_render_target")
        let rpd = MTLRenderPipelineDescriptor()
        rpd.vertexFunction = vertex_func
        rpd.fragmentFunction = fragment_func
        rpd.colorAttachments[0].pixelFormat = metalView.colorPixelFormat
        //        rpd.colorAttachments[0].isBlendingEnabled = true
        //        rpd.colorAttachments[0].alphaBlendOperation = .add
        //        rpd.colorAttachments[0].rgbBlendOperation = .add
        //        rpd.colorAttachments[0].sourceRGBBlendFactor = .sourceAlpha
        //        rpd.colorAttachments[0].sourceAlphaBlendFactor = .one
        //        rpd.colorAttachments[0].destinationRGBBlendFactor = .oneMinusSourceAlpha
        //        rpd.colorAttachments[0].destinationAlphaBlendFactor = .oneMinusSourceAlpha
        pipelineState = try metalView.device?.makeRenderPipelineState(descriptor: rpd)
    }

    func applicationWillTerminate(_ aNotification: Notification) {
        // Insert code here to tear down your application
    }

    func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {


    }

    func draw(in view: MTKView) {
        let renderPassDescriptor = MTLRenderPassDescriptor()
        let attachment = renderPassDescriptor.colorAttachments[0]
        attachment?.clearColor = metalView.clearColor
        attachment?.texture = metalView.currentDrawable?.texture
        attachment?.loadAction = .clear
        attachment?.storeAction = .store

        let commandBuffer = commandQueue?.makeCommandBuffer()

        let commandEncoder = commandBuffer?.makeRenderCommandEncoder(descriptor: renderPassDescriptor)

        commandEncoder?.setRenderPipelineState(pipelineState)

        commandEncoder?.setVertexBuffer(render_target_vertex, offset: 0, index: 0)
        commandEncoder?.setVertexBuffer(render_target_uniform, offset: 0, index: 1)

        let textureDescriptor = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: metalView.colorPixelFormat,
                                                                         width: Int(metalView.frame.size.width),
                                                                         height: Int(metalView.frame.size.height),
                                                                         mipmapped: false)
        textureDescriptor.usage = [.renderTarget, .shaderRead]
        let texture = metalView.device?.makeTexture(descriptor: textureDescriptor)
        commandEncoder?.setFragmentTexture(texture, index: 0)
        commandEncoder?.drawPrimitives(type: .triangleStrip, vertexStart: 0, vertexCount: 4)

        commandEncoder?.endEncoding()
        if let drawable = metalView.currentDrawable {
            commandBuffer?.present(drawable)
        }
        commandBuffer?.commit()
    }
}




请问有谁能帮我找到问题吗?

this is the window always like

1个回答

6

你正在对一个未初始化的纹理进行采样。

在你的的方法中,你绑定了从变量获取的纹理,而该纹理尚未被渲染过。

当创建一个Metal纹理时,它的内容是未定义的。它们可能是红色、黑色、随机噪声或其他任何东西。


在同一個專案中,另一個名為 MTKViewRed 的目標,我已經刪除了所有額外的程式碼。你能幫我修復這個問題嗎? - guojing
我真的不知道还能说什么。你正在创建一个纹理,其内容是未定义的,然后立即对其进行采样。因此,所得图像的内容也是未定义的,正如答案中所描述的那样。也许您可以告诉我们更多关于您预期的结果,因为我看到的一切都符合我的预期。 - warrenm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接