GKNoise, gradientColors, SKTexture: no alpha components?

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.

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


Accepted Reply

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.

Replies

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.