【问题标题】:RealityKit – How to set a ModelEntity's transparency?RealityKit – 如何设置 ModelEntity 的透明度?
【发布时间】:2020-03-23 20:07:12
【问题描述】:

在 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 (完全不透明))

不知道有没有办法在 RealityKit 中为 ModelEntity 设置透明度/不透明度/alpha?

【问题讨论】:

    标签: swift augmented-reality realitykit reality-composer


    【解决方案1】:

    RealityKit 1.0

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

     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 属性,而不是 .baseColor.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 值。

    【讨论】:

    【解决方案2】:

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

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

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

    plane.model?.materials = [OcclusionMaterial()]
    
    1. 带动画(您可以根据需要调整这些 sn-ps):
    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)
    
            }
    }
    

    希望这对某人有所帮助)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-05-05
      • 1970-01-01
      • 2020-05-04
      • 1970-01-01
      • 2023-02-03
      • 1970-01-01
      • 2020-01-27
      相关资源
      最近更新 更多