mvc*_*vcs 4 stencil-buffer swift metal
这是我第一次尝试使用模板测试,但我见过一些使用 OpenGL 的示例和一些使用 Metal 的示例,但主要关注深度测试。我了解模板测试背后的理论,但我不知道如何在金属上设置它。
我想画不规则的形状。为了简单起见,让我们考虑以下 2D 多边形:

我希望模板通过重叠三角形数量为奇数的地方,这样我就可以达到这样的效果,其中白色区域是要忽略的区域:

我正在按照确切的顺序执行以下步骤:
设置深度StencilPixelFormat:
mtkView.depthStencilPixelFormat = .stencil8
mtkView.clearStencil = .allZeros
Run Code Online (Sandbox Code Playgroud)
模板附件:
let textureDescriptor = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: .stencil8, width: drawable.texture.width, height: drawable.texture.height, mipmapped: true)
textureDescriptor.textureType = .type2D
textureDescriptor.storageMode = .private
textureDescriptor.usage = [.renderTarget, .shaderRead, .shaderWrite]
mainPassStencilTexture = device.makeTexture(descriptor: textureDescriptor)
let stencilAttachment = MTLRenderPassStencilAttachmentDescriptor()
stencilAttachment.texture = mainPassStencilTexture
stencilAttachment.clearStencil = 0
stencilAttachment.loadAction = .clear
stencilAttachment.storeAction = .store
renderPassDescriptor.stencilAttachment = stencilAttachment
Run Code Online (Sandbox Code Playgroud)
模板描述符:
stencilDescriptor.depthCompareFunction = MTLCompareFunction.always
stencilDescriptor.isDepthWriteEnabled = true
stencilDescriptor.frontFaceStencil.stencilCompareFunction = MTLCompareFunction.equal
stencilDescriptor.frontFaceStencil.stencilFailureOperation = MTLStencilOperation.keep
stencilDescriptor.frontFaceStencil.depthFailureOperation = MTLStencilOperation.keep
stencilDescriptor.frontFaceStencil.depthStencilPassOperation = MTLStencilOperation.invert
stencilDescriptor.frontFaceStencil.readMask = 0x1
stencilDescriptor.frontFaceStencil.writeMask = 0x1
stencilDescriptor.backFaceStencil = nil
depthStencilState = device.makeDepthStencilState(descriptor: stencilDescriptor)
Run Code Online (Sandbox Code Playgroud)
最后,我在主通道中设置参考值和模板状态:
renderEncoder.setStencilReferenceValue(0x1)
renderEncoder.setDepthStencilState(self.depthStencilState)
Run Code Online (Sandbox Code Playgroud)
我是否遗漏了一些东西,因为我得到的结果就像根本没有模板一样。更改深度测试的设置时我可以看到一些差异,但更改模板的设置时没有任何反应......
有什么线索吗?
先感谢您
您将模板纹理清除为 0。参考值为 1。比较函数为“相等”。因此,比较将失败(1 不等于 0)。模板比较失败时的操作是“keep”,因此模板纹理保持为0。后续片段不会发生任何变化。
我希望您不会得到渲染,尽管根据顶点的顺序和正面缠绕模式,您可能会看到三角形的背面,在这种情况下,模板测试实际上被禁用。如果您不关心正面与背面,只需以相同的方式设置两个模板描述符即可。
我认为你需要做两遍:首先,仅模板渲染;其次,颜色渲染由模板缓冲区控制。仅对于模板,您可以使用比较函数.always。这将切换(反转)在给定像素上绘制的每个三角形的低位,从而指示偶数或奇数计数。因为比较函数和运算都不涉及参考值,所以它是什么并不重要。
对于第二遍,您将比较函数设置为.equal并将参考值设置为 1。操作应该全部为.keep。另外,请确保将模板附件加载操作设置为.load(不是.clear)。
| 归档时间: |
|
| 查看次数: |
2058 次 |
| 最近记录: |