MTKView текстуры правильное наращивание цвета - PullRequest
0 голосов
/ 15 декабря 2018

Я работаю над приложением для рисования с металлической подложкой, в котором мазки кисти рисуются в MTKView путем многократной штамповки текстурированного квадрата вдоль траектории.У меня возникают проблемы с накоплением цвета, как показано на рисунке ниже:

snapshot of stamping implementation

Для значений альфа [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)

.

Подводя итог, мой вопрос, какнастроить режим текстур / смешивания таким образом, чтобы при любом значении прозрачности штампа накопленный результат рисования в области в конечном итоге приводил к полной непрозрачности цвета?Любые указатели будут оценены.

...