0

我正在开发一个金属支持的绘图应用程序,其中笔触是通过沿路径反复压印纹理正方形在 MTKView 上绘制的。我遇到了颜色累积问题,如下图所示:

冲压实施的快照

对于 alpha 值 [0.5 - 1.0],结果或多或少符合我的预期。但是,对于较小的 alpha 值,结果看起来不完整,并且永远无法达到原始完全不透明画笔颜色的均匀/正确饱和值(即,如上图中的顶部笔触)。

我的方法的一个关键概念是以下(可能有缺陷的)实现:比如说,所需的画笔颜色是蓝色,如上:

brushColor = (r: 0.0, g: 0.0, b:1.0, a: 1.0)

我设置每个 stampColor 的方式是通过将 BrushColor 除以重叠图章的数量:

overlapStampCount = n
stampColor = (r: 0.0/overlapStampCount, g: 0.0/overlapStampCount, b:1.0/overlapStampCount, a:1.0/overlapStampCount) 

.

这个想法是 n 个重叠的图章将累积加起来为画笔颜色(蓝色)。每个图章在每个顶点使用此 stampColor 将圆形斑点的白色纹理与 alpha 设置相乘。下面是我的片段着色器:

fragment float4 basic_fragment(VertexOut interpolated [[stage_in]], texture2d<float>  tex2D     [[ texture(0) ]],
 sampler           sampler2D [[ sampler(0) ]]) {
   float4 color = interpolated.color * tex2D.sample(sampler2D, interpolated.texCoord); // texture multiplied by vertex color

   return color;
 }

.

因此,基于这个概念,我着手寻找一种混合模式,可以给我想要的结果。经过反复试验,我得出了以下混合设置,以达到上图的效果:

renderPipelineDescriptor.colorAttachments[0].sourceRGBBlendFactor = .one
renderPipelineDescriptor.colorAttachments[0].destinationRGBBlendFactor = .oneMinusSourceAlpha
renderPipelineDescriptor.colorAttachments[0].sourceAlphaBlendFactor = .one
renderPipelineDescriptor.colorAttachments[0].destinationAlphaBlendFactor = .oneMinusSourceAlpha

.

在一个相关的帖子中,有人建议我使用“Source Over Compositing”

cdst′ = αsrc * csrc + (1 - αsrc) * cdst

...翻译为:

renderPipelineDescriptor.colorAttachments[0].sourceRGBBlendFactor = .sourceAlpha
renderPipelineDescriptor.colorAttachments[0].destinationRGBBlendFactor = .oneMinusSourceAlpha
renderPipelineDescriptor.colorAttachments[0].sourceAlphaBlendFactor = .sourceAlpha
renderPipelineDescriptor.colorAttachments[0].destinationAlphaBlendFactor = .oneMinusSourceAlpha

.

但结果与预期的结果相去甚远。

我正在使用的纹理是从 png 文件(具有透明度)构建的,如下所示:

let image = UIImage(contentsOfFile: path)!.cgImage!
let colorSpace = CGColorSpaceCreateDeviceRGB()
    width = image.width
    height = image.height

let rowBytes = width * bytesPerPixel

let context = CGContext(data: nil, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: rowBytes, space: colorSpace, bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue)!
let bounds = CGRect(x: 0, y: 0, width: Int(width), height: Int(height))
context.clear(bounds)

if flip == false {
  context.translateBy(x: 0, y: CGFloat(self.height))
  context.scaleBy(x: 1.0, y: -1.0)
}

context.draw(image, in: bounds)

let texDescriptor = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: MTLPixelFormat.rgba8Unorm, width: Int(width), height: Int(height), mipmapped: isMipmaped)

texture = device.makeTexture(descriptor: texDescriptor)

.

总而言之,我的问题是,我如何设置我的纹理/混合模式,对于任何印章透明度值,在一个区域中绘制的累积结果最终会导致全色不透明度?任何指针将不胜感激。

4

0 回答 0