一些属性是可动画的,其中一些属性将值统一应用于整个对象,而另一些属性则允许您使用 Alpha 通道纹理来控制每个点的透明度。将值应用于具有子节点的节点允许一次为多个节点设置透明度值。
漫反射 Alpha 通道
有时可以使用带有漫反射纹理的简单网格,而不是使用具有大量顶点的网格,另请参见下面的示例。
SCNMaterial.transparency
统一调整整个材质的不透明度。此属性是可动画的。
SCNMaterial.transparent
您可以单独设置每个点的不透明度,而不是为整个材质设置透明度值,通常使用纹理。
SCNNode.opacity
设置整个节点和所有子节点的不透明度。
还有更多可能的控制:
SCNMaterial.transparencyMode
通过材质的属性 transparentMode,您可以使用不同的模式:.aOne 使用 alpha 通道,.rgbZero 确定颜色亮度的透明度。
色彩数学
颜色数学由混合模式决定,并在此处描述:
https://developer.apple.com/documentation/scenekit/scnblendmode
案例阿尔法
通过将源颜色和目标颜色相乘来混合
值由它们对应的 alpha 值决定。
案例添加
通过将源颜色添加到目标颜色来混合。
案例减法
通过从目标颜色中减去源颜色来混合。
大小写相乘
通过将源颜色与背景颜色相乘来混合。
案例屏幕
通过将源颜色的倒数乘以目标颜色的倒数进行混合。
大小写替换
通过将目标颜色替换为源颜色来混合,
忽略阿尔法。
示例
树木/树叶
通常可以使用透明的漫反射纹理,而不是使用具有大量顶点的网格,这会导致帧速率明显下降甚至无法接受。一个很好的例子是例如树木和树叶。
在这里您可以看到左侧是透明纹理,中间是带有几个简单平面的网格,右侧是 SceneKit 渲染时的样子(网格和纹理取自 http://www.loopix-project.com)。
let mat = SCNMaterial()
mat.diffuse.contents = "palms1.png"
if let geometry = palm.geometry {
geometry.materials = [mat]
}
发光效果
对于不同的效果,可以使用混合模式,例如要获得一种发光效果,可以使用 blendMode .add:
mat.blendMode = .add
淡入/淡出
SCNNode.opacity 指的是一个包含所有子节点的节点。这个属性是动画的,所以如果你想淡入或淡出一个节点(或一组节点),这是正确的方法。
您还可以使用它为每个对象应用透明度。
预乘 alpha 与直接 alpha
SceneKit 在内部使用预乘 alpha。所以如果你正在编写着色器,你应该意识到这一点。
如果您只在 API 级别工作,则不会受到影响,例如如果你加载一个透明的.png文件,你不需要做任何事情来自己预乘RGB。
例如的交互SCNMaterial.transparent 与其他渠道
透明胶片必须能够针对不同的使用场景一起使用。例如,您想要淡出已经部分透明区域的对象。
人工演示示例
具有一些噪点纹理的球体已经具有透明区域
以材质 alpha .75 显示球体
添加第二个球体进行比较
设置:
let sphere1 = SCNSphere(radius: 0.5)
let material1 = SCNMaterial()
material1.diffuse.contents = "art.scnassets/colorTex.png"
material1.transparent.contents = UIColor(red: 1, green: 1, blue: 1, alpha: 0.75)
sphere1.materials = [material1]
let sphereNode1 = SCNNode(geometry: sphere1)
sphereNode1.position = SCNVector3(x: 0, y: -2, z: 0)
let sphere2 = SCNSphere(radius: 0.25)
let sphereNode2 = SCNNode(geometry: sphere2)
sphereNode2.position = SCNVector3(x: 0, y: -0.5, z: 0)
let spheres = SCNNode()
spheres.addChildNode(sphereNode1)
spheres.addChildNode(sphereNode2)
self.scnScene.rootNode.addChildNode(spheres)
现在通过 SCNNode.opacity 应用淡出:
let fadeOut = SCNAction.customAction(duration: 5) { (node, elapsedTime) -> () in
node.opacity = 1 - elapsedTime / 5
}
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
spheres.runAction(fadeOut)
}
结果如下: