- рендеринг выбранных объектов (к которым я хочу применить эффект свечения) в «текстуру маски»
- размытие текстуры маски по горизонтали
- размытие текстуры маски по вертикали
- компоновка маски с двойным размытием с помощью оригинальная текстура

Однако на моем iPhone 13 отображается сетка пурпурных квадратных артефактов mini:

Мой код постпроцессора выглядит так:
public func processFrame(context: ARView.PostProcessContext) -> Bool {
guard let commandBuffer = commandQueue.makeCommandBuffer() else {
return false
}
// Pass 1: Render selected entities to mask texture
let entityPassDescriptor: MTLRenderPassDescriptor = {
let descriptor = MTLRenderPassDescriptor()
descriptor.colorAttachments[0].texture = entityMaskTexture
descriptor.colorAttachments[0].loadAction = .clear
descriptor.colorAttachments[0].storeAction = .store
descriptor.colorAttachments[0].clearColor = MTLClearColor(red: 0, green: 0, blue: 0, alpha: 1)
return descriptor
}()
if let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: entityPassDescriptor) {
encoder.setRenderPipelineState(entityPipeline)
encoder.setCullMode(.back)
encoder.setFrontFacing(.counterClockwise)
renderEntitiesToMask(encoder: encoder, context: context)
encoder.endEncoding()
} else {
return false
}
// Pass 2: Blur horizontal
let texelSize = SIMD2(1.0 / Float(width), 1.0 / Float(height))
let blurHPassDescriptor: MTLRenderPassDescriptor = {
let descriptor = MTLRenderPassDescriptor()
descriptor.colorAttachments[0].texture = blurTexture1
descriptor.colorAttachments[0].loadAction = .clear
descriptor.colorAttachments[0].storeAction = .store
return descriptor
}()
if let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: blurHPassDescriptor) {
encoder.setRenderPipelineState(blurHPipeline)
encoder.setFragmentTexture(entityMaskTexture, index: 0)
var blurParams = SIMD3(texelSize.x, texelSize.y, blurRadius)
encoder.setFragmentBytes(&blurParams, length: MemoryLayout.size, index: 0)
encoder.drawPrimitives(type: .triangle, vertexStart: 0, vertexCount: 6)
encoder.endEncoding()
} else {
return false
}
// Pass 3: Blur vertical
let blurVPassDescriptor: MTLRenderPassDescriptor = {
let descriptor = MTLRenderPassDescriptor()
descriptor.colorAttachments[0].texture = blurTexture2
descriptor.colorAttachments[0].loadAction = .clear
descriptor.colorAttachments[0].storeAction = .store
return descriptor
}()
if let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: blurVPassDescriptor) {
encoder.setRenderPipelineState(blurVPipeline)
encoder.setFragmentTexture(blurTexture1, index: 0)
var blurParams = SIMD3(texelSize.x, texelSize.y, blurRadius)
encoder.setFragmentBytes(&blurParams, length: MemoryLayout.size, index: 0)
encoder.drawPrimitives(type: .triangle, vertexStart: 0, vertexCount: 6)
encoder.endEncoding()
} else {
return false
}
// Pass 4: Composite with glow color
let targetPixelFormat = context.targetColorTexture.pixelFormat
let compositePipeline = getOrCreateCompositePipeline(pixelFormat: targetPixelFormat)
let compositePassDescriptor: MTLRenderPassDescriptor = {
let descriptor = MTLRenderPassDescriptor()
descriptor.colorAttachments[0].texture = context.targetColorTexture
descriptor.colorAttachments[0].loadAction = .load
descriptor.colorAttachments[0].storeAction = .store
return descriptor
}()
if let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: compositePassDescriptor) {
encoder.setRenderPipelineState(compositePipeline)
encoder.setFragmentTexture(context.sourceColorTexture, index: 0)
encoder.setFragmentTexture(blurTexture2, index: 1) // Blurred mask
encoder.setFragmentTexture(entityMaskTexture, index: 2) // Original unblurred entity mask
encoder.setFragmentBytes(&glowColorVector, length: MemoryLayout.size, index: 0)
encoder.drawPrimitives(type: .triangle, vertexStart: 0, vertexCount: 6)
encoder.endEncoding()
} else {
return false
}
// have to manually commit, since it's our custom commandBuffer
commandBuffer.commit()
return true
}
Поскольку это связано с размером экрана, я подозревал, что это произошло из-за состояния гонки, когда постпроцессор RealityKit пытается получить доступ к окончательной текстуре, которая либо не готова, либо уже изменена в следующем кадре. Поэтому я добавил в конце одну строку кода:
// this fixes the issue
commandBuffer.commit()
commandBuffer.waitUntilCompleted() //
Подробнее здесь: https://stackoverflow.com/questions/798 ... -condition
Мобильная версия