来自MTKView纹理的CIImageAccumulator问题

时间:2018-03-23 22:39:58

标签: swift3 metal render-to-texture ciimage

我希望通过视图的纹理将MTKView的输出捕获到CIImageAccumulator中,以实现渐进的绘制构建效果。问题是累加器似乎弄乱了原始的颜色/ alpha /颜色空间,如下所示:

enter image description here

从上图中,我捕捉看起来较暗的笔触的方式是通过视图的currentDrawable.texture属性:

lastSubStrokeCIImage = CIImage(mtlTexture: self.currentDrawable!.texture, options: nil)!.oriented(CGImagePropertyOrientation.downMirrored)
subStrokeUIView.image = UIImage(ciImage: lastSubStrokeCIImage)

现在,一旦我拍摄相同的图像并将其传输到CIIAcumulator中以便以后处理(我每个绘图段仅执行一次),结果是附件上部显示的更亮的结果:

lazy var ciSubCurveAccumulator: CIImageAccumulator =
    {
      [unowned self] in
      return CIImageAccumulator(extent: CGRect(x: 0, y: 0, width: self.frame.width * self.contentScaleFactor, height: self.frame.height * self.window!.screen.scale ) , format: kCIFormatBGRA8)
      }()!
ciSubCurveAccumulator.setImage(lastSubStrokeCIImage)
strokeUIView.image = UIImage(ciImage: ciSubCurveAccumulator.image())

我尝试在CIImageAccumulator定义中使用各种kCIFormats,但都无济于事。什么是CIImageAccumulator正在搞乱原件,我该如何解决它?请注意,我打算使用ciSubCurveAccumulator逐步构建一致颜色的连续笔刷。为了简化问题,我没有显示累积部分。这个问题阻止了我的死亡。

任何建议都会受到赞赏

1 个答案:

答案 0 :(得分:0)

问题归结为两件事:一,我需要为CompositeOver合成设置MTLRenderPipelineDescriptor(),二,我需要设置引入CIFilter来保存累积的CIImageAccumulator上的中间合成。还需要将此CIFilter设置为CIOverCompositing。以下是捕获以上所有内容的代码段:

lazy var ciSubCurveAccumulator: CIImageAccumulator =
{
  [unowned self] in
  return CIImageAccumulator(extent: CGRect(x: 0, y: 0, width: self.frame.width * self.contentScaleFactor, height: self.frame.height * self.window!.screen.scale ) , format: kCIFormatBGRA8)
  }()! // set up CIImageAccumulator

let lastSubStrokeCIImage = CIImage(mtlTexture: self.currentDrawable!.texture, options: nil)!.oriented(CGImagePropertyOrientation.downMirrored)
let compositeFilter : CIFilter = CIFilter(name: "CISourceOverCompositing")!

compositeFilter.setValue(lastSubStrokeCIImage, forKey: kCIInputImageKey) // foreground image
compositeFilter.setValue(ciSubCurveAccumulator.image(), forKey: kCIInputBackgroundImageKey) // background image

let bboxChunkSubCurvesScaledAndYFlipped = CGRect(...) // capture the part of the texture that was drawn to
ciSubCurveAccumulator.setImage(compositeFilter.value(forKey: kCIOutputImageKey) as! CIImage, dirtyRect: bboxChunkSubCurvesScaledAndYFlipped) // comp bbox with latest updates

将上面的代码包装在draw()内,可以使渐进式绘画积累得非常好。希望这可以在某个时候对某人有所帮助。