我想在Mac应用程序上使用MTKView。初始化MTKView后,在我的笔记本电脑上是macOS Catalina 10.15.2的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。 here
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()
}
}
有人可以帮我找到问题吗?
答案 0 :(得分:1)
您正在从未初始化的纹理采样。
在MetalView
的{{1}}方法中,您绑定了draw
变量的纹理,该变量从未渲染过。
创建“金属”纹理时,其内容未定义。它们可能是红色,黑色,随机噪音或其他任何东西。