首页 > 其他分享 >【iOS ARKit】环境反射

【iOS ARKit】环境反射

时间:2024-01-31 16:44:35浏览次数:27  
标签:反射 iOS 环境 探头 automatic ARKit config

环境反射

    在使用 iOS AR中 渲染虚拟物体时,RealityKit 默认使用了一个简单的天空盒(Skybox,即IBL环境资源贴图),所有带反射材质的物体默认会对天空盒产生反射。

     但在AR 中,使用IBL 技术实现的天空盒反射有一个很大的问题,那就是不真实,因为天空盒由开发者在开发时设置,不能实时地反映用户使用时的真实环境。为解决这个问题,ARKit 提出了环境探头(Environment Probe)的概念,环境探头在一个特定点模拟了一个全向相机,向6个方向以90°视场角拍摄6张照片(这6个方向分别是十X、 X、+Y、 Y、+Z、一Z),因为视场角是90°,这6张照片捕提到了它周围各个方向的球面图,然后将捕获的图像存储为一个 Cubemap(立方体贴图),这样就可供具有反射材质的对象使用。

     利用环境探头捕捉的立方体贴图环境信息,在PBR渲染的基础上,我们就可以实现动态环境的实时反射,而且可以通过调整 PBR 中的 Metallic 和 Smoothness 值实现不同程度的反射效果以便更好进行虚实融合。

环境探头

    环境探头理论上能够实时地反映动态的环境,但在AR中还存在一个问题,其原因在于AR 中需要反射的环境是用户的真实环境,而这些真实环境信息只能来自于用户的设备摄像机,在用户 720°扫描其周围环境之前,环境探头无法获取其所需要的所有环境信息,因此无法生成立方体贴图。这是一个需要权衡折中的问题,我们无法强制要求用户必须先720°扫描其周边环境,那只能采用另外一种不精确的以用户已经扫描过的环境信息推测用户所在环境的技术来补充所需信息。

        设置多环境探头的方式对静态的、范围有限的场景是一种很好的解决方案,但在大场景中,这就需要设置非常多的环境探头,这显然也不是最理想的解决方案。而且,静态布置的环境探头无法反映动态的内容。以动态物体所在位置实时动态地生成立方体贴图就能解决这个问题。

       每一个反射探头的实质是不断拍摄其所在位置6个方向的纹理制作成立方体贴图供反射物体使用,这是一个性能消耗很大的操作,实时的反射探头每帧都会生成一个立方体贴图,在提供对动态物体良好的反射时也会对性能造成很大的影响,为了降低性能消耗,常用的做法有烘焙(Bake)、手动更新(Manually),如对一个大厅的反射,可以预先烘焙到纹理中,但这种方式不能反映运行过程中的环境变化,手动更新可以根据需要在合适的时机人工更新,为达到比较好的性能与表现均

      环境探头有位置(Probe Origin)和尺寸(Size)属性,ProbeOrigin 即为反射探头的原点,Size 定义了从其原点出发可以抓取的图像范围,Origin 和 Size 构成了反射探头的反射盒和所在位置,只有在反射盒里的物体才能被拍摄捕获,才能被利用该反射探头的物体所反射。

    在 RealityKit 中,使用 ARWorldTrackingConfiguration配置类的 environmentTexturing 属性设置生成环境探头的方式,支持3种方式:None、Manual、Automatic,分别表示不使用环境探头,手动更新环境探头、ARKit 自动使用环境探头,具体如下表所示。

名称

描述

ARWorldTrackingConfiguration. Environment Texturing. none

不使用环境探头,不使用环境反射

ARWorld TrackingConfiguration. Environment Texturing. manual

由开发人员手动设置,手动更新环境探头

ARWorldTrackingConfiguration. Environment Texturing. automatic

由ARKit 自动设置,自动更新环境探头

     environmentTexturing 属性所描述的环境信息也是 ARKit 基于图像估计光照算法的基础,RealityKit会根据environmentTexturing属性的设定白动调整虚拟元素渲染。在AR 中使用环境探头采集真实环境信息并用于虚拟元素反射渲染能极大地提高虚拟元素的可信度和真实感,如图6-13所示,采用了这种技术的圆球能反射真实的白色纸杯,这对反射率很高的材质可以极大地增强其真实感,营造虚实难辨的自然感。

      为进一步增强反射的真实性,ARKit 还支持环境探头配合 wantSHDREnvironmentTextures 属性使用,该属性为布尔值,用于设置是否使用 HDR(High Dynamic Range,高动态范围)反射,HDR图像能更真实地反映现实环境的亮度差,高保真还原真实环境信息。在RealityKit 中使用环境探头反射需要使用 AREnvironmentProbeAnchor 类,该类继本目 ARAnchor,用于在指定位置生成环境探头并采集环境信息。

  • 提示:ARKit 只在配置 ARSession 为 ARWorldTrackingConfiguration 或者 ARBodyTrackingConfiguration 时才能使用环境反射,在其他配置情况下不支持环境反射。

