我正在尝试在iOS上的SceneKit中实现网格的透明度。我对文档感到困惑,因为似乎有多种方法可以使网格透明:
SCNMaterial.(diffuse|emission|ambient|...).contents
SCNMaterial.transparency
(CGFloat从0.0到1.0)SCNMaterial.transparent
(另一个SCNMaterialProperty)SCNNode.opacity
(CGFloat从0.0(完全透明)到1.0(完全不透明))问题:
SCNMaterial.transparent
如何与其他颜色渠道互动,例如diffuse
?答案 0 :(得分:13)
某些属性是可动画的,其中一些属性将值均匀地应用于整个对象,而其他属性则允许您使用alpha通道纹理来控制每个点的透明度。将值应用于具有子节点的节点可以一次为多个节点设置透明度值。
漫反射Alpha通道
代替使用具有大量顶点的网格,有时可以使用具有漫反射纹理的简单网格,另请参见以下示例。
SCNMaterial.transparency
为整个材质均匀地调整不透明度。该属性是可动画的。
SCNMaterial.transparent
通常可以使用纹理来设置每个点的不透明度,而不是为整个材质设置透明度。
SCNNode.opacity
设置整个节点和所有子节点的不透明度。
还有更多可能的控制权
SCNMaterial.transparencyMode
使用材料的透明模式属性,您可以使用不同的模式:.aOne使用alpha通道,.rgbZero通过颜色亮度确定透明度。
颜色数学
颜色数学由混合模式决定,并在此处进行描述:
https://developer.apple.com/documentation/scenekit/scnblendmode
大小写字母
通过将源颜色和目标颜色相乘来混合 值及其对应的Alpha值。
添加案例
通过将源颜色添加到目标颜色进行混合。
大小写减去
通过从目标颜色中减去源颜色来进行混合。
大小写乘
通过将源颜色与背景颜色相乘来混合。
案例屏幕
通过将源颜色的倒数与目标颜色的倒数相乘来混合。
替换大小写
通过将目标颜色替换为源颜色进行混合, 忽略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级别上工作,则不会受到影响,例如如果您以透明的方式加载a.png文件,则无需做任何事自己对RGB进行预乘。
例如SCNMaterial.transparent与其他渠道
透明胶片必须能够一起用于不同的使用场景。例如,您要淡出具有已经部分透明的区域的对象。
人工演示示例
具有某些噪声纹理的球体,该球体已经具有透明区域
显示材质为.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)
}
结果如下: