如何在RealityKit中以编程方式向ModelEntity添加材质?

5
RealityKit的文档包含了以下结构体:OcclusionMaterialSimpleMaterialUnlitMaterial,用于向ModelEntity添加材料。

或者您可以加载已附有材质的模型。

我想在程序中向ModelEntity添加自定义材料/纹理。如何在不将材料添加到Reality Composer或其他3D软件中的模型的情况下实现这一点?

1个回答

13

更新日期:2023年6月24日

RealityKit材质

目前RealityKit中有八种类型的材质:

SwiftUI版本

在这里,我使用了两种macOS实现(SwiftUI和Cocoa)来演示如何以编程方式分配RealityKit材质。

import SwiftUI
import RealityKit

struct VRContainer : NSViewRepresentable {        
    let arView = ARView(frame: .zero)
    let anchor = AnchorEntity()
    
    func makeNSView(context: Context) -> ARView {                    
        var smpl = SimpleMaterial()
        smpl.color.tint = .blue
        smpl.metallic = 0.7
        smpl.roughness = 0.2
                
        var pbr = PhysicallyBasedMaterial()
        pbr.baseColor.tint = .green

        let mesh: MeshResource = .generateBox(width: 0.5,
                                             height: 0.5,
                                              depth: 0.5,
                                       cornerRadius: 0.02,
                                         splitFaces: true)

        let box = ModelEntity(mesh: mesh, materials: [smpl, pbr])    
        box.orientation = Transform(pitch: .pi/4,
                                      yaw: .pi/4, roll: 0.0).rotation
        anchor.addChild(box)
        arView.scene.anchors.append(anchor)
        arView.environment.background = .color(.black)
        return arView
    }
    func updateNSView(_ view: ARView, context: Context) { }
}

struct ContentView: View {
    var body: some View {
        VRContainer().ignoresSafeArea()
    }
}

enter image description here

可可版本

import Cocoa
import RealityKit

class ViewController: NSViewController {        
    @IBOutlet var arView: ARView!
    
    override func awakeFromNib() {
        let box = try! Experience.loadBox()
        
        var simpleMat = SimpleMaterial()
        simpleMat.color = .init(tint: .blue, texture: nil)
        simpleMat.metallic = .init(floatLiteral: 0.7)
        simpleMat.roughness = .init(floatLiteral: 0.2)
        
        var pbr = PhysicallyBasedMaterial()
        pbr.baseColor = .init(tint: .green, texture: nil) 

        let mesh: MeshResource = .generateBox(width: 0.5, 
                                             height: 0.5, 
                                              depth: 0.5, 
                                       cornerRadius: 0.02, 
                                         splitFaces: true)

        let boxComponent = ModelComponent(mesh: mesh,
                                     materials: [simpleMat, pbr])

        box.steelBox?.children[0].components.set(boxComponent)
        box.steelBox?.orientation = Transform(pitch: .pi/4, 
                                                yaw: .pi/4, 
                                               roll: 0).rotation
        arView.scene.anchors.append(box)
    }
}

阅读这篇文章,了解如何为RealityKit的着色器加载纹理。


RealityKit着色器与SceneKit着色器

我们知道,在SceneKit中有5种不同的着色模型,因此我们可以使用RealityKit的SimpleMaterialPhysicallyBasedMaterialUnlitMaterial来生成我们习惯使用的这五种着色器。

让我们看看它是什么样子:

SCNMaterial.LightingModel.blinn           – SimpleMaterial(color: . gray,
                                                        roughness: .float(0.5),
                                                       isMetallic: false)

SCNMaterial.LightingModel.lambert         – SimpleMaterial(color: . gray,
                                                        roughness: .float(1.0),
                                                       isMetallic: false)
  
SCNMaterial.LightingModel.phong           – SimpleMaterial(color: . gray,
                                                        roughness: .float(0.0),
                                                       isMetallic: false)

SCNMaterial.LightingModel.physicallyBased – PhysicallyBasedMaterial()


// all three shaders (`.constant`, `UnlitMaterial` and `VideoMaterial `) 
// don't depend on lighting
SCNMaterial.LightingModel.constant        – UnlitMaterial(color: .gray)
                                          – VideoMaterial(avPlayer: avPlayer)

1
我可以确认这在iOS 13上完美运行!谢谢@ARGeo - iicaptain
2
是的,它确实可以工作。目前似乎需要使用一种解决方法来使 alpha 通道正常工作:Apple 论坛 - HelloTimo
1
有没有办法将6个脸部纹理添加到一个盒子上? - Jayden Irwin
1
是的,我不确定如何使用3D软件。我希望有一种简单的方法可以在代码中实现它。就像SceneKit可以使用一个包含6个纹理的数组来放置在盒子的每个面上一样。 - Jayden Irwin
嗨@JaydenIrwin,我更新了我的答案。有一个splitFaces: Bool参数可以帮助您应用6X纹理。 - Andy Jazz
1
@AndyJazz 我尝试在一个分割面的盒子上放置不同的材料(VideoMaterial和SimpleMaterial),然而,这只显示了带有视频纹理的立方体的侧面(其他部分不可见)。如果我不混合材料,结果是正常的。我是在VisionOS模拟器上完成的。也许这就是问题所在? - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接