创建透明渐变并将其用作SpriteKit中的alpha遮罩

时间:2015-12-22 18:37:30

标签: swift sprite-kit cifilter ciimage

我正在尝试制作渐变并将其用作alpha蒙版。现在,我能够制作与此类似的图像(从黑色到透明):

gradient

这是我用来制作所有这些的代码:

private func createImage(width: CGFloat, height: CGFloat) -> CGImageRef?{

        if let ciFilter = CIFilter(name: "CILinearGradient"){

            let ciContext = CIContext()

            ciFilter.setDefaults()

            let startColor  = CIColor(red: 0, green: 0, blue: 0, alpha: 0)
            let endColor    = CIColor(red: 0, green: 0, blue: 0, alpha: 1)

            let startVector = CIVector(x: 0, y: height-10)
            let endVector   = CIVector(x: 0, y: height-22)

            ciFilter.setValue(startColor,   forKey: "inputColor0")
            ciFilter.setValue(endColor,     forKey: "inputColor1")
            ciFilter.setValue(startVector,  forKey: "inputPoint0")
            ciFilter.setValue(endVector,    forKey: "inputPoint1")



            if let outputImage = ciFilter.outputImage {

                let  cgImage:CGImageRef = ciContext.createCGImage(outputImage, fromRect: CGRect(x: 0, y: 0, width: width, height: height))

                return  cgImage

            }

        }

        return nil
    }

对我来说,这种方式非常完美,因为我在代码中创建了一次掩码(创建GUI元素时),因此性能根本不受影响。

问题是我实际上需要一个结果图像(渐变纹理)看起来像这样(渐变应该有固定的高度,但黑色区域的大小可能会有所不同):

desired look of a gradient texture

由于CILinearGradient过滤器没有inputImage参数,我无法一个接一个地链接两个过滤器。但我必须创建一个图像,并应用过滤器,然后创建另一个图像,并应用新的过滤器。

我正如上所述解决了这个问题。此外,我必须分三个步骤扩展一个过程(创建上部渐变,创建中间,黑色区域并创建较低的渐变),然后将所有这些组合成一个图像。

我想知道有什么关于我不知道的CILinearGradient过滤器吗?也许有一种更简单的方法可以解决这个问题并制作复杂的渐变?

请注意,我正在使用SpriteKit并使用CAGradientLayer解决此问题并不是我想要的方式。

1 个答案:

答案 0 :(得分:3)

我不确定Core Image是否适合这项工作 - 您可能最好使用CGGradient函数绘制图像。

除此之外:您可以提出的问题是可行的,但在CoreImage中很麻烦。可以想象一下,作为Photoshop或其他常用图形软件的用户创建这些图像所做的工作...... CoreImage的方式是这样的:

  1. 为上部渐变创建图层,使用渐变填充整个画布,并将图层转换为正确的位置和大小
  2. 为中间黑色部分创建一个图层,用黑色填充整个画布,并将图层转换为正确的位置和大小
  3. 同上#1,但是底部渐变。
  4. 您可以使用生成器过滤器,转换过滤器和合成过滤器的组合来完成此操作......

    gradient    -> transform -\
                               }-> composite -\
    solid color -> transform -/                \
                                                }-> composite
    gradient    -> transform ————————————————--/
    

    但是设置它会很难看。

    同样,在Photoshop中,您可以使用选择工具和填充/渐变工具在单个图层中完全创建渐变填充渐变设计......使用CoreGraphics绘制单个图像的方式类似于。

    那么,如何进行单程CG绘图?像这样......

    func createImage(width: CGFloat, _ height: CGFloat) -> CGImage {
    
        let gradientOffset: CGFloat = 10 // white at bottom and top before/after gradient
        let gradientLength: CGFloat = 12 // height of gradient region
    
        // create colors and gradient for drawing with
        let space = CGColorSpaceCreateDeviceRGB()
        let startColor = UIColor.whiteColor().CGColor
        let endColor = UIColor.blackColor().CGColor
        let colors: CFArray = [startColor, endColor]
        let gradient = CGGradientCreateWithColors(space, colors, [0,1])
    
        // start an image context
        UIGraphicsBeginImageContext(CGSize(width: width, height: height))
        defer { UIGraphicsEndImageContext() }
        let context = UIGraphicsGetCurrentContext()
    
        // fill the whole thing with white (that'll show through at the ends when done)
        CGContextSetFillColorWithColor(context, startColor)
        CGContextFillRect(context, CGRect(x: 0, y: 0, width: width, height: height))
    
        // draw top gradient
        CGContextDrawLinearGradient(context, gradient, CGPoint(x: 0, y: gradientOffset), CGPoint(x: 0, y: gradientOffset + gradientLength), [])
    
        // fill solid black middle
        CGContextSetFillColorWithColor(context, endColor)
        CGContextFillRect(context, CGRect(x: 0, y: gradientOffset + gradientLength, width: width, height: height - 2 * gradientOffset - 2 * gradientLength))
    
        // draw bottom gradient
        CGContextDrawLinearGradient(context, gradient, CGPoint(x: 0, y: height - gradientOffset), CGPoint(x: 0, y: height - gradientOffset - gradientLength), [])
    
        return CGBitmapContextCreateImage(context)!
    }