一些属性是可动画的,有些应用于整个对象,而其他一些允许您使用alpha通道纹理来控制每个点的透明度。将值应用于具有子节点的节点允许为多个节点设置透明度值。
漫反射Alpha通道
有时候可以使用带有漫反射纹理的简单网格代替顶点数量较高的网格,下面的示例中也可以看到这种情况。
SCNMaterial.transparency
统一调整整个材料的不透明度。此属性是可动画的。
SCNMaterial.transparent
与其为整个材料设置透明度值,不如为每个点分别设置不透明度,通常使用纹理实现。
SCNNode.opacity
设置整个节点及其所有子节点的不透明度。
还有更多的控制方式:
SCNMaterial.transparencyMode
使用材料的transparencyMode属性可以使用不同的模式:.aOne使用alpha通道,.rgbZero从颜色亮度确定透明度。
颜色计算
混合模式决定了颜色计算方式,详见:
https://developer.apple.com/documentation/scenekit/scnblendmode
alpha
通过将源颜色和目标颜色的对应alpha值相乘来混合。
add
通过将源颜色添加到目标颜色来混合。
subtract
通过从目标颜色中减去源颜色来混合。
multiply
通过将源颜色与背景颜色相乘来混合。
screen
通过将源颜色的补数与目标颜色的补数相乘来混合。
replace
用源颜色替换目标颜色,忽略alpha通道。
示例
树木/植被
使用顶点数量较高的网格会导致帧率明显或甚至无法接受的降低,通常可以使用透明的漫反射纹理。一个很好的例子是树木和叶子。
左边是透明的纹理,中间是由几个简单平面组成的网格,右边是SceneKit呈现的效果(网格和纹理取自http://www.loopix-project.com)。
![leaves](https://istack.dev59.com/YyJ75.webp)
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 级别上工作,则不受影响,例如,如果您加载带有透明度的 a.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)
}
结果看起来是这样的:
![combined transparency](https://istack.dev59.com/qURxU.gif)
。