首页 > 其他分享 >iOS ARKit 光照效果之光源

iOS ARKit 光照效果之光源

时间:2024-01-29 15:25:17浏览次数:464  
标签:光源 iOS ARView ARKit let var arView 光照

  • 光照

     在现实世界中,光扮演了极其重要的角色,没有光万物将失去色彩,没有光世界将一片漆黑。在3D数字世界中亦是如此,3D数字世界本质上是一个使用数学精确描述的真实世界复本,光照计算是影响这个数字世界可信度的极其重要的因素。

  • 光源

     顾名思义,光源即是光的来源,常见的光源有阳光、月光、星光、灯光等。光的本质其实很复杂,它是一种电磁辐射但却有波粒二象性(我们不会深入研究光学,那将是一件非常复杂且枯燥的工作,在计算机图形学中,只需要了解一些简单的光学属性并应用)。在实时渲染时,通常把光源当成一个没有体积的点,用工表示由其发射光线的方向,使用辐照度(Irradiance)量化光照强度。对平行光而言,它的辐照度可以通过计算在垂直于L 的单位面积上单位时间内穿过的能量衡量。在图形学中考虑光照,我们只要想象光源会向空间中发射带有能量的光子,然后这些光子会与物体表面发生作用(反射、折射和吸收),最后的结果是我们看到物体的颜色和各种纹理。

  •  RealityKit 中的光源

    iOS Reality Kit 支持3种光源类型:平行光(DirectionalLight)、点光(PointLigbt)、聚光(SpotLight),分别同于模拟太阳光、普通灯泡类灯光、手电筒类灯光,组合使用这3种光源类型可以实现绝大部分光照效果道染需求。实际上,RealityRit还支持环境光,但 RealityKit 中的环境光照并不直接来自光源,而是使用IBL(Image Based Lighting,基于图像的光照)技术从背景图像中提取。

      RealityKit 采用IBL 技术的初衷是增强3D虚拟元素的真实感,使用该技术可以从提供的环境资源貼因中提取环境信息及光照信息。环境资源贴图定义了AR环境中的大概颜色及明暗信息,利用这些信息,RealityKit 可以将其用于环境反射以增强虚拟元素的真实感和可信。

    使用环境资源贴图首先需要新建一个以.skybox为后辍的文件夹,并在该文件夹中放置使用的环境资源文件。环净资源贴图文件需为等距杜状投影环境图(经纬投影图)。將该文件实拖入 Xeode 工程文年写藏窗口中,在弹出的“选项”对 框中选择文件实引用(不要使用组),这样在工程编译译时 Xcode会自动打包该文件夹中所有的资源。

     Reality Kit 环境资源贴图类型支持常见图像格式,如.png 和.jpg 格式图像文件,但获得表现力更丰富:颜色更饱满的照明和反射效果,建议使用.exr或,bdr 格式图像,这两种格式支持高动态范围,用于环境反射效果更出色。

    在 RealityKit 中使用环境资源贴图只需要将贴图文件赋给 ARView. environment. background 属性,由干环境资源贴图放在特定的文件夹中,RealityKit 也提供了简洁的贴图加载方式,大大地简化了开发者的工作,典型代码如代码如下所示。

arView.environment.background = .skybox(try! EnvironmentResource.load(named: "Space"))

    平行光用于模拟在远处发射的光照效果,在Reality Kit中,使用平行光的代码如下:

//
//  DirectionalLightView.swift
//  ARKitDeamo
//
//  Created by Zhaoquan on 2023/1/7.
//

import SwiftUI
import RealityKit
import ARKit

struct DirectionalLightView : View {
    var body: some View {
        return ARViewContainer11().edgesIgnoringSafeArea(.all)
    }
}

struct ARViewContainer11: UIViewRepresentable {
    
    func makeUIView(context: Context) -> ARView {
        
        let arView = ARView(frame: .zero)
        let config = ARWorldTrackingConfiguration()
        config.planeDetection = .horizontal
        config.worldAlignment = .gravity
        arView.session.run(config, options:[ ])
        arView.session.delegate = arView
        arView.createPlane11()
        
        return arView
        
    }
    
    func updateUIView(_ uiView: ARView, context: Context) {
    }
}

var boxMesh = MeshResource.generateBox(size: 0.1)
var boxMaterial = SimpleMaterial(color:.white,isMetallic: false)
var boxEntity11 = ModelEntity(mesh:boxMesh,materials:[boxMaterial])

var planeMesh11 = MeshResource.generatePlane(width: 0.3,depth: 0.3)
var planeMaterial11 = SimpleMaterial(color:.white,isMetallic: false)
var planeEntity11 = ModelEntity(mesh:planeMesh11,materials:[planeMaterial11])

extension ARView {
    func createPlane11(){
        let planeAnchor = AnchorEntity(plane:.horizontal,classification: .any,minimumBounds: [0.3,0.3])
        planeAnchor.addChild(boxEntity11)
        var tf = boxEntity11.transform
        tf.translation = SIMD3(tf.translation.x,tf.translation.y + 0.06,tf.translation.z)
        boxEntity11.move(to: tf, relativeTo: nil)
        planeAnchor.addChild(planeEntity11)
        
        //添加平行光源
        let directionalLight = DirectionalLight()
        //光照强度
        directionalLight.light.intensity = 50000
        //光照颜色
        directionalLight.light.color = UIColor.red
        directionalLight.light.isRealWorldProxy = false
        
        directionalLight.look(at: [0, 0, 0], from: [0.01, 1, 0.01], relativeTo: nil)
        planeAnchor.addChild(directionalLight)
        self.scene.addAnchor(planeAnchor)
    }
}


#if DEBUG
struct DirectionalLightView_Previews : PreviewProvider {
    static var previews: some View {
        ARViewContainer11()
    }
}
#endif

    对平行光而言,光源位置并不重要,重要的是光照方向,在实际开发中,经常使用平行光的look()方法设置光照方向。

   点光从光源位置向所有方向发射光线,当光线沿各方向传播时会出现衰减,在RealityKit 中使用 attenuationRadius 参数表示光线最大有效距离,即超出该距离后的物体无法被光源照射。使用点光时,不仅要指定光源位置,还需要指定衰减半径,典型的点光使用代码如代码如下。

//
//  PointLightView.swift
//  ARKitDeamo
//
//  Created by Zhaoquan on 2023/1/7.
//

import SwiftUI
import RealityKit
import ARKit

struct PointLightView : View {
    var body: some View {
        return ARViewContainer12().edgesIgnoringSafeArea(.all)
    }
}

struct ARViewContainer12: UIViewRepresentable {
    
    func makeUIView(context: Context) -> ARView {
        
        let arView = ARView(frame: .zero)
        let config = ARWorldTrackingConfiguration()
        config.planeDetection = .horizontal
        config.worldAlignment = .gravity
        arView.session.run(config, options:[ ])
        arView.session.delegate = arView
        arView.createPlane12()
        return arView
    }
    
    func updateUIView(_ uiView: ARView, context: Context) {
    }
}



extension ARView {
    func createPlane12(){
        let planeAnchor = AnchorEntity(plane:.horizontal,classification: .any,minimumBounds: [0.3,0.3])
        
        let planeMesh = MeshResource.generatePlane(width: 0.8,depth: 0.8)
        let planeMaterial = SimpleMaterial(color:.white,isMetallic: false)
        let planeEntity = ModelEntity(mesh:planeMesh,materials:[planeMaterial])
        planeAnchor.addChild(planeEntity)
        
        let boxMesh = MeshResource.generateBox(size: 0.1)
        let boxMaterial = SimpleMaterial(color:.white,isMetallic: false)
        let boxEntity = ModelEntity(mesh:boxMesh,materials:[boxMaterial])
        planeAnchor.addChild(boxEntity)
        //添加点光源
        let l = PointLight()
        l.light = PointLightComponent(color: .green, intensity: 5000, attenuationRadius: 0.5)
        l.position = [planeEntity.position.x , planeEntity.position.y + 0.5,planeEntity.position.z+0.2]
        l.move(to: l.transform, relativeTo: nil)
        
        let lightAnchor = AnchorEntity(world: l.position)
        lightAnchor.components.set(l.light)
        self.scene.addAnchor(lightAnchor)
        self.scene.addAnchor(planeAnchor)
    }
}


