2015-04-23 31 views
5

Apple's texture importer'u kullanırken veya kendim, yazılımda (şeffaf bir bg ile) veya Photoshop'ta (beyaz bir kenarlı) çizilen beyaz yumuşak kenarlı bir daire Bir PNG olarak işlendiğinde, yarı-şeffaf renklerinin Metal'e getirildiğinde siyah ile yer değiştirmesi gerekir.Metal MTLTexture, 1 veya 0 olmayan Alfa değerleri olduğunda yarı saydam alanları siyahla değiştirir 0

Xcode'un Metal hata ayıklayıcısından alınan bir ekran yakalayıcısıdır, dokuyu gölgelendiricilere gönderilmeden önce görebilirsiniz. Bir UIImageView sokulduklarında Xcode

Image located here (I'm not high ranked enough to embed)

, bulucu ve kaynak doku halkasına sahip değildir. Ama UIImage -> CGContex -> MTLTexture süreci boyunca bir yerlerde (özellikle MTLTexture parçasını düşünüyorum) şeffaf bölümler kararıyor.

Kafamı duvara yapıştırarak geçtiğimiz birkaç gün boyunca yapabileceğim her şeyi değiştirdim ama anlayamıyorum.

, burada benim kişisel ithalat kodu

import UIKit 
import CoreGraphics 

class MetalTexture { 

    class func imageToTexture(imageNamed: String, device: MTLDevice) -> MTLTexture { 
     let bytesPerPixel = 4 
     let bitsPerComponent = 8 

     var image = UIImage(named: imageNamed)! 

     let width = Int(image.size.width) 
     let height = Int(image.size.height) 
     let bounds = CGRectMake(0, 0, CGFloat(width), CGFloat(height)) 

     var rowBytes = width * bytesPerPixel 
     var colorSpace = CGColorSpaceCreateDeviceRGB() 

     let context = CGBitmapContextCreate(nil, width, height, bitsPerComponent, rowBytes, colorSpace, CGBitmapInfo(CGImageAlphaInfo.PremultipliedLast.rawValue)) 

     CGContextClearRect(context, bounds) 
     CGContextTranslateCTM(context, CGFloat(width), CGFloat(height)) 
     CGContextScaleCTM(context, -1.0, -1.0) 
     CGContextDrawImage(context, bounds, image.CGImage) 

     var texDescriptor = MTLTextureDescriptor.texture2DDescriptorWithPixelFormat(.RGBA8Unorm, width: width, height: height, mipmapped: false) 

     var texture = device.newTextureWithDescriptor(texDescriptor) 
     texture.label = imageNamed 

     var pixelsData = CGBitmapContextGetData(context) 

     var region = MTLRegionMake2D(0, 0, width, height) 
     texture.replaceRegion(region, mipmapLevel: 0, withBytes: pixelsData, bytesPerRow: rowBytes) 

     return texture 
    } 
} 

olduğu Ama Apple'ın Swift içinde bir kopyası beri (sorun olduğunu sanmıyorum, ben sizinkinin yerine kullandım şeffaf (ha) olmak farklılık olmadan).

Herhangi bir müşteri adayı süper yardımcı olabilir.

+0

Bu aslında "siyah" değil, görüyorsunuz. Beyazdır, görüntünün alfa kanalıyla çarpılır, arka arkaya alfa ile çarpılır ve sonuca eklenir. CGImageAlphaInfo.Last'ın sorunu çözeceğini düşündüm, ancak bu donanım üzerinde uygulanmadı. Eşlenmemiş verileri nasıl elde edeceğimizi öğrenene kadar premultiplied alfa harmanlamayı uygulayabilir misiniz? – Jessy

+1

Aha! Beni doğru yol boyunca yönlendirdin. Cevabımı şimdi gönderiyorum. –

cevap

2

Jessy sayesinde alfalarımı nasıl karıştırdığımı incelemeye karar verdim ve anladım. Dokümanım hala GPU hata ayıklayıcıda kararıyor, ancak gerçek uygulamada her şey doğru görünüyor. Değişikliklerimi, aşağıda görebileceğiniz, boru hattı durum tanımlayıcısına yaptım.

pipelineStateDescriptor.colorAttachments[0].blendingEnabled = true 
pipelineStateDescriptor.colorAttachments[0].rgbBlendOperation = .Add 
pipelineStateDescriptor.colorAttachments[0].alphaBlendOperation = .Add 
pipelineStateDescriptor.colorAttachments[0].sourceRGBBlendFactor = .DestinationAlpha 
pipelineStateDescriptor.colorAttachments[0].sourceAlphaBlendFactor = .DestinationAlpha 
pipelineStateDescriptor.colorAttachments[0].destinationRGBBlendFactor = .OneMinusSourceAlpha 
pipelineStateDescriptor.colorAttachments[0].destinationAlphaBlendFactor = .OneMinusBlendAlpha 
1

Eğer src.rgb değerleri zaten src.a ile çarpılır çünkü karanlık alanlar neden olacak standart RGB = src.rgb * src.a + dst.rgb * (1-src.a) kullanarak, alfa kanalı ile çarpılır renkleri kullanmak üzere yapılandırılmış bir CGContext kullanıyorsunuz beri. Bu ne istediğini böyle yapılandırıldığını src.rgb + dst.rgb * (1-src.a) demektir:

pipeline.colorAttachments[0].isBlendingEnabled = true 
pipeline.colorAttachments[0].rgbBlendOperation = .add 
pipeline.colorAttachments[0].alphaBlendOperation = .add 
pipeline.colorAttachments[0].sourceRGBBlendFactor = .one 
pipeline.colorAttachments[0].sourceAlphaBlendFactor = .sourceAlpha 
pipeline.colorAttachments[0].destinationRGBBlendFactor = .oneMinusSourceAlpha 
pipeline.colorAttachments[0].destinationAlphaBlendFactor = .oneMinusSourceAlpha 

.one-olduğu gibi RGB terk etmek anlamına gelir. Premultiplied renklerin sebebi, harmanlandığınız her zamanın aksine renkleri yalnızca bir kez yaratımda çoğaltmanız gerektiğidir. Yapılandırmanız bunu da sağlıyor, ancak dolaylı olarak.