14

在使用Apple 或我自己的纹理导入器时,在软件(带有透明背景)或 Photoshop(另存为 PNG)中绘制的白色软边圆在渲染时将其半透明颜色替换为黑色.

下面是 Xcode 的 Metal 调试器的屏幕截图,您可以在发送到着色器之前看到纹理。

图片位于此处(我的排名不够高,无法嵌入)

在 Xcode、finder 中,当放入 UIImageView 时,源纹理没有环。但是在 UIImage -> CGContex -> MTLTexture 过程中的某个地方(我特别想的是 MTLTexture 部分)透明部分变暗了。

在过去的几天里,我一直在努力改变一切,但我无法弄清楚。

为了透明(哈),这是我个人的导入代码

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

但我不认为这是问题所在(因为它是 Apple 在 Swift 中的副本,而我使用的是他们的,没有任何区别)。

任何线索都会非常有帮助。

4

2 回答 2

9

由于您使用的CGContext是配置为使用与 alpha 通道预乘的颜色,因此使用标准RGB = src.rgb * src.a + dst.rgb * (1-src.a)将导致变暗区域,因为这些src.rgb值已经预src.a这意味着您想要的是src.rgb + dst.rgb * (1-src.a)这样配置的:

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保持 RGB 不变的方法。预乘颜色的原因是您只需在创建时将颜色乘以一次,而不是每次混合时。您的配置也实现了这一点,但是是间接的。

于 2017-04-27T02:53:53.547 回答
7

感谢 Jessy,我决定研究一下我是如何混合我的 alpha 的,我已经弄明白了。我的纹理在 GPU 调试器中看起来仍然变暗,但在实际应用程序中一切看起来都正确。我对管道状态描述符进行了更改,您可以在下面看到。

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
于 2015-04-24T15:14:31.743 回答