#if DEBUG
struct PointLightView_Previews : PreviewProvider {
    static var previews: some View {
        ARViewContainer12()
    }
}
#endif

    聚光沿圆锥体发射光线,类似于手电筒的发光效果,其光线在传播时也会出现衰减,同时,在使用光需要指定圆锥角(innerAngleInDegrees)、聚光方向角(outerAngleInDegrees) 和光照方向,典型的聚光使用代码如下所示。

//
//  SpotLightView.swift
//  ARKitDeamo
//
//  Created by Zhaoquan on 2023/1/7.
//


import SwiftUI
import RealityKit
import ARKit

struct SpotLightView : View {
    var body: some View {
        return ARViewContainer12().edgesIgnoringSafeArea(.all)
    }
}

struct ARViewContainer13: UIViewRepresentable {
    
    func makeUIView(context: Context) -> ARView {
        
        let arView = ARView(frame: .zero)
        let config = ARWorldTrackingConfiguration()
        config.planeDetection = .horizontal
        config.worldAlignment = .gravity
        arView.session.run(config, options:[ ])
        arView.session.delegate = arView
        arView.createPlane13()
        return arView
        
    }
    
    func updateUIView(_ uiView: ARView, context: Context) {
    }
}
/*
class SpotLight: Entity, HasSpotLight {

    required init() {
        super.init()
        self.light = SpotLightComponent(color: .yellow,intensity: 50000, innerAngleInDegrees: 60,outerAngleInDegrees: 130,attenuationRadius: 5)
    }
}
 */

var planeMesh13 = MeshResource.generatePlane(width: 0.8,depth: 0.8)
var planeMaterial13 = SimpleMaterial(color:.white,isMetallic: false)
var planeEntity13 = ModelEntity(mesh:planeMesh13,materials:[planeMaterial13])

extension ARView : ARSessionDelegate{
    func createPlane13(){
        let planeAnchor = AnchorEntity(plane:.horizontal,classification: .any,minimumBounds: [0.3,0.3])
        planeAnchor.addChild(planeEntity13)
        let l = SpotLight()
        l.light = SpotLightComponent(color: .yellow, intensity: 5000, innerAngleInDegrees: 5, outerAngleInDegrees: 80, attenuationRadius: 2)
        l.position = [planeEntity13.position.x , planeEntity13.position.y + 0.1,planeEntity13.position.z+0.5]
        l.move(to: l.transform, relativeTo: nil)
        let lightAnchor = AnchorEntity(world: l.position)
        l.look(at: planeEntity13.position, from: l.position, relativeTo: nil)
        lightAnchor.components.set(l.light)
        self.scene.addAnchor(lightAnchor)
        self.scene.addAnchor(planeAnchor)
    }
}


#if DEBUG
struct SpotLightView_Previews : PreviewProvider {
    static var previews: some View {
        ARViewContainer13()
    }
}
#endif

     利用光照可以在数字世界中模拟真实物体的照明效果,营造真实可信的虛实融合场景,但光照计算是一頂对资源消耗比较大的任务,场最中光源设置得越多,对性能消耗就越大,为提商应用性能,需要控制场果中的光源数量,或者使用顶渲染的纹理贴图替代实时光照计算。RealityKit 中各光源类型对资源消耗排序为:聚光>点光>平行光>环境光,聚光对性能消耗最大,需谨慎使用。

 

标签:光源,iOS,ARView,ARKit,let,var,arView,光照
From: https://www.cnblogs.com/duzhaoquan/p/17994586

