MTKView texture correct color build-up

我与影子孤独终老i 提交于 2020-01-24 01:03:30

问题


I am working on a metal-backed drawing application where brushstrokes are drawn on an MTKView by stamping a textured square repeatedly along a path. I am having color-accumulation issues as illustrated with the picture below:

For alpha values [0.5 - 1.0] the results are more or less what I expect. However, for small alpha values, the result looks patchy and never achieves the uniform/correctly saturated value of the original fully opaque brush color (i.e. like the top brushstroke in above picture).

One key concept of my approach, is the following (perhaps flawed) implementation: Say, the desired brushColor is blue, as above:

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

The way I set each stampColor is by dividing brushColor by the number of overlapping stamps:

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

.

The idea being that n overlapping stamps will cumulatively add up to brushColor (blue). Each stamp uses this stampColor at each vertex to multiply a white texture of a round blob with an alpha setting. Below is my fragment shader:

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;
 }

.

Thus, based on this concept I set out to find a blending mode that would give me the desired result. Through trial and error, I arrived at the following blending settings to achieve the result in the picture above:

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

.

On a related post, I had been advised to use "Source Over Compositing"

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

...which translates to:

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

.

but the results are even farther from the desired outcome.

the texture I'm using is built from a png file (with transparency) as follows:

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)

.

To sum up, my question is, how do I set up my textures/blending mode in a way that, for any stamp transparency value, the accumulated result of drawing in a region will eventually result in full color opacity? Any pointers would be appreciated.

来源:https://stackoverflow.com/questions/53788939/mtkview-texture-correct-color-build-up

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!