SceneKit:漫反射 Alpha 与透明/透明
SceneKit: Diffuse Alpha vs. Transparency / Transparent
我正在尝试在 iOS 上的 SceneKit 中实现网格的透明度。我对文档感到困惑,因为似乎有多种方法可以使网格透明:
- 通过
SCNMaterial.(diffuse|emission|ambient|...).contents
使用UIColor的alpha通道
- 使用
SCNMaterial.transparency
(一个从 0.0 到 1.0 的 CGFloat)
- 使用
SCNMaterial.transparent
(另一个SCNMaterialProperty)
- 使用
SCNNode.opacity
(一个从 0.0(完全透明)到 1.0(完全不透明)的 CGFloat)
问题:
- 有没有关于颜色数学的详细描述?
- 添加透明度的常用方法是什么(每个对象,而不是通过 textures/per 顶点)?
SCNMaterial.transparent
如何与 diffuse
等其他颜色通道交互?
- Alpha 通道是否必须按照 中的建议预乘?
一些属性是可动画的,其中一些将一个值统一应用于整个对象,而另一些则允许您使用 alpha 通道纹理来控制每个点的透明度。将值应用于具有子节点的节点允许一次为多个节点设置透明度值。
漫反射 Alpha 通道
有时可以使用具有漫反射纹理的简单网格,而不是使用具有大量顶点的网格,另请参见下面的示例。
SCNMaterial.transparency
统一调整整体的不透明度material。这个 属性 是可动画的。
SCNMaterial.transparent
您可以单独设置每个点的不透明度,而不是为整个 material 设置透明度值,通常使用纹理。
SCNNode.opacity
设置整个节点和所有子节点的不透明度。
还有更多的控制可能:
SCNMaterial.transparency模式
使用 属性 transparencyMode of a material 你可以使用不同的模式:.aOne 使用 alpha 通道,.rgbZero 从颜色亮度决定透明度。
颜色数学
颜色数学由混合模式决定并在此处描述:
https://developer.apple.com/documentation/scenekit/scnblendmode
case alpha
Blend by multiplying source and destination color
values by their corresponding alpha values.
case add
Blend by adding the source color to the destination color.
case subtract
Blend by subtracting the source color from the destination color.
case multiply
Blend by multiplying the source color with the background color.
case screen
Blend by multiplying the inverse of the source color with the inverse of the destination color.
case replace
Blend by replacing the destination color with the source color,
ignoring 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
淡出in/Fade
SCNNode.opacity指的是包含所有子节点的节点。这个 属性 是可动画的,所以如果你想淡入或淡出一个节点(或一组节点),这是正确的方法。
您还可以使用它来为每个对象应用透明度。
预乘 alpha 与直接 alpha
SceneKit 内部使用预乘 alpha。所以如果你正在编写着色器,你应该知道这一点。
如果您只在 API 级别工作,则不会受到影响,例如如果你加载 a.png 透明文件,你不需要自己预乘 RGB。
例如互动SCNMaterial.transparent 与其他频道
透明胶片必须能够针对不同的使用场景一起使用。例如,您想要淡出已经部分透明区域的对象。
人工演示示例
一个已经有透明区域的带有噪声纹理的球体
显示球体 material 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)
}
结果如下所示:
我正在尝试在 iOS 上的 SceneKit 中实现网格的透明度。我对文档感到困惑,因为似乎有多种方法可以使网格透明:
- 通过
SCNMaterial.(diffuse|emission|ambient|...).contents
使用UIColor的alpha通道
- 使用
SCNMaterial.transparency
(一个从 0.0 到 1.0 的 CGFloat) - 使用
SCNMaterial.transparent
(另一个SCNMaterialProperty) - 使用
SCNNode.opacity
(一个从 0.0(完全透明)到 1.0(完全不透明)的 CGFloat)
问题:
- 有没有关于颜色数学的详细描述?
- 添加透明度的常用方法是什么(每个对象,而不是通过 textures/per 顶点)?
SCNMaterial.transparent
如何与diffuse
等其他颜色通道交互?- Alpha 通道是否必须按照 中的建议预乘?
一些属性是可动画的,其中一些将一个值统一应用于整个对象,而另一些则允许您使用 alpha 通道纹理来控制每个点的透明度。将值应用于具有子节点的节点允许一次为多个节点设置透明度值。
漫反射 Alpha 通道
有时可以使用具有漫反射纹理的简单网格,而不是使用具有大量顶点的网格,另请参见下面的示例。
SCNMaterial.transparency
统一调整整体的不透明度material。这个 属性 是可动画的。
SCNMaterial.transparent
您可以单独设置每个点的不透明度,而不是为整个 material 设置透明度值,通常使用纹理。
SCNNode.opacity
设置整个节点和所有子节点的不透明度。
还有更多的控制可能:
SCNMaterial.transparency模式
使用 属性 transparencyMode of a material 你可以使用不同的模式:.aOne 使用 alpha 通道,.rgbZero 从颜色亮度决定透明度。
颜色数学
颜色数学由混合模式决定并在此处描述:
https://developer.apple.com/documentation/scenekit/scnblendmode
case alpha
Blend by multiplying source and destination color values by their corresponding alpha values.
case add
Blend by adding the source color to the destination color.
case subtract
Blend by subtracting the source color from the destination color.
case multiply
Blend by multiplying the source color with the background color.
case screen
Blend by multiplying the inverse of the source color with the inverse of the destination color.
case replace
Blend by replacing the destination color with the source color, ignoring 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
淡出in/Fade
SCNNode.opacity指的是包含所有子节点的节点。这个 属性 是可动画的,所以如果你想淡入或淡出一个节点(或一组节点),这是正确的方法。
您还可以使用它来为每个对象应用透明度。
预乘 alpha 与直接 alpha
SceneKit 内部使用预乘 alpha。所以如果你正在编写着色器,你应该知道这一点。
如果您只在 API 级别工作,则不会受到影响,例如如果你加载 a.png 透明文件,你不需要自己预乘 RGB。
例如互动SCNMaterial.transparent 与其他频道
透明胶片必须能够针对不同的使用场景一起使用。例如,您想要淡出已经部分透明区域的对象。
人工演示示例
一个已经有透明区域的带有噪声纹理的球体
显示球体 material 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)
}
结果如下所示: