Raildex
Raildex

Reputation: 4817

RealityKit – Material's Alpha transparency

Is it possible to have alpha transparency with textures?

I have png file that contains 8 bit RGBA, but for some reason, the supposed-to-be-transparent parts are simply black.

I assign the material like this:

private func setupLightMeshes(_ scene: Entity) {
    let lightEntity = scene.findEntity(named: "LightWindow_Plane")!
    var lightMaterial = UnlitMaterial()
    
    lightMaterial.baseColor = try! MaterialColorParameter.texture(
    TextureResource.load(named: "light.png")) // this is 8bpc RGBA
    var modelComponent = lightEntity.components[ModelComponent] as! ModelComponent
    modelComponent = ModelComponent(mesh: modelComponent.mesh, materials: [lightMaterial])
    lightEntity.components.set(modelComponent)
}

Upvotes: 4

Views: 2247

Answers (2)

Andy Jazz
Andy Jazz

Reputation: 58563

iOS RealityKit 1.0

.tintColor is a multiplier for .baseColor

If you have a .png file with a premultiplied alpha (RGB*A). all you need to do is to additionally use a tintColor instance property with alpha equal to 0.9999.

material.tintColor = UIColor(white: 1.0, alpha: 0.9999)

Here's how it looks like in a real code:

fileprivate func material() -> UnlitMaterial {

    var material = UnlitMaterial()
    material.baseColor = try! .texture(.load(named: "transparent.png"))
    material.tintColor = UIColor(white: 1.0, alpha: 0.9999)
    return material
}

override func viewDidLoad() {
    super.viewDidLoad()
    
    let sphere: MeshResource = .generateSphere(radius: 0.5)

    let entity = ModelEntity(mesh: sphere,
                        materials: [material()])

    let anchor = AnchorEntity()
    anchor.orientation = simd_quatf(angle: .pi, axis: [0, 1, 0])

    anchor.addChild(entity)
    arView.scene.anchors.append(anchor)
}

Seems like a bug in RealityKit for iOS – why png transparency doesn't work as expected?!


iOS RealityKit 2.0

The same story about partially transparent textures is in RealityKit 2.0:

var material = SimpleMaterial()

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

tint parameter is a multiplier for texture as well.


RealityKit for visionOS

In visionOS app, to create a transparent material has become easier with OpacityComponent:

modelEntity.components[OpacityComponent.self] = .init(opacity: 0.25)

Upvotes: 13

93sauu
93sauu

Reputation: 4127

In case of using the PhysicallyBasedMaterial, the tint color does not work. You need to use the blending property together with opacityThreshold.

RealityKit 2.0

The easy solution is to use the convenience method to create a transparent texture with an opacity near to 1.

Besides if you want to show the texture for both sides of the mesh which was my case, you can set the faceCulling to none

var material = PhysicallyBasedMaterial()
material.baseColor = .init(texture: .init(myPNGTexture))
material.blending = .init(blending: .transparent(opacity: 0.9999))
material.opacityThreshold = 0.0 // IMPORTANT
material.faceCulling = .none

Upvotes: 4

Related Questions