AR/MR实时光照阴影开发教程

article/2025/8/5 7:14:39

一、效果演示

1、PICO4 Ultra MR 发光的球

2、AR实时光照

二、实现原理

        PICO4 Ultra MR开发时,通过空间网格能力扫描周围环境,然后将扫描到的环境网格材质替换为一个透明材质并停止扫描;基于Google ARCore XR Plugin和ARFoundation进行安卓手机的AR开发,通过扫描周围环境进行平面识别,然后将扫描到的平面的材质替换为一个透明材质并停止扫描。此处透明材质可以接收光照和阴影。

三、实现过程

        本教程使用Unity版本为2022.3LTS,渲染管线为URP,Built-In同样可用。

1、创建透明材质

        透明材质着色器来源于Meta的MRUK Sample,点击此处进入其Github页。

        克隆项目至本地,用Unity国际版本打开项目,需要复制着色器及三个依赖文件至计算机本地路径下。

(1)着色器资源准备

        找到下图所示Packages路径下的着色器,右键在资源管理器中打开,复制至本地文件夹下。

        找到下图所示Packages路径下的EnvironmentDepth文件夹,右键在资源管理器中打开,将EnvironmentOcclusion.cginc、URP中的EnvironmentOcclusionURP.hlsl和BiRP中的EnvironmentOcclusionBiRP.cginc复制至本地文件夹下。

        资源复制完成明细如下图所示。

(2)项目导入着色器

        将复制出的着色器及其依赖资源文件拖动至Unity项目合适路径下。此时,着色器会报错。

        此报错为资源引用路径所致,双击打开HighlightsAndShadows着色器脚本进行修改。

        1)找到以下引用:

        修改为:

#include "EnvironmentOcclusionURP.hlsl" //occl

        2)找到以下引用:

        修改为:

#include "EnvironmentOcclusionBiRP.cginc" //occl

注意:此引用有两处,都需修改

        修改完着色器脚本后,其依赖文件也会因资源引用路径而报错。

        双击打开EnvironmentOcclusionBiRP文件进行修改。

        找到以下引用:

        修改为:

#include "EnvironmentOcclusion.cginc"

        双击打开EnvironmentOcclusionURP文件进行修改。

        找到以下引用:

        修改为:

#include "EnvironmentOcclusion.cginc"

(3)创建材质

        按照以上修改完相关文件后,便可以使用HighlightsAndShadows着色器。有两种方式可以将此着色器应用于项目材质。

1)通过着色器直接创建材质

        选中HighlightsAndShadows着色器,鼠标右键-->Create--> Material。

2)材质引用着色器

        选中项目材质,在Shader设置中,选择Meta/MRUK/Scene/HighlightsAndShadows。

(4)材质效果

        可以将材质应用于Plane物体,查看光影效果。

2、PICO4 Ultra MR 发光的球实现

        此处需要使用空间网格,具体配置不再详述,参见:PICO4 Ultra MR开发 空间网格扫描 模型导出及预览或者PICO官网空间网格

(1)材质替换及停止扫描

        需要在扫描完成后,将网格材质替换为HighlightsAndShadows材质。首先需要找到所有网格对象,扫描生成的网格一般会作为挂载PXR_SpatialMeshManager脚本的物体的子物体,所以只需以此查找网格对象即可。具体代码如下:

