I'm using GKNoise with a gradient map to generate color noise, getting a CGImage via SKTexture, on Mac OS. In particular I'm using a GKPerlinNoiseSource and setting two gradient colors, at values -1.0 and 1.0.
It works as expected if the two colors are opaque. If one or both colors has an alpha component less than 1.0, I expect the output to have transparency. However, it looks to me like the alpha is completely ignored in GKNoise's gradient color input (treated as if it's always 1.0) - or, if not ignored there, ignored in the SKTexture rendering of the image output.
I have found a couple of SO questions which reference limitations with SKTexture in other uses, including a possible workaround with SKView rendering, however that doesn't apply here because I'm only using an SKTexture instance to get a CGImage (not using SKView or otherwise using anything from SpriteKit) - and FWIW those questions focus on iOS. For reference:
I'm looking for ideas on how to make alpha components in the gradient colors work using GKNoise/SKTexture.
Below is the test output image, and the code that reproduces it. In the view, both CGImages draw identically; I expect the one drawn with the red alpha=0.5 to be darker in the red parts when the background is black, lighter when it's white, etc.
import Foundation
import GameplayKit
class GKNoiseGradientIssue {
var redColor_opaque = NSColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0)
var redColor_halfAlpha = NSColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 0.5)
var blueColor_opaque = NSColor(red: 0.0, green: 0.0, blue: 1.0, alpha: 1.0)
var opaqueImage: CGImage
var halfAlphaImage: CGImage
init() {
let noiseSource = GKPerlinNoiseSource(frequency: 0.15,
octaveCount: 7,
persistence: 1.25,
lacunarity: 0.5,
seed: 12345)
let opaqueGradient: [NSNumber: NSColor] = [-1.0: redColor_opaque, 1.0: blueColor_opaque]
let opaqueNoise = GKNoise(noiseSource, gradientColors: opaqueGradient)
let opaqueNoiseMap = GKNoiseMap(opaqueNoise,
size: [200.0, 200.0],
origin: [0.0, 0.0],
sampleCount: [200, 200],
seamless: true)
let opaqueTexture = SKTexture(noiseMap: opaqueNoiseMap)
self.opaqueImage = opaqueTexture.cgImage()
let halfAlphaGradient: [NSNumber: NSColor] = [-1.0: redColor_halfAlpha, 1.0: blueColor_opaque]
let halfAlphaNoise = GKNoise(noiseSource, gradientColors: halfAlphaGradient)
let halfAlphaNoiseMap = GKNoiseMap(halfAlphaNoise,
size: [200.0, 200.0],
origin: [0.0, 0.0],
sampleCount: [200, 200],
seamless: true)
let halfAlphaTexture = SKTexture(noiseMap: halfAlphaNoiseMap)
self.halfAlphaImage = halfAlphaTexture.cgImage()
}
}
class GradientIssueView: NSView {
var issue: GKNoiseGradientIssue?
override func awakeFromNib() {
self.issue = GKNoiseGradientIssue()
}
override func draw(_ dirtyRect: NSRect) {
NSColor.black.setFill()
self.bounds.fill()
if let cgc = NSGraphicsContext.current?.cgContext {
cgc.draw(self.issue!.opaqueImage,
in: CGRect(origin: CGPoint(x: 10.0, y: 10.0),
size: CGSize(width: 200.0, height: 200.0)))
cgc.draw(self.issue!.halfAlphaImage,
in: CGRect(origin: CGPoint(x: 10.0, y: 220.0),
size: CGSize(width: 200.0, height: 200.0)))
}
}
}