创建透明渐变并将其用作 SpriteKit 中的 alpha 蒙版
Creating transparent gradient and use it as an alpha-mask in SpriteKit
我正在尝试制作渐变并将其用作 alpha 蒙版。现在,我可以制作类似这样的图像(从黑色到透明):
这是我用来制作所有这些的代码:
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 元素时),所以性能完全不受影响。
问题是我实际上需要一个结果图像(渐变纹理)看起来像这样(渐变应该有固定的高度,但黑色区域的大小可能会有所不同):
因为 CILinearGradient
过滤器没有 inputImage
参数,我不能一个接一个地链接两个过滤器。但是我必须创建一个图像,并应用一个过滤器,然后创建另一个图像,并应用一个新的过滤器。
我按照上面的方法解决了这个问题。此外,我还必须在三个步骤中扩展一个过程(创建上部渐变、创建中间、黑色区域和创建下部渐变),然后将所有这些组合成一个图像。
我想知道 CILinearGradient 过滤器有什么我不知道的吗?也许有更简单的方法来解决这个问题并制作复杂的渐变?
请注意,我正在使用 SpriteKit 并且使用 CAGradientLayer 解决这个问题不是我想要的方式。
我不确定 Core Image 是否适合这里的工作——你最好使用 CGGradient
函数来绘制图像。
旁白:您所要求的在 CoreImage 中是可能的,但很麻烦。将其类比为您作为 Photoshop 或其他常见图形软件的用户创建这些图像的方式......CoreImage 方式将是这样的:
- 为上面的渐变创建一个图层,用你的渐变填充整个canvas,并将图层变换到合适的位置和大小
- 为中间的黑色部分创建图层,将整个canvas填充为黑色,并将图层变换到合适的位置和大小
- 同上 #1,但用于底部渐变。
您可以结合使用生成器过滤器、转换过滤器和合成过滤器...
gradient -> transform -\
}-> composite -\
solid color -> transform -/ \
}-> composite
gradient -> transform ————————————————--/
但是这样设置会很丑陋。
同样,在 Photoshop 中,您可以使用选择工具和 fill/gradient 工具在单个图层内完全创建渐变-填充-渐变设计……这与使用 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)!
}
我正在尝试制作渐变并将其用作 alpha 蒙版。现在,我可以制作类似这样的图像(从黑色到透明):
这是我用来制作所有这些的代码:
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 元素时),所以性能完全不受影响。
问题是我实际上需要一个结果图像(渐变纹理)看起来像这样(渐变应该有固定的高度,但黑色区域的大小可能会有所不同):
因为 CILinearGradient
过滤器没有 inputImage
参数,我不能一个接一个地链接两个过滤器。但是我必须创建一个图像,并应用一个过滤器,然后创建另一个图像,并应用一个新的过滤器。
我按照上面的方法解决了这个问题。此外,我还必须在三个步骤中扩展一个过程(创建上部渐变、创建中间、黑色区域和创建下部渐变),然后将所有这些组合成一个图像。
我想知道 CILinearGradient 过滤器有什么我不知道的吗?也许有更简单的方法来解决这个问题并制作复杂的渐变?
请注意,我正在使用 SpriteKit 并且使用 CAGradientLayer 解决这个问题不是我想要的方式。
我不确定 Core Image 是否适合这里的工作——你最好使用 CGGradient
函数来绘制图像。
旁白:您所要求的在 CoreImage 中是可能的,但很麻烦。将其类比为您作为 Photoshop 或其他常见图形软件的用户创建这些图像的方式......CoreImage 方式将是这样的:
- 为上面的渐变创建一个图层,用你的渐变填充整个canvas,并将图层变换到合适的位置和大小
- 为中间的黑色部分创建图层,将整个canvas填充为黑色,并将图层变换到合适的位置和大小
- 同上 #1,但用于底部渐变。
您可以结合使用生成器过滤器、转换过滤器和合成过滤器...
gradient -> transform -\
}-> composite -\
solid color -> transform -/ \
}-> composite
gradient -> transform ————————————————--/
但是这样设置会很丑陋。
同样,在 Photoshop 中,您可以使用选择工具和 fill/gradient 工具在单个图层内完全创建渐变-填充-渐变设计……这与使用 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)!
}