You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ARKit开发:如何实现仅环形网格中心区域透明?

解决中心空心透视环形3D模型的问题

问题根源

你当前用两个圆柱叠加的方式存在两个核心问题:

  • UIColor.clear材质默认不写入深度缓冲区,导致内圆柱无法遮挡外圆柱的中心区域,空心效果无法显现
  • 给父实体添加OpacityComponent会统一作用于所有子实体,因此整个环形都会变透明

解决方案1:用Alpha Clipping实现内圆柱遮挡

修改内圆柱的材质,启用Alpha Clipping(透明度裁剪),让透明部分完全剔除,同时确保它能正确遮挡外圆柱的中心:

func createRing(outerColor: UIColor, outerOpacity: CGFloat, outerRadius: Float, innerRadius: Float) -> Entity {
    // 外圆环材质
    let outerMaterial = UnlitMaterial(color: outerColor.withAlphaComponent(outerOpacity))
    
    // 内遮挡物材质:启用Alpha Clipping,完全透明且不显示自身
    let innerMaterial = UnlitMaterial()
    innerMaterial.color = .init(tint: .clear, texture: nil)
    innerMaterial.alphaClippingThreshold = 0.1 // 裁剪所有透明度低于0.1的像素
    innerMaterial.writesToDepthBuffer = true // 确保写入深度缓冲区,实现遮挡
    innerMaterial.blending = .opaque // 关闭混合,避免半透明影响

    // 外圆柱(环形的边框部分)
    let outerMesh = MeshResource.generateCylinder(height: 0.01, radius: outerRadius)
    let outerEntity = ModelEntity(mesh: outerMesh, materials: [outerMaterial])

    // 内圆柱(用于遮挡外圆柱中心,实现空心),高度略高于外圆柱避免缝隙
    let innerMesh = MeshResource.generateCylinder(height: 0.012, radius: innerRadius)
    let innerEntity = ModelEntity(mesh: innerMesh, materials: [innerMaterial])

    // 移除内圆柱的碰撞组件,避免干扰交互
    innerEntity.components[CollisionComponent.self] = nil

    // 外圆柱的碰撞与交互设置
    outerEntity.components[CollisionComponent.self] = CollisionComponent(shapes: [ShapeResource.generateBox(size: [outerRadius * 2, outerRadius * 2, 0.01])])
    outerEntity.generateCollisionShapes(recursive: true)
    outerEntity.components.set(InputTargetComponent())

    let ringEntity = Entity()
    ringEntity.addChild(outerEntity)
    ringEntity.addChild(innerEntity)

    return ringEntity
}

解决方案2:直接生成环形网格(更高效)

避免叠加两个实体,直接创建真正的环形(空心圆盘)Mesh,这是更优雅的实现方式,减少实体数量且性能更优:

func createRing(outerColor: UIColor, outerOpacity: CGFloat, outerRadius: Float, innerRadius: Float) -> Entity {
    // 创建环形Mesh:通过SCNTorus转换为MeshResource
    func generateRingMesh(outerRadius: Float, innerRadius: Float, height: Float) -> MeshResource {
        let scnGeometry = SCNTorus(ringRadius: (outerRadius + innerRadius)/2, pipeRadius: (outerRadius - innerRadius)/2)
        scnGeometry.height = CGFloat(height)
        return MeshResource(scnGeometry: scnGeometry)
    }

    let ringMesh = generateRingMesh(outerRadius: outerRadius, innerRadius: innerRadius, height: 0.01)
    let material = UnlitMaterial(color: outerColor.withAlphaComponent(outerOpacity))
    let ringEntity = ModelEntity(mesh: ringMesh, materials: [material])

    // 碰撞与交互设置
    ringEntity.components[CollisionComponent.self] = CollisionComponent(shapes: [ShapeResource.generateBox(size: [outerRadius * 2, outerRadius * 2, 0.01])])
    ringEntity.generateCollisionShapes(recursive: true)
    ringEntity.components.set(InputTargetComponent())

    return ringEntity
}

关键说明

  • 方案1适合快速修改现有代码,通过遮挡实现空心效果
  • 方案2直接生成环形Mesh,视觉效果更稳定(不会出现两个圆柱叠加的缝隙问题)

内容的提问来源于stack exchange,提问作者kartbouni

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 21:32:33