如何解决MTKView 透明度
我无法让我的 MTKView 清除背景。我已将视图及其图层的 isOpaque 设置为 false,将背景颜色设置为清除,并尝试了在 google/stackoverflow 上找到的多种解决方案(大部分在下面的代码中,如 loadAction 和颜色附件的 clearColor),但没有任何效果。
似乎忽略了所有背景颜色设置。设置 MTLRenderPassColorAttachmentDescriptor 的 loadAction 和 clearColor 没有任何作用。
我想在 MTKView 下绘制我的常规 UIView。我错过了什么?
// initialization
let Metal = MTKView(frame: self.view.bounds)
Metal.device = MTLCreateSystemDefaultDevice()
self.renderer = try! MetalRenderer(mtkView: Metal)
Metal.delegate = self.renderer
self.view.addSubview(Metal);
import Foundation
import MetalKit
import simd
public enum MetalError: Error {
case mtkViewError
case renderError
}
internal class MetalRenderer: NSObject,MTKViewDelegate {
private let commandQueue: MTLCommandQueue;
private let pipelinestate: MTLRenderPipelinestate
private var viewportSize: SIMD2<UInt32> = SIMD2(x: 10,y: 10);
private weak var mtkView: MTKView?
init(mtkView: MTKView) throws {
guard let device = mtkView.device else {
print("device not found error")
throw MetalError.mtkViewError
}
self.mtkView = mtkView
// Load all the shader files with a .Metal file extension in the project.
guard let defaultLibrary = device.makeDefaultLibrary() else {
print("Could not find library")
throw MetalError.mtkViewError
}
let vertexFunction = defaultLibrary.makeFunction(name: "vertexShader")
let fragmentFunction = defaultLibrary.makeFunction(name: "fragmentShader")
mtkView.layer.isOpaque = false;
mtkView.layer.backgroundColor = UIColor.clear.cgColor
mtkView.isOpaque = false;
mtkView.backgroundColor = .clear
let pipelinestateDescriptor = MTLRenderPipelineDescriptor();
pipelinestateDescriptor.label = "Pipeline";
pipelinestateDescriptor.vertexFunction = vertexFunction;
pipelinestateDescriptor.fragmentFunction = fragmentFunction;
pipelinestateDescriptor.isAlphaToCoverageEnabled = true
pipelinestateDescriptor.colorAttachments[0].pixelFormat = .bgra8Unorm;
pipelinestateDescriptor.colorAttachments[0].isBlendingEnabled = true;
pipelinestateDescriptor.colorAttachments[0].destinationRGBBlendFactor = .oneMinusSourceAlpha;
pipelinestateDescriptor.colorAttachments[0].destinationAlphaBlendFactor = .oneMinusSourceAlpha;
pipelinestate = try! device.makeRenderPipelinestate(descriptor: pipelinestateDescriptor);
guard let queue = device.makeCommandQueue() else {
print("make command queue error")
throw MetalError.mtkViewError
}
commandQueue = queue
}
func mtkView(_ view: MTKView,drawableSizeWillChange size: CGSize) {
viewportSize.x = UInt32(size.width)
viewportSize.y = UInt32(size.height)
}
func draw(in view: MTKView) {
let vertices: [Vertex] = [
Vertex(position: SIMD3<Float>(x: 250.0,y: -250.0,z: 0)),Vertex(position: SIMD3<Float>(x: -250.0,Vertex(position: SIMD3<Float>(x: 0.0,y: 250.0,]
guard let commandBuffer = commandQueue.makeCommandBuffer() else {
print("Couldn't create command buffer")
return
}
// Create a new command buffer for each render pass to the current drawable.
commandBuffer.label = "MyCommand";
// Obtain a renderPassDescriptor generated from the view's drawable textures.
guard let renderPassDescriptor = view.currentRenderPassDescriptor else {
print("Couldn't create render pass descriptor")
return
}
guard let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor) else {
print("Couldn't create render encoder")
return
}
renderPassDescriptor.colorAttachments[0].loadAction = .clear
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(1.0,0.0,0.5)
renderEncoder.label = "MyRenderEncoder";
// Set the region of the drawable to draw into.
renderEncoder.setViewport(MTLViewport(originX: 0.0,originY: 0.0,width: Double(viewportSize.x),height: Double(viewportSize.y),znear: 0.0,zfar: 1.0))
renderEncoder.setRenderPipelinestate(pipelinestate)
// Pass in the parameter data.
renderEncoder.setVertexBytes(vertices,length: MemoryLayout<Vertex>.size * vertices.count,index: Int(VertexInputIndexVertices.rawValue))
renderEncoder.setVertexBytes(&viewportSize,length: MemoryLayout<SIMD2<UInt32>>.size,index: Int(VertexInputIndexViewportSize.rawValue))
renderEncoder.drawPrimitives(type: MTLPrimitiveType.triangle,vertexStart: 0,vertexCount: 3)
renderEncoder.endEncoding()
// Schedule a present once the framebuffer is complete using the current drawable.
guard let drawable = view.currentDrawable else {
print("Couldn't get current drawable")
return
}
commandBuffer.present(drawable)
// Finalize rendering here & push the command buffer to the GPU.
commandBuffer.commit()
}
}
解决方法
感谢 Frank,答案是设置视图本身的 clearColor 属性,我错过了。我还删除了 MTLRenderPipelineDescriptor 中的大部分调整,现在谁的代码是:
let pipelineStateDescriptor = MTLRenderPipelineDescriptor();
pipelineStateDescriptor.label = "Pipeline";
pipelineStateDescriptor.vertexFunction = vertexFunction;
pipelineStateDescriptor.fragmentFunction = fragmentFunction;
pipelineStateDescriptor.colorAttachments[0].pixelFormat =
mtkView.colorPixelFormat;
也无需从 currentRenderPassDescriptor 更改 MTLRenderPassDescriptor。
EDIT: 还要确保将 MTKView 的 isOpaque 属性也设置为 false。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。