9 votes

RealityKit - Comment définir la transparence d'une ModelEntity ?

Dans SceneKit, il existe de nombreuses options telles que

  • Utiliser le canal alpha de UIColor via SCNMaterial.(diffuse|emission|ambient|...).contents
  • Utilice SCNMaterial.transparency (un CGFloat de 0,0 à 1,0)
  • Utilice SCNMaterial.transparent (autre propriété SCNMaterial)
  • Utilice SCNNode.opacity (un CGFloat de 0.0 (totalement transparent) à 1.0 (totalement opaque))

Je me demande s'il existe un moyen de définir la transparence/opacité/alpha pour ModelEntity dans RealityKit ?

15voto

Gigantic Points 4447

RealityKit 1.0

Il existe une solution dans RealityKit 1.0 qui permet de contrôler la transparence des objets. Vous pouvez le faire en utilisant baseColor o tintColor les propriétés de l'instance de SimpleMaterial() :

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

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

Solution iOS (exemple en couleur pour RealityKit 1.0)

Il fonctionne parfaitement sous iOS, même avec les paramètres de couleur :

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

enter image description here

solution macOS (exemple de texture pour 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)

Ou si vous n'avez pas besoin de texture sur un modèle (juste la couleur avec l'opacité), vous pouvez contrôler la transparence via baseColor propriété de l'instance :

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

Si votre scène contient les deux types d'objets - ceux créés dans Reality Composer et ceux créés programmatiquement dans Xcode et que vous assignez le même matériau aux deux objets - une application compilée présente des artefacts de rendu (voir l'image ci-dessous).

enter image description here

C'est dû au travail instable de RealityKit (parce que le framework est trop jeune pour le moment). Je pense que dans la prochaine version de RealityKit des bugs tels que missing texture on Reality Composer model et weird reflection left from sphere seront éliminés.

RealityKit 2.0

Dans RealityKit 2.0, les ingénieurs de l'équipe AR nous ont donné un .color au lieu de .baseColor et .tintColor . Ces deux mentions sont obsolètes dans iOS 15.

Solution iOS (exemple en couleur pour 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

enter image description here

Solution iOS (exemple de texture pour RealityKit 2.0)

La texture peut être appliquée en utilisant le même initialisateur :

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

Accordez une attention particulière aux éléments suivants tint multiplicateur - vous devez utiliser 0.9999 dans le cas où votre texture comporte des parties transparentes.

-2voto

Dilshod Turobov Points 122

J'ai trouvé plusieurs façons de le faire.

  1. Sans animation et le plus simple est d'utiliser OcclusionMaterial() :

    let plane = ModelEntity( mesh: .generatePlane(width: 0.1, depth: 0.1), materials: [OcculusionMaterial()] )

modifier l'opacité de l'entité existante :

plane.model?.materials = [OcclusionMaterial()]
  1. Avec animation (vous pouvez adapter ces extraits à vos besoins) :

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

    }

J'espère que cela a aidé quelqu'un )

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X