swift RealityKit -如何设置模型实体的透明度?

b5lpy0ml  于 2023-02-07  发布在  Swift
关注(0)|答案(2)|浏览(145)

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

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

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

ohtdti5x

ohtdti5x1#

现实工具包1.0
RealityKit 1.0中有一个解决方案允许你控制对象的透明度,你可以使用baseColorSimpleMaterial()tintColor示例属性来实现:

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

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

它完美地工作在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等bug将被消除。
现实工具包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值。
在这里你可以找到如何设置PhysicallyBasedMaterial的透明度。

ds97pgxw

ds97pgxw2#

我已经找到了几种方法。
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)

        }
}

希望这对某人有帮助)

相关问题