如何为渲染到纹理iOS应用启用MSAA

时间:2018-11-27 02:23:45

标签: swift metal fragment-shader metalkit msaa

我有一个可以渲染的纹理,可以使玩具iOS应用程序纹理化。问题是它有很多锯齿,因为它是点采样且没有抗锯齿:

enter image description here

我将MTKView子类中的样本数增加到4以启用MSAA。

这是相关代码的样子。

// render to texture render pass descriptor
renderPassDesc = MTLRenderPassDescriptor()
renderPassDesc.EI_configure(clearColor: MTLClearColorMake(1, 1, 1, 1), clearDepth: 1)

// my MTLRenderPassDescriptor extension convenience method
public func EI_configure(clearColor:MTLClearColor, clearDepth: Double) {

    // color
    colorAttachments[ 0 ] = MTLRenderPassColorAttachmentDescriptor()
    colorAttachments[ 0 ].storeAction = .store
    colorAttachments[ 0 ].loadAction = .clear
    colorAttachments[ 0 ].clearColor = clearColor

    // depth
    depthAttachment = MTLRenderPassDepthAttachmentDescriptor()
    depthAttachment.storeAction = .dontCare
    depthAttachment.loadAction = .clear
    depthAttachment.clearDepth = clearDepth;

}

我将为MSAA配置的颜色和深度缓冲区附加到renderPassDesc

// color
let colorDesc = MTLTextureDescriptor.texture2DDescriptor(pixelFormat:view.colorPixelFormat, width:Int(view.bounds.size.width), height:Int(view.bounds.size.height), mipmapped:false)
colorDesc.mipmapLevelCount = 1;
colorDesc.textureType = .type2DMultisample
colorDesc.sampleCount = view.sampleCount
colorDesc.usage = [.renderTarget, .shaderRead]
renderPassDesc.colorAttachments[ 0 ].texture = view.device!.makeTexture(descriptor:colorDesc)

// depth
let depthDesc = MTLTextureDescriptor.texture2DDescriptor(pixelFormat:.depth32Float, width:Int(view.bounds.size.width), height:Int(view.bounds.size.height), mipmapped:false)
depthDesc.mipmapLevelCount = 1;
depthDesc.textureType = .type2DMultisample
depthDesc.sampleCount = view.sampleCount
depthDesc.usage = .renderTarget
renderPassDesc.depthAttachment.texture = view.device!.makeTexture(descriptor:depthDesc)

在我的绘制循环中,我从片段着色器中获取了以下错误,该着色器消耗了渲染到的纹理:

失败的断言片段功能(finalPassOverlayFragmentShader): MTLTextureType2DMultisample的索引0(预期MTLTextureType2D)的纹理绑定处绑定的纹理类型(underlay[0])不正确

这是片段着色器:

fragment float4 finalPassOverlayFragmentShader(InterpolatedVertex vert [[ stage_in ]],
                                               texture2d<float> underlay [[ texture(0) ]],
                                               texture2d<float> overlay [[ texture(1) ]]) {

    constexpr sampler defaultSampler;

    float4 _F = overlay.sample(defaultSampler, vert.st).rgba;

    float4 _B = underlay.sample(defaultSampler, vert.st).rgba;

    float4 rgba = _F + (1.0f - _F.a) * _B;

    return rgba;
}

我确定我错过了某个地方的设置,但是找不到。

我在这里错过了什么?

更新0

现在我的2次通过玩具发生了MSAA。唯一的问题是没有太多的抗锯齿事件。实际上,很难说一切都已改变。这是我的最新设置

// color - multi-sampled texture target
let desc = MTLTextureDescriptor.texture2DDescriptor(pixelFormat:format, width:w, height:h, mipmapped:false)
desc.mipmapLevelCount = 1;
desc.textureType = .type2DMultisample
desc.sampleCount = view.sampleCount
desc.usage = .renderTarget
let tex:MTLTexture? = view.device!.makeTexture(descriptor:desc)

// color - point-sampled resolve-texture
let resolveDesc = MTLTextureDescriptor.texture2DDescriptor(pixelFormat:format, width:w, height:h, mipmapped:true)
let resolveTex:MTLTexture? = view.device!.makeTexture(descriptor:resolveDesc)

// depth texture target
let depthDesc = MTLTextureDescriptor.texture2DDescriptor(pixelFormat:.format, width:w, height:h, mipmapped:false)
depthDesc.mipmapLevelCount = 1;
depthDesc.textureType = .type2DMultisample
depthDesc.sampleCount = view.sampleCount
depthDesc.usage = .renderTarget
let depthTex:MTLTexture? = view.device!.makeTexture(descriptor:depthDesc)

// render pass descriptor
renderPassDesc = MTLRenderPassDescriptor()
// color
renderPassDesc.colorAttachments[ 0 ] = MTLRenderPassColorAttachmentDescriptor()
renderPassDesc.colorAttachments[ 0 ].storeAction = .storeAndMultisampleResolve
renderPassDesc.colorAttachments[ 0 ].loadAction = .clear
renderPassDesc.colorAttachments[ 0 ].clearColor = MTLClearColorMake(0.25, 0.25, 0.25, 1)
renderPassDesc.colorAttachments[ 0 ].texture = tex
renderPassDesc.colorAttachments[ 0 ].resolveTexture = resolveTex
// depth
renderPassDesc.depthAttachment = MTLRenderPassDepthAttachmentDescriptor()
renderPassDesc.depthAttachment.storeAction = .dontCare
renderPassDesc.depthAttachment.loadAction = .clear
renderPassDesc.depthAttachment.clearDepth = 1;
renderPassDesc.depthAttachment.texture = depthTex

更新1

锯齿似乎是从渲染到纹理,而不是在资产中。以下是并排比较。 顶部图像是通过启用MSAA的单次渲染来渲染的。 底部图像将渲染为纹理。锯齿在底部图像中清晰可见

单程 enter image description here

2次通过 enter image description here

1 个答案:

答案 0 :(得分:1)

该错误与您的渲染目标(也就是颜色和深度附件)无关。这与您要通过渲染命令编码器的片段纹理表传入的纹理有关,即您在调用setFragmentTexture(_:index:)的位置。当将着色器编码为期望.type2DMultisample时,您为索引0传递的是.type2D,因为您已将underlay声明为texture2d<...>

您的MSAA设置可以正常进行。您最终将需要将纹理解析为非多重采样纹理,以便将其绘制到屏幕上。对于该步骤(可能是此渲染命令编码器或更高版本,具体取决于您的需要),您需要将颜色附件的storeAction设置为.multisampleResolve.storeAndMultisampleResolve 。并且您需要将resolveTexture设置为2D纹理。那可能是您自己的图像或可绘制的纹理。