3

在 SceneKit 中,有很多选项,例如

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

我想知道是否有办法在 RealityKit 中为 ModelEntity 设置透明度/不透明度/alpha?

4

2 回答 2

5

RealityKit 1.0

RealityKit 1.0 中有一个解决方案允许您控制对象的透明度。您可以使用baseColortintColor实例属性来做到这一点SimpleMaterial()

 var tintColor: NSColor { get set }
 var baseColor: NSColor { get set }

 var tintColor: UIColor { get set }
 var baseColor: UIColor { get set }

iOS 解决方案(RealityKit 1.0 的颜色示例)

即使使用颜色参数,它也可以在 iOS 中完美运行:

import UIKit
import RealityKit

class GameViewController: UIViewController {
    
    @IBOutlet var arView: ARView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        arView.backgroundColor = .black

        var material = SimpleMaterial()

        material.tintColor = UIColor.init(red: 1.0, 
                                        green: 1.0, 
                                         blue: 1.0, 
                                        alpha: 0.025)

        material.baseColor = MaterialColorParameter.color(UIColor.red)

        let mesh: MeshResource = .generateSphere(radius: 0.7)
        let modelEntity = ModelEntity(mesh: mesh,
                                 materials: [material])
        let anchor = AnchorEntity()
        anchor.addChild(modelEntity)
        arView.scene.anchors.append(anchor)
    }
}

在此处输入图像描述

macOS 解决方案(RealityKit 1.0 的纹理示例):

var material = SimpleMaterial()
         
// CYAN TINT and SEMI-TRANSPARENT ALPHA   
material.tintColor = NSColor.init(red: 0.0, green: 1.0, blue: 1.0, alpha: 0.5)

material.baseColor = try! MaterialColorParameter.texture(TextureResource.load(contentsOf: url))
material.roughness = MaterialScalarParameter(floatLiteral: 0.0)
material.metallic = MaterialScalarParameter(floatLiteral: 1.0)
    
// CUBE WAS MADE IN REALITY COMPOSER
cubeComponent.materials = [material]
    
// SPHERE IS MADE PROGRAMMATICALLY
let mesh: MeshResource = .generateSphere(radius: 0.7)

let sphereComponent = ModelComponent(mesh: mesh,
                                materials: [material])

anchor.steelBox!.components.set(cubeComponent)
anchor.components.set(sphereComponent)
arView.scene.anchors.append(anchor)

或者,如果您不需要模型上的任何纹理(只是具有不透明度的颜色),您可以通过baseColor实例属性控制透明度:

material.baseColor = MaterialColorParameter.color(.init(red: 0.0,
                                                      green: 1.0, 
                                                       blue: 1.0, 
                                                      alpha: 0.5))

如果您的场景包含两种类型的对象 - 在 Reality Composer 中制作并在 Xcode 中以编程方式制作,并且您为这两种对象分配相同的材质 - 已编译的应用程序会呈现一些渲染伪影(请看下图)。

在此处输入图像描述

这是由于 RealityKit 的工作不稳定(因为目前框架太年轻)。我认为在 RealityKit 的下一个版本中,此类错误missing texture on Reality Composer modelweird reflection left from sphere被消除。


RealityKit 2.0

在 RealityKit 2.0 中,AR 团队的工程师给了我们一个.color属性,而不是.baseColorand .tintColor。提到的这两个在 iOS 15 中已弃用。

iOS 解决方案(RealityKit 2.0 的颜色示例)

var material = SimpleMaterial()

material.color =  .init(tint: .red.withAlphaComponent(0.05), texture: nil)

material.baseColor       // deprecated in iOS 15
material.tintColor       // deprecated in iOS 15

在此处输入图像描述

iOS 解决方案(RealityKit 2.0 的纹理示例)

可以使用相同的初始化程序应用纹理:

material.color = try! .init(tint: .white.withAlphaComponent(0.9999),
                         texture: .init(.load(named: "mat.png", in: nil)))

特别注意tint乘数——如果你的纹理有透明部分,你必须使用0.9999值。

于 2019-11-30T15:34:42.623 回答
-2

我找到了几种方法来做到这一点。

  1. 没有动画,最简单的是使用OcclusionMaterial()
let plane = ModelEntity(
                       mesh: .generatePlane(width: 0.1, depth: 0.1), 
                       materials: [OcculusionMaterial()]
            )

改变现有实体的不透明度:

plane.model?.materials = [OcclusionMaterial()]
  1. 使用动画(您可以根据需要调整这些片段):
var planeColor = UIColor.blue

func fadeOut() {
        runTimer(duration: 0.25) { (percentage) in
            let color = self.planeColor.withAlphaComponent(1 - percentage)
            var material: Material = SimpleMaterial(color: color, isMetallic: false)
            if percentage >= 0.9 {
                material = OcclusionMaterial()
            }
            self.plane.model?.materials = [material]
        }

}

func fadeIn() {
        runTimer(duration: 0.25) { (percentage) in
            let color = self.planeColor.withAlphaComponent(percentage)
            let material: Material = SimpleMaterial(color: color, isMetallic: false)

            self.plane.model?.materials = [material]
        }
}

func runTimer(duration: Double, completion: @escaping (_ percentage: CGFloat) -> Void) {
        let startTime = Date().timeIntervalSince1970
        let endTime = duration + startTime

        Timer.scheduledTimer(withTimeInterval: 1 / 60, repeats: true) { (timer) in
            let now = Date().timeIntervalSince1970

            if now > endTime {
                timer.invalidate()
                return
            }
            let percentage = CGFloat((now - startTime) / duration)
            completion(percentage)

        }
}

希望这对某人有帮助)

于 2020-05-19T13:29:50.970 回答