环境反射操作

     RealityKit 在渲染场景时默认不开启环境反射,在使用时,我们也可以手动将配置中 environmentTexturing属性设置为 none 来强制关闭环境反射,代码如下:

//
//  EnvironmentTexturing.swift
//  ARKitDeamo
//
//  Created by zhaoquan du on 2024/1/30.
//
 
import SwiftUI
import ARKit
import RealityKit
 
 
struct TextWidthtKey: PreferenceKey {
    static var defaultValue: CGFloat = 0
 
    static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
        value = max(value, nextValue())
    }
}
 
struct EnvironmentTexturing: View {
    @State var automatic: Bool = true
    @State var textWidth: CGFloat = 0
    var body: some View {
        GeometryReader { ge in
            EnvironmentTexturingContainer(automatic: $automatic)
                .overlay(content: {
                   
                    VStack {
                        Spacer()
                        HStack{
                            Text(automatic ? "自动环境探头" : "不使用环境探头")
                                
                                .background(GeometryReader {_ in 
                                    Color.white
                                        //.preference(key: TextWidthtKey.self, value: $0.frame(in: .local).size.width)
                                })
//                                .onPreferenceChange(TextWidthtKey.self, perform: { width in
//                                    print("----------------w: \(ge.size.width), tw: \(width)")
//                                    self.textWidth = width
//                                })
                                .padding(10)
                                .offset(x: 0 )
                            
                            Toggle(isOn: $automatic) {}
                                .frame(width: 50)
                                .offset(x: 0)
                        }
                       
                        Spacer().frame(height: 40)
                    }
                    
 
                })
                .edgesIgnoringSafeArea(.all)
                .navigationTitle("环境探头")
        }
       
        
    }
}
 
struct EnvironmentTexturingContainer : UIViewRepresentable{
    
    @Binding var automatic: Bool
    func makeUIView(context: Context) -> ARView
    {
        let arView = ARView(frame: .zero)
        
        return arView
    }
    
    func updateUIView(_ uiView: ARView, context: Context) {
        
        if automatic {
            let config = ARWorldTrackingConfiguration()
            config.planeDetection = .horizontal
            
            config.environmentTexturing = .automatic
            config.wantsHDREnvironmentTextures = true
            
            context.coordinator.arView = uiView
            uiView.session.delegate = context.coordinator
            uiView.automaticallyConfigureSession = false
            uiView.session.run(config, options: [.resetTracking,.removeExistingAnchors])
            return
        }else{
            let config = ARWorldTrackingConfiguration()
            config.planeDetection = .horizontal
            
            config.environmentTexturing = .none
            
            context.coordinator.arView = uiView
            uiView.session.delegate = context.coordinator
            
            uiView.session.run(config, options: [.resetTracking,.removeExistingAnchors])
        }
        
        
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(parent: self)
    }
    
    class Coordinator: NSObject,ARSessionDelegate {
        var arView: ARView? = nil
        var parent: EnvironmentTexturingContainer
        init(parent: EnvironmentTexturingContainer) {
            self.parent = parent
        }
        func session(_ session: ARSession, didAdd anchors: [ARAnchor]) {
            guard let anchor = anchors.first as? ARPlaneAnchor else {
                return
            }
            let mesh = MeshResource.generateSphere(radius: 0.1)
            let meterial = SimpleMaterial(color: .blue, isMetallic: true)
            
            
            let modelEntity = ModelEntity(mesh: mesh, materials: [meterial])
            
            let planAnchor = AnchorEntity(anchor: anchor)
            //放在正上方
            modelEntity.transform.translation = [0, planAnchor.transform.translation.y + 0.05,0]
            
            planAnchor.addChild(modelEntity)
            arView?.scene.addAnchor(planAnchor)
            
            //只添加一次
            session.delegate = nil
            session.run(ARWorldTrackingConfiguration())
            
        }
    }
    
}

     我们手动将 environmentTexturing 属性设置为 none来关闭环境反射功能,这样创建的球体将不会对用户真实的环境进行反射效果如下左图所示。但在前文的学习中我们已经知道,RealityKit 默认会使用其内置的天空盒进行反射,这也就是我们能在光滑的球体表面看到模糊光斑的原因。

     对代码进行修改,当我们设置 environmentTexturing 为 automatic 时,RealityKit 将自行决定在用户的环境中放置一个或者多个环境探头,并利用这些环境探头采集的环境信息渲染虚拟元素的反射,效果如上图右图所示。

     在代码中我们加入了 arView.automaticallyConfigureSession = false 这一行语句,如果不设置禁止 automaticallyConfigureSession,自动环境反射不会起作用,因为 ARKit 的自动配置会覆盖开发者关于环境反射的设置。另外,我们还加人了config.wantsHDREnvironmentTextures = true这一行语句,这是允许 ARKit使用HDR 环境图进行反射,使反射效果更真实。

