解决方案一
渐变上的条带伪影是计算机图形学中相当普遍的问题。要消除条带,您通常需要使用模糊。这是一个代码,可以帮助您为 SceneKit 漫反射材质执行此操作:
import SceneKit
class ViewController: UIViewController {
@IBOutlet var sceneView: SCNView!
let ciContext = CIContext()
fileprivate func gaussianBlur() -> UIImage? {
let uiImage = UIImage(named: "art.scnassets/banding.png")!
let ciImage = CIImage(image: uiImage)
guard let ciBlurFilter = CIFilter(name: "CIGaussianBlur")
else { return nil }
ciBlurFilter.setValue(ciImage, forKey: "inputImage")
let resultedImage = ciBlurFilter.value(forKey: "outputImage") as! CIImage
var blurredImage = UIImage(ciImage: resultedImage)
let cgImage = ciContext.createCGImage(resultedImage,
from: resultedImage.extent)
blurredImage = cgImage.flatMap { UIImage(cgImage: $0) }!
return blurredImage
}
override func viewDidLoad() {
super.viewDidLoad()
sceneView.scene = SCNScene()
let sphereNode = SCNNode(geometry: SCNSphere(radius: 0.2))
sphereNode.geometry?.firstMaterial?.diffuse.contents = gaussianBlur()
sceneView.scene?.rootNode.addChildNode(sphereNode)
}
}
解决方案二
.psd
在生成的 16 位和 32 位图像(例如、或文件格式)的源中.hdr
,不可能出现条带伪影。常规或每通道 8 位。.tiff
.exr
.png
.jpg
增加 8 位图像的大小不会带来积极的结果。那是因为每个通道仍有 256 个灰色半色调。但是,如果您使用 16 位,则.tiff
每个通道会获得 65536 级灰度。它是 8 位图像的 256 倍。
但是,让我们看看 Apple文档对此有何评论。
尽管图像对象支持所有平台原生图像格式,但建议您对应用程序中的大多数图像使用PNG
或JPEG
文件。图像对象针对读取和显示这两种格式进行了优化,并且这些格式提供了比大多数其他图像格式更好的性能。因为 PNG 格式是无损的,所以特别推荐您在应用程序界面中使用的图像。
所以 Apple 试图告诉我们使用 16 位和 32 位文件是可能的,但它闻起来像non-optimized
开发方式。如果您计划在 SCNScene 中渲染过多的 32 位纹理,请准备好获得冻结(无响应)的视图。
我个人尝试使用.hdr
,.tiff
和.exr
文件格式,它们看起来不错。不是 100% 肯定,但我认为您可以利用 16 位和 32 位.psd
文件,但是我认为在将它们导入 Xcode 项目之前必须将它们展平(成为单层)。
方案三
您可以通过编程方式构建 CIFilter 的CISmoothLinearGradient。这个过滤器有四个参数:
- inputPoint0 (CIVector)
- inputPoint1 (CIVector)
- 输入颜色0 (CIColor)
- 输入颜色1 (CIColor)