【问题标题】:Why the SceneKit Material looks different, even when the image is the same?为什么 SceneKit 材质看起来不同,即使图像相同?
【发布时间】:2020-11-07 09:53:02
【问题描述】:

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

我注意到,当使用不同的加载器加载相同的图像文件 (.png) 时,渲染的材质会有所不同。

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

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

这是渲染示例:

关于代码:

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

【问题讨论】:

    标签: sprite-kit scenekit


    【解决方案1】:

    我认为这与色彩空间/伽马校正有关。我的猜测是通过 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 StackOverflow question image.
    //        let planeWithSKTextureDog = planeWith(diffuseContent: originalDogTexture)
          // Looks correct
            let planeWithSKTextureDog = planeWith(diffuseContent: gammaCorrectedDogTexture)
    

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

    【讨论】:

    • 天啊!!谢谢!!效果很好,稍微测试一下,我发现最接近 gamma 的是 1.75,我会为以后的搜索更新答案。非常感谢!
    猜你喜欢
    • 2015-01-30
    • 2018-10-25
    • 1970-01-01
    • 1970-01-01
    • 2018-04-28
    • 2017-07-31
    • 1970-01-01
    • 2018-11-28
    • 1970-01-01
    相关资源
    最近更新 更多