为什么 SceneKit Material 看起来不同,即使图像相同?

Why the SceneKit Material looks different, even when the image is the same?

material内容支持很多加载选项,其中两个是NSImage(或UIImage)和SKTexture。

我注意到当使用不同的加载程序加载相同的图像文件 (.png) 时,material 呈现不同。

我很确定它是从 SpriteKit 转换加载的额外 属性,但我不知道它是什么。

为什么 SceneKit Material 看起来不同,即使图像相同?

这是渲染的例子:

关于代码:

let plane = SCNPlane(width: 1, height: 1)
plane.firstMaterial?.diffuse.contents = NSColor.green
let plane = SCNPlane(width: 1, height: 1)
plane.firstMaterial?.diffuse.contents = NSImage(named: "texture")
let plane = SCNPlane(width: 1, height: 1)
plane.firstMaterial?.diffuse.contents = SKTexture(imageNamed: "texture")

完整的例子在这里:https://github.com/Maetschl/SceneKitExamples/tree/master/MaterialTests

我认为这与颜色spaces/gamma校正有关。我的猜测是通过 SKTexture(imageNamed:) 初始值设定项加载的纹理未正确进行伽马校正。你会认为这会在某处记录下来,或者其他人会注意到,但我似乎找不到任何东西。

这里有一些代码可以与您链接的示例项目中的最后一张图片进行交换。为了简洁起见,我已经尽可能地强制展开:

      // Create the texture using the SKTexture(cgImage:) init 
      // to prove it has the same output image as SKTexture(imageNamed:)
      let originalDogNSImage = NSImage(named: "dog")!
      var originalDogRect = CGRect(x: 0, y: 0, width: originalDogNSImage.size.width, height: originalDogNSImage.size.height)
      let originalDogCGImage = originalDogNSImage.cgImage(forProposedRect: &originalDogRect, context: nil, hints: nil)!
      let originalDogTexture = SKTexture(cgImage: originalDogCGImage)

      // Create the ciImage of the original image to use as the input for the CIFilter 
      let imageData = originalDogNSImage.tiffRepresentation!
      let ciImage = CIImage(data: imageData)
      
      // Create the gamma adjustment Core Image filter
      let gammaFilter = CIFilter(name: "CIGammaAdjust")!
      gammaFilter.setValue(ciImage, forKey: kCIInputImageKey)
      // 0.75 is the default. 2.2 makes the dog image mostly match the NSImage(named:) intializer
      gammaFilter.setValue(2.2, forKey: "inputPower")
      
      // Create a SKTexture using the output of the CIFilter
      let gammaCorrectedDogCIImage = gammaFilter.outputImage!
      let gammaCorrectedDogCGImage = CIContext().createCGImage(gammaCorrectedDogCIImage, from: gammaCorrectedDogCIImage.extent)!
      let gammaCorrectedDogTexture = SKTexture(cgImage: gammaCorrectedDogCGImage)
      
      // Looks bad, like in Whosebug question image.
//        let planeWithSKTextureDog = planeWith(diffuseContent: originalDogTexture)
      // Looks correct
        let planeWithSKTextureDog = planeWith(diffuseContent: gammaCorrectedDogTexture)

使用 inputPower 为 2.2 的 CIGammaAdjust 过滤器会使 SKTexture 差不多?匹配 NSImage(named:) 初始化。我已经包含了通过 SKTexture(cgImage:) 加载的原始图像,以排除使用该初始化程序与您询问的 SKTexture(imageNamed:) 相比引起的任何更改。