具体代码地址:https://github.com/duzhaoquan/ARkitDemo.git

标签:反射,iOS,环境,探头,automatic,ARKit,config
From: https://www.cnblogs.com/duzhaoquan/p/17999571

相关文章

  • IOS自动化测试框架appium
    由于公司的产品坐落于不同的平台,如ios、mac、Android、windows、web。因此每次有新需求的时候,开发结束后,留给测试的时间也不多。此外,一些新的功能实现,偶尔会影响其他的模块功能正常的使用。网上的ios自动化方面的内容也是少之又少。由于本人对ios自动化初次接触,花了两天......
  • 修改主板bios开机logo
    1. 下载AFUWIN5.12.zip,ChangeLogov5.2.0.22.zip   2.准备新logo,大小按原大小800*600可以jpg可以bmp3.操作:①原rom:打开AFUWINGUIx64.EXE程序 点击存储保存桌面原rom(建议多复制一个)②换logo图片:打开ChangeLogo64.exe程序 点击loadimage选择原......
  • Java的反射机制
    ​ java反射机制的核心是在程序运行时启动动态加载并获取类的信息,从而操作类或对象的属性和方法,本质是jvm得到class对象后,再通过class对象进行反编译,从而获取对象的各种语言信息。​ java属于先编译再执行的语言,程序中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动......
  • SpringBoot自定义注解+反射实现 excel 导入的数据组装及字段校验
    本次给大家带来的SpringBoot中通过自定义注解+反射实现excel导入数据组装及字段校验的实现方式。这种实现方式其实是很普通、常规的方法,但很多同学在开发过程中,可能却不太容易想到他。当然我也是众多同学中的一员。1背景在前段时间的开发工作中,接手了一个很简单,很普通的开发任务。......
  • IOS七层模型
    ISO七层模型的分层和作用7应用层<--------------应用层协议------------>应用层APDU6表示层<--------------表示层协议------------>表示层PPDU5会话层<--------------会话层协议------------>会话层SPDU4传输层<--------------传输层协议----------......
  • 2023最新版克魔助手抓包教程(9) - 克魔助手 IOS 数据抓包
     引言在移动应用程序的开发中,了解应用程序的网络通信是至关重要的。数据抓包是一种很好的方法,可以让我们分析应用程序的网络请求和响应,了解应用程序的网络操作情况。克魔助手是一款非常强大的抓包工具,可以帮助我们在Android和iOS平台上进行数据抓包。本篇博客将介绍如何使......
  • iOS App审核状态和审核时间管理指南
    引言对于一款开发完成并准备上架的iOS应用程序来说,通过苹果公司的审核是非常重要的一步。苹果公司会对应用程序进行严格的检查,以确保应用程序的质量和安全性。本文将介绍iOS应用程序审核的流程和时间,希望能够帮助开发者更好地了解和处理审核过程中的问题。添加图片注释,不超......
  • axios实现,在一个极短时间内,请求同一个接口,若传参完全一样,则使用浏览器中的缓存中的上
    axios实现,在一个极短时间内,请求同一个接口,若传参完全一样,则使用浏览器中的缓存中的上次的值。同时,上次的值应该在指定时间内可以自动清除。请写一个axios适配器。实现上述功能。在axios中,我们可以利用浏览器的缓存机制(HTTP缓存)来实现这个需求。不过,浏览器的HTTP缓存主要依赖于服......
  • 【教程】iOS如何抓取HTTP和HTTPS数据包经验分享
    ......
  • 【iOS ARKit】光照估计
    光照估计    AR与VR在光照上最大的不同在于VR世界是纯数字世界,有一套完整的数学模型,而AR则是将计算机生成的虚拟物体或关于真实物体的非几何信息叠加到真实世界的场景之上实现对真实世界的增强,融合了真实世界与数字世界。就光照而言,VR中的光照完全由开发人员决定,光照效......