Я работаю над приложением для рисования с металлической подложкой, в котором мазки кисти рисуются в MTKView путем многократной штамповки текстурированного квадрата вдоль траектории.У меня возникают проблемы с накоплением цвета, как показано на рисунке ниже:
Для значений альфа [0,5 - 1,0] результаты более или менее соответствуютЯ жду.Однако при малых значениях альфа результат выглядит неоднородным и никогда не достигает равномерного / правильно насыщенного значения исходного полностью непрозрачного цвета кисти (т. Е., Как и верхний мазок кисти на рисунке выше).
Одной из ключевых концепций моего подхода является следующая (возможно, некорректная) реализация: Скажем, требуемый brushColor имеет синий цвет, как указано выше:
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 перекрывающихся штампов будут суммироваться в сумме brushColor (синий).Каждый штамп использует этот stampColor в каждой вершине, чтобы умножить белую текстуру круглого шарика с настройкой альфа.Ниже представлен мой фрагментный шейдер:
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)
.
Подводя итог, мой вопрос, какнастроить режим текстур / смешивания таким образом, чтобы при любом значении прозрачности штампа накопленный результат рисования в области в конечном итоге приводил к полной непрозрачности цвета?Любые указатели будут оценены.