public Transform spatialMeshParent;  //空间网格生成的父物体,即挂载PXR_SpatialMeshManager脚本的物体
public Material meshMaterial;        //接收光照和阴影的材质private MeshRenderer[] spatialMeshes;//空间网格上的MeshRenderer数组
private XRMeshSubsystem meshSubsystem;//网格子系统void Start()
{meshSubsystem = XRGeneralSettings.Instance.Manager.ActiveLoaderAs<PXR_Loader>().meshSubsystem;
}void Update()
{if (Controller.UXR_GetKeyDown(0, XR_KeyCode.APP)){spatialMeshes = spatialMeshParent.GetComponentsInChildren<MeshRenderer>();foreach(MeshRenderer renderer in spatialMeshes){renderer.material = meshMaterial;}//停止扫描网格meshSubsystem.Stop();}
}

(2)灯光设置

        创建一个点光源作为小球的子物体,并置于小球中心处。

(3)小球弹跳

        若使小球不会穿过墙面并可以在地面上弹跳,需要给网格预制件添加MeshCollider组件并赋予物理材质,物理材质设置合适弹性参数;小球上则需添加SpereCollider组件和Rigidbody组件,同样设置物理材质。

3、AR实时光照实现

        基于ARFoundation进行手机AR开发,若为安卓手机,额外导入Google ARCore XR Plugin,若为苹果手机,额外导入Apple ARKit XR Plugin。

(1)AR环境搭建

        创建XR Origin,并删除场景里的MainCamera物体。

        按照下图所示设置并添加组件。

        其中,ARPlaneManager的PlanePrefab需要手动创建并制作为预制件,赋予此处。

        创建ARSession。

(2)材质替换及停止扫描

        完整代码如下。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;public class ARDanceManager : MonoBehaviour
{public Material transparentMat;         //接收光照和阴影的材质public GameObject dancerPrefab;         //虚拟人物预制件public ARRaycastManager raycastManager; //射线碰撞检测器public ARPlaneManager m_ARPlaneManager; //平面生成器private List<ARRaycastHit> hits;private GameObject dancerObject = null;private bool hasSpawned = false;// Start is called before the first frame updatevoid Start(){hits = new List<ARRaycastHit>();}// Update is called once per framevoid Update(){if (dancerObject == null){if (Input.touchCount == 0)return;}if (!hasSpawned){var touch = Input.GetTouch(0);if (raycastManager.Raycast(touch.position, hits, TrackableType.PlaneWithinPolygon | TrackableType.PlaneWithinBounds)){var hitPose = hits[0].pose;if (dancerObject == null)//没有虚拟物体则生成{dancerObject = Instantiate(dancerPrefab, hitPose.position, /*hitPose.rotation*/dancerPrefab.transform.rotation);dancerObject.name = "Dancer";m_ARPlaneManager.enabled = false;SetAllPlanesTransparent();}else                      //有虚拟物体将虚拟物体锚定到射线碰撞点处{dancerObject.transform.position = hitPose.position;}}hasSpawned = true;}}//设置渲染的平面为透明void SetAllPlanesTransparent(){foreach (var plane in m_ARPlaneManager.trackables){plane.gameObject.GetComponent<MeshRenderer>().material = transparentMat;plane.gameObject.GetComponent<LineRenderer>().material = transparentMat;}}
}

        以上脚本挂载于场景物体,赋值相应变量即可。

四、视频教程

        视频教程参见:


http://www.hkcw.cn/article/ILObAixgBI.shtml

相关文章

图文详解Java集合面试题

文章目录 1、集合框架2、ArrayList、LinkedList3、HashMap、红黑树4、HashMap的put流程 1、集合框架 两条大支线&#xff1a; ①Collection接口&#xff1a;最基本的集合框架&#xff0c;提供添加、删除、清空等基本操作&#xff0c;主要有三个子接口&#xff1a;i&#xff1a…

深度学习|pytorch基本运算-乘除法和幂运算

【1】引言 前序学习进程中&#xff0c;已经对pytorch张量数据的生成和广播做了详细探究&#xff0c;文章链接为&#xff1a; 深度学习|pytorch基本运算-CSDN博客 深度学习|pytorch基本运算-广播失效-CSDN博客 上述探索的内容还止步于张量的加减法&#xff0c;在此基础上&am…

Python Day39 学习(复习日志Day4)

复习Day4日志内容 浙大疏锦行 补充: 关于“类”和“类的实例”的通俗易懂的例子 补充&#xff1a;如何判断是用“众数”还是“中位数”填补空缺值&#xff1f; 今日复习了日志Day4的内容&#xff0c;感觉还是得在纸上写一写印象更深刻&#xff0c;接下来几日都采取“纸质化复…

深度解析微服务网关:APISIX、Higress 与 Spring Cloud Gateway 技术对比与实战指南

一、引言 在微服务架构的演进中,API 网关作为流量入口的核心枢纽,其技术选型直接影响系统的性能、可扩展性和安全性。本文将从技术架构、核心功能、性能工程、生态体系等维度,对当前主流的三款网关 ——Apache APISIX(以下简称 APISIX)、Higress、Spring Cloud Gateway(…

rsync服务的搭建

目录 一、rsync介绍 rsync的安装 二、rsync的语法 三、rsync命令使用 1. 本机同步 2. 远程同步 四、rsync作为服务使用 1、尝试启动rsync程序 2、rsync的配置文件介绍 注意事项&#xff1a; 3. rsyncinotify实时同步 3.依赖服务托管xinetd&#xff08;CentOS 6中rs…

UE5.4.4+Rider2024.3.7开发环境配置

文章目录 一、UE5安装 安装有两种方式一种的源码编译安装、一种是EPIC安装&#xff0c;推荐后者&#xff0c;只需要注册一个EPIC账号就可以一键安装。 二、C环境安装 1.下载VisualStudioSetup 下载链接如下下载 Visual Studio Tools - 免费安装 Windows、Mac、Linux 选择社…

spining-lidar的电机和激光雷达体(lidar-imu)之间的标定

一、使用的是面结构标定 也就是用场景中的面结构来约束标定。 二、电机转轴和激光雷达之间的参数有哪些&#xff1f; 1.位置方面&#xff0c;显然&#xff0c;电机转轴是没有高度的&#xff0c;所以优化的相对量就是detax和detaY. 2.角度方面&#xff0c;显然&#xff0c;一开…

内存管理 : 06 内存换出

内存换出的重要性及与换入的关系 现在我们讲第25讲&#xff0c;主题是内存的换出&#xff08;swipe out&#xff09;。实际上&#xff0c;上一讲我们讲的是内存的换入&#xff0c;而这一节聚焦于内存的换出。 换入和换出必须合在一起工作&#xff0c;不能只有换入而没有换出。…

SAP财务过账BAPI函数使用以及代码

本文只是整理备用大部分整理自&#xff1a;https://www.cnblogs.com/chaguoguo/p/14006892.html 一、BAPI介绍 BAPI_ACC_GL_POSTING_POST&#xff1a; 主要用于处理总账凭证的过账。 它允许外部系统或程序直接向SAP的总账模块发送过账请求&#xff0c;而无需通过传统的用户…

PyTorch ——torchvision数据集使用

如果下载的很慢&#xff0c;可以试试下面这个

C#里与嵌入式系统W5500网络通讯(4)

怎么样修改W5500里的socket收发缓冲区呢? 需要进行下面的工作,首先要了解socket缓冲区的作用,接着了解缓冲区的硬件资源, 最后就是要了解自己的需求,比如自己需要哪个socket的收发送缓冲区多大。 硬件的寄存器为: 这是 W5500 数据手册中关于 Sn_RXBUF_SIZE(Socket n …

【PostgreSQL 04】PostgreSQL性能飞跃指南:从慢查询到服务器配置的全栈优化实战

PostgreSQL性能飞跃指南&#xff1a;从慢查询到服务器配置的全栈优化实战 关键词&#xff1a; PostgreSQL性能优化、查询优化、数据库调优、执行计划、索引优化、服务器配置、EXPLAIN分析、数据库性能监控 摘要&#xff1a; 你的PostgreSQL查询慢得像蜗牛爬行&#xff1f;数据库…

基于内存高效算法的 LLM Token 优化:一个有效降低 API 成本的技术方案

在使用 OpenAI、Claude、Gemini 等大语言模型 API 构建对话系统时&#xff0c;开发者普遍面临成本不断上升的挑战。无论是基于检索增强生成&#xff08;RAG&#xff09;的应用还是独立的对话系统&#xff0c;这些系统都需要维护对话历史以确保上下文的连贯性&#xff0c;类似于…

Marvin - 生成结构化输出 和 构建AI工作流

文章目录 一、关于Marvin1、项目概览2、相关链接资源3、功能特性4、为什么选择Marvin&#xff1f; 二、安装三、示例1、结构化输出工具marvin.extractmarvin.castmarvin.classifymarvin.generate 2、代理式控制流marvin.runmarvin.Agentmarvin.Task 四、核心抽象概念1、任务2、…

智慧新基建数字孪生,绘就桥梁运维新画卷

图扑融合中国风元素&#xff0c;打造智慧桥梁新基建数字孪生体系。以古韵山水风格呈现桥梁三维模型&#xff0c;精准映射结构细节。实时汇聚应力、位移等数据&#xff0c;兼具古典意境与现代科技。助力桥梁全生命周期管理&#xff0c;在传统美学与前沿技术交融中&#xff0c;提…

Codeforces Round 1028 (Div. 2) C. Gellyfish and Flaming Peony

Codeforces Round 1028 (Div. 2) C. Gellyfish and Flaming Peony 题目 Gellyfish hates math problems, but she has to finish her math homework: Gellyfish is given an array of n n n positive integers a 1 , a 2 , … , a n a_1, a_2, \ldots, a_n a1​,a2​,…,a…

while循环判断数字位数

while循环 #include <stdio.h> int main() {int x;int n 1;printf("请输入待测数字&#xff1a;\n");scanf("%d",&x);getchar();x / 10;while (x > 0){n;x / 10;}printf("位数为&#xff1a;%d\n",n);printf("请按下回车键退…

牛顿迭代算法-深度解析

牛顿迭代算法-深度解析 一、牛顿迭代算法的起源与基本概念1.1 算法起源1.2 基本概念 二、牛顿迭代算法的原理与推导2.1 几何原理2.2 数学推导2.3 收敛性分析 三、牛顿迭代算法的代码实现3.1 Python实现3.2 C实现3.3 Java实现 四、牛顿迭代算法的时间复杂度与空间复杂度分析4.1 …

SpringAI+DeepSeek大模型应用开发实战

内容来自黑马程序员 这里写目录标题 认识AI和大模型大模型应用开发模型部署方案对比模型部署-云服务模型部署-本地部署调用大模型什么是大模型应用传统应用和大模型应用大模型应用 大模型应用开发技术架构 SpringAI对话机器人快速入门会话日志会话记忆 认识AI和大模型 AI的发…

Python打卡第42天

浙大疏锦行 知识点回顾 回调函数lambda函数hook函数的模块钩子和张量钩子Grad-CAM的示例 回调函数 Hook本质是回调函数&#xff0c;所以我们先介绍一下回调函数 回调函数是作为参数传递给其他函数的函数&#xff0c;其目的是在某个特定事件发生时被调用执行。这种机制允许代码…