Search code examples
macosmetalblending

Correct blending mode for r8Unorm texture


Destination texture and brush textures are r8Unorm. What will be correct blending mode in this case?

Brush texture is radial gradient and looks like this:

enter image description here

On the first draw call it looks correct, but on the next draw calls it becomes full red circle without any gradient.

My current wrong blending settings looks like this:

private func createBrushDescriptor(library: MTLLibrary) -> MTLRenderPipelineDescriptor {
    let vertexDescriptor = MTLVertexDescriptor()
    vertexDescriptor.attributes[0].format = .float2
    vertexDescriptor.attributes[0].offset = 0
    vertexDescriptor.attributes[0].bufferIndex = 0

    vertexDescriptor.layouts[0].stride = 2 * MemoryLayout<simd_float1>.size
    vertexDescriptor.layouts[0].stepFunction = .perVertex
    vertexDescriptor.layouts[0].stepRate = 1
    
    let descriptor = MTLRenderPipelineDescriptor()
    descriptor.vertexFunction = library.makeFunction(name: "brush_vertex_function")
    descriptor.vertexDescriptor = vertexDescriptor
    descriptor.fragmentFunction = library.makeFunction(name: "brush_fragment_function")
    descriptor.colorAttachments[0].pixelFormat = .r8Unorm
    
    descriptor.colorAttachments[0].isBlendingEnabled = true
    descriptor.colorAttachments[0].rgbBlendOperation = .add
    descriptor.colorAttachments[0].sourceRGBBlendFactor = .one
    descriptor.colorAttachments[0].destinationRGBBlendFactor = .one
    
    descriptor.depthAttachmentPixelFormat = .invalid
    
    return descriptor
}

I draw brush using MTLPrimitiveType.point primitive.


Solution

  • I solved my problem with this configuration:

    descriptor.colorAttachments[0].isBlendingEnabled = true
    descriptor.colorAttachments[0].rgbBlendOperation = .max
    descriptor.colorAttachments[0].sourceRGBBlendFactor = .one
    descriptor.colorAttachments[0].destinationRGBBlendFactor = .one