【iOS ARKit】环境反射

环境反射

    在使用 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/371122.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【快速上手QT】01-QWidgetQMainWindow QT中的窗口

总所周知,QT是一个跨平台的C图形用户界面应用程序开发框架。它既可以开发GUI程序,也可用于开发非GUI程序,当然我们用到QT就是要做GUI的,所以我们快速上手QT的第一篇博文就讲QT的界面窗口。 我用的IDE是VS2019,使用QTc…

神经网络 | 基于 CNN 模型实现土壤湿度预测

Hi,大家好,我是半亩花海。在现代农业和环境监测中,了解土壤湿度的变化对于作物生长和水资源管理至关重要。通过深度学习技术,特别是卷积神经网络,我们可以利用过去的土壤湿度数据来预测未来的湿度趋势。本文将使用 Pad…

Postgresql体系结构

client连接PostgreSQL过程: 1、客户端发起请求 2、主服务postmaster进程负责服务器是否接受客户端的host通信认证,服务器对客户端进行身份鉴别 3、主服务进程为该客户端单独fork一个客户端工作进程postgres 4、客户端与postgres进程建立通信连接&#xf…

【算法与数据结构】647、516、LeetCode回文子串+最长回文子序列

文章目录 一、647、回文子串二、516、最长回文子序列三、完整代码 所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。 一、647、回文子串 思路分析:判断一个字符串是否为回文串那么必须确定回文串的所在区间,而一维…

SQL--DDL

全称 Structured Query Language,结构化查询语言。操作关系型数据库的编程语言,定义了 一套操作关系型数据库统一标准。 1 SQL通用语法 在学习具体的SQL语句之前,先来了解一下SQL语言的同于语法。 1). SQL语句可以单行或多行书写&#xff0…

处理SERVLET中的错误和异常

处理SERVLET中的错误和异常 应用服务器服务客户机请求时可能会遇到一些问题,如找不到所请求的资源或运行中的servlet引发异常。例如,在线购物门户中如果用户选择了当前缺货的物品要放入购物车中,就会出现问题, 这种情况下,浏览器窗口中将显示错误消息。您可以在servlet中…

Maven工程的配置及使用

一、Maven章节 Maven 是 Apache 软件基金会组织维护的一款专门为 Java 项目提供构建和依赖管理支持的工具 1.1、maven的作用 1)依赖管理: 方便快捷的管理项目依赖的资源包(jar包)避免版本冲突 2)统一项目结构&…

STC系列单片机的中断系统

目录 一、中断系统的定义 二、STC15系列单片机的中断请求源及结构图 三、中断查询表以及触发方式 四、在keil c中如何声明中断函数 五、外部中断 六、基于STC15芯片实战中断系统的使用 (1)外部中断2/外部中断3来检测门的开关状态 (2&a…

【C++】- 继承(继承定义!!基本格式!切片概念!!菱形继承详解!)

继承 了解继承继承的定义基类和派生类对象赋值转换继承中的作用域派生类的默认成员函数继承和友元菱形继承和菱形虚拟继承 了解继承 继承机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保 持原有类特性的基础上进行扩展,增加功能&a…

优化 IT 支出和消除浪费的 8 种主要方法

不懈追求最佳 IT 支出对于任何组织的长期可持续发展和成功都至关重要。在这个技术快速进步的时代,您必须做出明智的决策,消除浪费,同时最大限度地提高技术投资的价值。 从进行 IT 成本分析到采用敏捷预算和技术标准化,这些策略对…

关于服务器解析A记录和CNAME记录的分析

内容提要: 大致讲下理解,dns域名解析这一块 0 . 问题来源 最近搞了一个七牛云上传,然后需要配置融合cdn加速,也就是可以加速域名,中间有一部需要CNAME 域名,也就是将七牛云提供的域名CNAME一下,查阅资料其实就是起一个别名,好访问而已. 方便我们访问云存储,达到加速的效果. …

Elasticsearch(ES) 简述请求操作索引下文档 增删查改操作

上文 Elasticsearch(ES) 创建带有分词器规则的索引 带着大家创建了一个带有分词功能的索引 老规矩 我们启动一下ES服务 本文 我们就来说说 关于文档的操作 我们先来添加一个文档 就像数据库加一条数据一样 这里 并不需要指定什么表结构和数据结构 它的文档结构是无模式的 添…

es6中标签模板

之所以写这篇文章,是因为标签模板是一个很容易让人忽略的知识点 首先我们已经非常熟悉模板字符串的使用方法 const name "诸葛亮" const templateString hello, My name is ${name}标签模板介绍 这里的标签模板其实不是模板,而是函数调用…

2024年Java面试题大全 面试题附答案详解,BTA内部面试题

基础篇 1、 Java语言有哪些特点 1、简单易学、有丰富的类库 2、面向对象(Java最重要的特性,让程序耦合度更低,内聚性更高) 阿里内部资料 基本类型 大小(字节) 默认值 封装类 6、Java自动装箱与拆箱 装箱就是…

《幻兽帕鲁》解锁基地和工作帕鲁数量上限

帕鲁私服的游戏参数通常可通过配置文件 PalWorldSettings.ini 来进行修改,然而这个配置文件有个别参数对游戏不生效,让人很是头疼。没错!我说的就是终端最大的帕鲁数量! 其实还有另外一种更加高级的参数修改方式,那就…

《Python 网络爬虫简易速速上手小册》第2章:网络爬虫准备工作(2024 最新版)

文章目录 2.1 选择合适的爬虫工具和库2.1.1 重点基础知识讲解2.1.2 重点案例:使用 Scrapy 抓取电商网站2.1.3 拓展案例 1:使用 Requests 和 BeautifulSoup 抓取博客文章2.1.4 拓展案例 2:使用 Selenium 抓取动态内容 2.2 设置开发环境2.2.1 重…

【前沿技术杂谈:开源软件】引领技术创新与商业模式的革命

【前沿技术杂谈:开源软件】引领技术创新与商业模式的革命 开源软件如何推动技术创新开源软件的开放性和协作精神促进知识共享和技术迭代推动关键技术的发展开源软件与新技术的融合 开源软件的商业模式开源软件的商业模式将开源软件与商业软件相结合 开源软件的安全风…

Docker Dockerfile

1、概念介绍 Dockerfile是用来构建Docker镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚本。 每条保留字指令都必须为大写字母且后面要跟随至少一个参数 指令按照从上到下,顺序执行 #表示注释 每条指令都会创建一个新的镜像层并对镜像进…

PyTorch 2.2 中文官方教程(十)

使用整体追踪分析的追踪差异 原文:pytorch.org/tutorials/beginner/hta_trace_diff_tutorial.html 译者:飞龙 协议:CC BY-NC-SA 4.0 作者: Anupam Bhatnagar 有时,用户需要识别由代码更改导致的 PyTorch 操作符和 CUDA 内核的变化…

vulhub中AppWeb认证绕过漏洞(CVE-2018-8715)

AppWeb是Embedthis Software LLC公司负责开发维护的一个基于GPL开源协议的嵌入式Web Server。他使用C/C来编写,能够运行在几乎先进所有流行的操作系统上。当然他最主要的应用场景还是为嵌入式设备提供Web Application容器。 AppWeb可以进行认证配置,其认…