ios - Metal (iOS) 中的多重采样/锯齿状边缘

标签 ios swift metal

我目前正在尝试绘制一个图形,该图形将在 Swift 中使用 Metal 进行动画处理。我已经成功地绘制了我的图形的单个框架。图形很简单,正如您从这张图片中看到的那样。我想不通的是如何对绘图进行多重采样。一般而言,似乎很少有关于 Metal 的引用,尤其是在 Swift 语法方面。

self.metalLayer = CAMetalLayer()
self.metalLayer.device = self.device
self.metalLayer.pixelFormat = .BGRA8Unorm
self.metalLayer.framebufferOnly = true
self.metalLayer.frame = self.view.frame
self.view.layer.addSublayer(self.metalLayer)

self.renderer = SunRenderer(device: self.device, frame: self.view.frame)

let defaultLibrary = self.device.newDefaultLibrary()
let fragmentProgram = defaultLibrary!.newFunctionWithName("basic_fragment")
let vertexProgram = defaultLibrary!.newFunctionWithName("basic_vertex")

let pipelineStateDescriptor = MTLRenderPipelineDescriptor()
pipelineStateDescriptor.vertexFunction = vertexProgram
pipelineStateDescriptor.fragmentFunction = fragmentProgram
pipelineStateDescriptor.colorAttachments[0].pixelFormat = .BGRA8Unorm
pipelineStateDescriptor.colorAttachments[0].blendingEnabled = true

pipelineStateDescriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperation.Add
pipelineStateDescriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperation.Add
pipelineStateDescriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactor.SourceAlpha
pipelineStateDescriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactor.SourceAlpha
pipelineStateDescriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactor.OneMinusSourceAlpha
pipelineStateDescriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactor.OneMinusSourceAlpha

问题是,如何平滑这些边缘?

更新:

所以我实现了一个 MultiSample 纹理并将 sampleCount 设置为 4。我没有注意到任何差异,所以我怀疑我做错了什么。

最终:

所以,最终,多重采样确实有效。最初,我让顶点用 0 alpha 包裹这些“光线”。这是使边缘更平滑的技巧。对于这些顶点,多重采样似乎并没有改善边缘。当我恢复为每条射线有 4 个顶点时,多重采样改进了它们的边缘。

let defaultLibrary = self.device.newDefaultLibrary()
let fragmentProgram = defaultLibrary!.newFunctionWithName("basic_fragment")
let vertexProgram = defaultLibrary!.newFunctionWithName("basic_vertex")
        
let pipelineStateDescriptor = MTLRenderPipelineDescriptor()
pipelineStateDescriptor.vertexFunction = vertexProgram
pipelineStateDescriptor.fragmentFunction = fragmentProgram
pipelineStateDescriptor.colorAttachments[0].pixelFormat = .BGRA8Unorm
pipelineStateDescriptor.colorAttachments[0].blendingEnabled = true
pipelineStateDescriptor.sampleCount = 4
        
pipelineStateDescriptor.colorAttachments[0].rgbBlendOperation =    MTLBlendOperation.Add
pipelineStateDescriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperation.Add
pipelineStateDescriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactor.SourceAlpha
pipelineStateDescriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactor.SourceAlpha

pipelineStateDescriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactor.OneMinusSourceAlpha
pipelineStateDescriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactor.OneMinusSourceAlpha

let desc = MTLTextureDescriptor()
desc.textureType = MTLTextureType.Type2DMultisample
desc.width = Int(self.view.frame.width)
desc.height = Int(self.view.frame.height)
desc.sampleCount = 4
desc.pixelFormat = .BGRA8Unorm
        
self.sampletex = self.device.newTextureWithDescriptor(desc)


// When rendering
let renderPassDescriptor = MTLRenderPassDescriptor()
renderPassDescriptor.colorAttachments[0].texture = sampletex
renderPassDescriptor.colorAttachments[0].resolveTexture = drawable.texture
renderPassDescriptor.colorAttachments[0].loadAction = .Clear
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColor(red: 23/255.0, green: 26/255.0, blue: 31/255.0, alpha: 0.0)
renderPassDescriptor.colorAttachments[0].storeAction = .MultisampleResolve
    
    
let commandBuffer = commandQueue.commandBuffer()
    
let renderEncoder = commandBuffer.renderCommandEncoderWithDescriptor(renderPassDescriptor)
renderEncoder.setRenderPipelineState(pipelineState)

最佳答案

这在 MTKView 中要简单得多(只需将 sampleCount 设置为 View 和管道描述符上所需的 MSAA 样本数),但这里是滚动的步骤你自己的。

  1. 创建渲染管线状态时,将渲染管线状态描述符的 sampleCount 设置为多重采样计数。

  2. 在启动时以及图层调整大小时,通过创建其 textureTypeMTLTextureType2DMultisample 的纹理描述符,创建尺寸等于图层可绘制大小的多重采样纹理并且其 sampleCount 是您的多重样本计数。如果您使用的是深度和/或模板缓冲区,请同时在它们的描述符上设置这些属性。

  3. 渲染时,将 MSAA 纹理设置为渲染过程描述符的原色附件的 texture,并将当前 drawable 的纹理设置为 resolveTexture

  4. 将颜色附件的 storeAction 设置为 MTLStoreActionMultisampleResolve,以便在 channel 结束时将 MSAA 纹理解析到渲染缓冲区中。

  5. 像往常一样绘画和展示。

关于ios - Metal (iOS) 中的多重采样/锯齿状边缘,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36227209/

相关文章:

ios - 使用 NSKeyedUnarchiver unarchivedObject(ofClass :from:)) 取消归档数组

ios - Table View 窗外屏幕 iOS objective C

ios - 颜色作为 slider 位置的函数,用于设置颜色

objective-c - 整除后float为0

swift - 如果 LongPressReconizerState 结束,预定的计时器不会结束

ios - CLCircularRegion didEnterRegion 不起作用

swift - 空合并运算符的简写和可重新生成属性的赋值?

iOS Metal : casting half4 variable to float4 type

xcode - 目标的build设置中没有 "Metal Compiler"

ios - 使用 Metal 在 iOS 中扭曲 View