SceneKit:漫反射Alpha与透明度/透明

时间:2017-07-09 17:41:40

标签: ios opengl-es scenekit

我正在尝试在iOS上的SceneKit中实现网格的透明度。我对文档感到困惑,因为似乎有多种方法可以使网格透明:

  • 通过SCNMaterial.(diffuse|emission|ambient|...).contents
  • 使用UIColor的Alpha通道
  • 使用SCNMaterial.transparency(CGFloat从0.0到1.0)
  • 使用SCNMaterial.transparent(另一个SCNMaterialProperty)
  • 使用SCNNode.opacity(CGFloat从0.0(完全透明)到1.0(完全不透明))

问题:

  • 在某处有颜色数学的详细描述吗?
  • 添加透明度的常用方法是什么(每个对象,而不是纹理/每个顶点)?
  • SCNMaterial.transparent如何与其他颜色渠道互动,例如diffuse
  • 是否必须按https://stackoverflow.com/a/30195543/278842
  • 中的建议预乘alpha通道

1 个答案:

答案 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)。

leaves

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)
}

结果如下:

combined transparency