I'm using GKNoise with a gradient map to generate color noise, getting a CGImage via SKTexture, on Mac OS.
The GKNoise gradientColors: init parameter takes a map of NSNumber to NSColor instances. I'm setting two to the min and max values (-1.0, 1.0), with a GKPerlinNoiseSource.
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).
Is there anything I overlooked to make GKNoise/SKTexture support alpha components of gradient input colors, corresponding to transparency in the output CGImage? Or is this 'as designed' or a known bug?
Below is test 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.
The GKNoise gradientColors: init parameter takes a map of NSNumber to NSColor instances. I'm setting two to the min and max values (-1.0, 1.0), with a GKPerlinNoiseSource.
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).
Is there anything I overlooked to make GKNoise/SKTexture support alpha components of gradient input colors, corresponding to transparency in the output CGImage? Or is this 'as designed' or a known bug?
Below is test 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.
Code Block import Foundation import GameplayKit class GKNoiseGradientIssue { var noiseSource: GKNoiseSource var color0_opaque = NSColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0) var color0_halfAlpha = NSColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 0.5) var color1_opaque = NSColor(red: 0.0, green: 0.0, blue: 1.0, alpha: 1.0) var opaqueNoise: GKNoise var halfAlphaNoise: GKNoise var opaqueNoiseMap: GKNoiseMap var halfAlphaNoiseMap: GKNoiseMap var opaqueImage: CGImage var halfAlphaImage: CGImage init() { let source = GKPerlinNoiseSource(frequency: 0.15, octaveCount: 7, persistence: 1.25, lacunarity: 0.5, seed: 12345) self.noiseSource = source let opaqueGradient: [NSNumber: NSColor] = [-1.0: color0_opaque, 1.0: color1_opaque] self.opaqueNoise = GKNoise(source, gradientColors: opaqueGradient) let halfAlphaGradient: [NSNumber: NSColor] = [-1.0: color0_halfAlpha, 1.0: color1_opaque] self.halfAlphaNoise = GKNoise(source, gradientColors: halfAlphaGradient) self.opaqueNoiseMap = GKNoiseMap(self.opaqueNoise, size: [200.0, 200.0], origin: [0.0, 0.0], sampleCount: [200, 200], seamless: false) self.halfAlphaNoiseMap = GKNoiseMap(self.halfAlphaNoise, size: [200.0, 200.0], origin: [0.0, 0.0], sampleCount: [200, 200], seamless: false) let opaqueTexture = SKTexture(noiseMap: self.opaqueNoiseMap) self.opaqueImage = opaqueTexture.cgImage() let halfAlphaTexture = SKTexture(noiseMap: self.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))) } } }
Just posting a follow-up here, I did eventually decide to jettison the use of SKTexture because of this issue - there does not appear to be any workaround.
Using the other init method of GKNoiseMap() that just takes noise, size, origin, sampleCount and seamless params, using noisemap.value() to get the generative values and using my own drawing code (supporting NSColors with alphas in the gradients I calculate) to render the output. It's slower so far (will be working on optimization) but the lack of alpha support in the SKTexture output was a deal-breaker. On the plus side, I can also now generate noise with more than two colors across the -1.0 to 1.0 value output; SKTexture only supported two opaque colors.
Using the other init method of GKNoiseMap() that just takes noise, size, origin, sampleCount and seamless params, using noisemap.value() to get the generative values and using my own drawing code (supporting NSColors with alphas in the gradients I calculate) to render the output. It's slower so far (will be working on optimization) but the lack of alpha support in the SKTexture output was a deal-breaker. On the plus side, I can also now generate noise with more than two colors across the -1.0 to 1.0 value output; SKTexture only supported two opaque colors.