ARKit-光影特效
本文主要介绍在AR中实现光照估计、环境光反射等相关知识,提高AR中虚拟物体渲染的真实性。
ARKit中的光照估计
ARKit支持对用户所处环境光照信息的估计,在ARConfiguration类中定义isLightEstimationEnabled布尔属性用于开启和关闭光照估计,该功能默认为启用状态。用于ARConfiguration是所有其他配置类的父类,因此ARKit所有的配置类都支持光照估计功能。
当设置isLightEstimationEnabled值为true时,ARKit每帧都会对从设备摄像头中采集的图像进行光照估计计算,并且将估计值保存在frame.lightEstimate属性中,frame.lightEstimate时ARLightEstimate类的实例,ARLightEstimate类只包含两个属性,如表6-2所示。
ARLightEstimate类属性
属性名描述ambientIntensity环境光强度值,取值范围[0,2000],在光照条件良好的环境中,该值约为1000,0表示环境非常黑暗,2000表示环境非常明亮ambientColorTemperature环境光温度值,单位为开尔文(K),纯白光为6500,低于该值表示环境更温暖,更偏向于黄光或橘黄光,而高于该值表示环境更冷,更偏向于蓝光
在RealityKit中,一般情况下开发人员无须关注frame.lightEstimate中的值,当设置 isLightEstimationEnabled的值为true时,RealityKit会自动使用环境光照估计值渲染虚拟元素的光照。但在使用自定义渲染时,开发人员必须自行处理光照估计。
下面演示如何启用光照估计并获取实时的光照估计值。(我选错了材质,导致不是很明显)
代码
//
// ViewController.swift
// ARImage
//
// Created by mac on 2022/11/6.
//
import UIKit
import RealityKit
import ARKit
var isPlaced = false
var times: Int = 0
class ViewController: UIViewController {
lazy var arview:ARView = {
let arView = ARView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height))
return arView
}()
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
view.addSubview(arview)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let config = ARWorldTrackingConfiguration()
config.planeDetection = .horizontal
config.isLightEstimationEnabled = true
self.arview.session.run(config)
self.arview.session.delegate = arview
}
}
extension ARView: ARSessionDelegate{
public func session(_ session: ARSession, didAdd anchors: [ARAnchor]) {
guard let anchor = anchors.first as? ARPlaneAnchor,!isPlaced else{return}
do{
let planeAnchor = AnchorEntity(anchor: anchor)
let box: MeshResource = .generateBox(size: 0.1,cornerRadius: 0.003)
var boxMaterial = SimpleMaterial(color: .blue, isMetallic: false)
boxMaterial.baseColor = try .texture(.load(named: "Box_Texture.jpg"))
boxMaterial.roughness = 0.8
let boxEntity = ModelEntity(mesh: box, materials: [boxMaterial])
planeAnchor.addChild(boxEntity)
self.installGestures(for: boxEntity)
self.scene.addAnchor(planeAnchor)
isPlaced = true
}
catch{
print("无法加载纹理图片")
}
}
public func session(_ session: ARSession, didUpdate frame: ARFrame) {
guard let estimatLight = frame.lightEstimate, times < 10 else{return}
print("light intensity:\(estimatLight.ambientIntensity),light temperature:\(estimatLight.ambientColorTemperature)")
times += 1
}
}
除了通用的光照估计,在使用ARFaceTrackingConfiguration配置运行ARSession时,ARKit会提供更多关于环境光照的估计信息,在这里不多赘述。
环境反射(反光的实现)
在使用RealityKit渲染虚拟物体时,RealityKit默认使用了一个简单的天空盒(Skybox,即IBL环境资源贴图),所有带反射材质的物体默认会对天空盒产生反射,但在AR中,存在的一个大问题就是不真实,不能实时地反映用户使用时的真实环境。
因此,我们引入了环境探头,环境探头理论上能够实时反映动态的环境,在RealityKit中,使用,ARWorldTrackingConfiguration配置类的environmentTexturing属性设置生成环境探头的方式,支持三种方式:None、Manual、Automatic,我们一般使用自动属性,为进一步增强反射的真实性,ARKit还支持环境探头配合wantsHDREnvironmentTextures属性使用,该属性为布尔值,用于设置是否使用HDR反射,HDR图像能更真实地反射现实环境的亮度差,高保真还原真实环境信息。
使用方法:
config.environmentTexturing = .automatic
config.wantsHDREnvironmentTextures = true
在使用自动环境反射时:开发人员无需进行有关环境反射的任何操作,只需要设置自动环境反射即可,其余工作完全由RealityKit自动完成,这适用于基本的常见环境反射。但这种环境反射方案是一种普适性的反射,并没有专门针对某特定虚拟元素进行优化,在这种情况下效果并不精细,并且我们也无法进行干预调优,如一辆行驶的赛车对环境的反射就需要更精细的控制,这时就需要手动控制环境探头的生成及更新。
使用手动控制环境探头时,我们需要将配置中的environmentTexturing属性设置为manual,并决定在什么地方、什么时候设置与更新环境探头。通常而言,可以遵循以下流程:
(1)在场景中某个特定位置创建AREnvironmentProbeAnchor锚点
(2)将创建的AREnvironmentProbeAnchor锚点添加到ARSession中
(3)使用session(_:didUpdate:)代理方法根据需要更新环境探头
精彩文章
发表评论