相关文章

  • 【教程】iOS 手机抓包工具介绍及教程
    ......
  • iOS应用崩溃了,如何通过崩溃手机连接电脑查找日志方法
    ​在iOS应用开发过程中,调试日志和奔溃日志是开发者必不可少的工具。当iOS手机崩溃时,我们可以连接电脑并使用XcodeConsole等工具来查看日志。然而,这种方式可能不够方便,并且处理奔溃日志也相当繁琐。克魔助手的出现为开发者带来了极大的便利,本文将详细介绍其功能和使用方法。克魔......
  • 2024最新苹果iOS17.3微信分身详解分享
    微信是目前最流行的社交软件之一,拥有庞大的用户群体。然而,对于一些需要同时使用多个微信账号的用户来说,使用官方版微信就显得有些不方便。iOS分身微信软件可以解决这个问题,它可以让用户在同一台设备上同时登录多个微信账号,从而实现工作生活两不误。iOS分身微信软件的优势iOS......
  • iOS 17.4 测试版包含大模型相关代码
    外界普遍预计苹果将在6月份通过iOS18推出主要的新人工智能功能。不过根据9to5Mac的报道,他们在iOS17.4第一个测试版中发现的代码表明,苹果正在开发由大语言模型技术支持的Siri新版本,并得到了其他来源的一些帮助。所谓其他来源是指苹果似乎正在使用OpenAI的ChatGPTA......
  • BIOS
    BIOS(BasicI/OSystem,基本输入输出系统)是计算机启动时自动执行的一组程序,位于计算机主板上的ROM(只读存储器)中.BIOS的主要功能是初始化计算机硬件,并进行自检,确保硬件设备正常运作.此外,BIOS还负责加载操作系统,为操作系统提供硬件控制和管理功能.BIOS在计算机启动过程中分为......
  • 描述文件错误:如何屏蔽 iOS 软件自动更新,去除更新通知和标记
    描述文件错误:如何屏蔽iOS软件自动更新,去除更新通知和标记适用于iOS、iPadOS和watchOS,即iPhone、iPad和AppleWatch通用请访问原文链接:https://sysin.org/blog/disable-ios-update/,查看最新版。原创作品,转载请保留出处。作者主页:sysin.org如何禁用iPhone、iPad和A......
  • 标准光照Shader
    思路《Shader入门精要》看到第九章,试着结合前面的知识实现一个标准光照模型,采用Blin-Phong模型,分为三大部分环境光,漫反射,高光反射。实现过程中加入凹凸效果,阴影效果。注释部分是透明效果,采用透明度测试的方法实现。具体细节见代码代码//UpgradeNOTE:replaced'mul(UNITY_MAT......
  • iOS 中 深拷贝和浅拷贝的区别
    在iOS开发中,深拷贝和浅拷贝是两种不同的对象复制方式,它们在处理NSArray、NSMutableArray以及其他集合类型时尤为重要。浅拷贝(ShallowCopy)浅拷贝仅复制对象的指针,而不复制对象本身。如果你对一个对象进行浅拷贝,新对象和原对象将指向相同的内存地址。这意味着如果你修改了其中一......
  • 【iOS ARKit】同时开启前后摄像头BlendShapes
       在上一节中已经了解了iOSARkit进行BlendShapes的基本操作,这一小节继续实践同时开启前后摄像头进行人脸捕捉和世界追踪。   iOS设备配备了前后两个摄像头,在运行AR应用时,需要选择使用哪个摄像头作为图像输人。最常见的AR体验使用设备后置摄像头进行世界跟踪、......
  • 【iOS ARKit】BlendShapes
    ​BlendShapes基础介绍   利用前置摄像头采集到的用户面部表情特征,ARKit提供了一种更加抽象的表示面部表情的方式,这种表示方式叫作BlendShapes,BlendShapes可以翻译成形状融合,在3dsMax中也叫变形器,这个概念原本用于描述通过参数控制模型网格的位移,苹果公司借用了这......