【问题标题】:How Do I Enable MSAA for a Render to Texture iOS App如何为渲染到纹理 iOS 应用启用 MSAA
【发布时间】:2019-04-28 17:34:49
【问题描述】:

我有一个工作渲染到纹理玩具 iOS 应用程序。问题是它有很多锯齿,因为它是点采样而不是抗锯齿的:

我将 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-pass 玩具正在发生 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

锯齿似乎来自渲染到纹理,而不是资产中。下面是并排比较。 top 图像使用启用 MSAA 的单通道渲染。 底部 图像被渲染为纹理。锯齿在底部图像中清晰可见

单程

2-pass

【问题讨论】:

  • 关于您的更新,您现在是否使用resolveTex 而不是texfinalPassOverlayFragmentShader 进行合成通道?
  • 是的。创建解析纹理修复了该错误。但是我看不到抗锯齿。所以要澄清。为渲染到纹理步骤启用了 MS。我使用该纹理作为背景,在其上合成一个半透明的纹理。我看到在渲染到纹理步骤中渲染的纹理中出现锯齿。复合材料很好。
  • 实际上,有轻微的抗锯齿发生。但是,当我在非渲染到纹理示例中使用多重采样时,我看到的 AA 完全不同。很奇怪。
  • 你确定锯齿不在你的渲染到纹理通道的输入中,而不是它的结果吗?

标签: swift metal fragment-shader metalkit msaa


【解决方案1】:

错误与您的渲染目标无关(也就是颜色和深度附件)。它是关于您通过渲染命令编码器的片段纹理表传入的纹理——也就是说,您在其中调用setFragmentTexture(_:index:)。当着色器被编码为期望.type2D 时,您为索引0 传递的那个是.type2DMultisample,因为您将underlay 声明为texture2d&lt;...&gt;

您的 MSAA 设置可以用于中间步骤。您最终需要将纹理解析为非多重采样纹理才能将其绘制到屏幕上。对于该步骤(可能用于此渲染命令编码器或更高版本,取决于您的需要),您需要将颜色附件的storeAction 设置为.multisampleResolve.storeAndMultisampleResolve。您需要将resolveTexture 设置为2D 纹理。这可能是您自己的纹理之一或可绘制的纹理。

【讨论】:

  • 非常感谢肯。让我试着解开你的答案。 1)我的碎片着色器中允许使用多样本与当前点采样纹理的正确语法是什么。 2)我的渲染到纹理传递导致纹理(定义为多样本)。我的玩具应用程序采用多样本纹理和叠加纹理,并将它们合成到上面显示的片段着色器中。超级简单。 3)我不完全了解resolve纹理的作用,您能否详细说明并区分.multisampleResolve和.storeAndMultisampleResolve?你能指点我这方面的相关文档吗?
  • 我在文档中做了更多的挖掘工作。关于解析纹理和存储操作的使用。如果我将颜色附件存储操作设置为 .storeAndMultisampleResolve 我为解析纹理设置什么存储操作?
  • 您可以将underlay 声明为texture2d_ms&lt;float&gt;,但您只能从中获得read(),而不是sample()。您究竟希望合成如何工作?在我看来,您似乎希望在合成步骤之前解决抗锯齿,所以您会想要这样做。多重采样只是一个中间步骤。 MS 纹理的每个 texcoord 有多个值(样本),但最终您需要一个值,例如在绘制到屏幕时。解析是从多个值中生成单个值。
  • .multisampleResolve 将解析后的数据存储在resolveTexture 中,否则会丢弃 MS 纹理的数据。 .storeAndMultisampleResolve 都解析为 resolveTexture 并将数据存储在 MS 纹理中。只有在解决后需要对其执行其他操作时,您才会这样做。如果您还没有,请查看Metal Programming Guide。它已“存档”但仍然相关。请参阅图形渲染和新增功能页面。
  • 我解决了锯齿问题。我忘了使用 UIScreen.main.scale 来放大我的渲染目标。 AA 正在发生。甜蜜。
猜你喜欢
  • 1970-01-01
  • 2016-12-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-23
相关资源
最近更新 更多