【ARFoundation自学03】平面追踪可视化效果美化

       对已检测到的平面默认的渲染效果显得有些生硬和突兀,有时我们需要更加友好、美观的的平面虚拟界面,这时就需要对已检测到的平面定制个性化的可视方案。为达到更好的视觉效果,处理的思路如下。

视觉效果前后对比!

(本节Shader与ARFeatheredPlaneMesh Visualizer.cs脚本来自Untiy官方AR Foudnation参考代码)

在实现本案例前需要先看第一篇,这篇文章搭建了平面检测的框架!本篇是在此基础上进行的升级!【ARFoundation自学01】搭建AR框架+检测平面+点击克隆立方体到地面=自信入门!_ar foundation教程-CSDN博客

一、 修改材质

(1)隐藏掉系统自带的黑色边框。

(2)重新制作一个渲染材质和Shader脚本

使用带Alpha通道半透明的PNG格式伯纹理,通过Shader脚本渲染这个半透明的纹理,将纹理透明区域镂空。

(3)编写一个渐隐的脚本,让边界的纹理渐隐

为了达到更好的视觉过渡。按照以上思路,我们直接对AR Default Plane预制体进行改造即可。

(1)删除AR Default Plane预制体上的Line Renderer组件。(这个是渲染黑色描边框的组件,删除就意味着不要描边)

(2)编写一个Shader代码,制作一张带Alpha通道半透明PNG格式纹理贴图在外部赋值给这个shader 代码!

Shader "Unlit/FeatheredPlaneShader"
{Properties{_MainTex ("Texture", 2D) = "white" {}_TexTintColor("Texture Tint Color", Color) = (1,1,1,1)_PlaneColor("Plane Color", Color) = (1,1,1,1)_ShortestUVMapping("Shortest UV Mapping Value", Range(0, 1)) = 1.0}SubShader{Tags { "RenderType"="Transparent" "Queue"="Transparent" }LOD 100Blend SrcAlpha OneMinusSrcAlphaZWrite OffPass{CGPROGRAM#pragma vertex vert#pragma fragment frag   #include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;float3 uv2 : TEXCOORD1;};struct v2f{float4 vertex : SV_POSITION;float2 uv : TEXCOORD0;float3 uv2 : TEXCOORD1;};sampler2D _MainTex;float4 _MainTex_ST;fixed4 _TexTintColor;fixed4 _PlaneColor;float _ShortestUVMapping;v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = TRANSFORM_TEX(v.uv, _MainTex);o.uv2 = v.uv2;return o;}fixed4 frag (v2f i) : SV_Target{fixed4 col = tex2D(_MainTex, i.uv) * _TexTintColor;col = lerp(_PlaneColor, col, col.a);    col.a *= 1 - smoothstep(1, _ShortestUVMapping, i.uv2.x);return col;}ENDCG}}
}

这个是一个材质脚本,我们写好以后创建一个普通材质,把脚本直接拖给材质即可!

调一下参数!Unlit/FeatheredPlaneShader的材质进行如下操作:

  • 将在PS里面做好的透明纹理赋值给给_MainTex属性(Texture)。
  • _TexTintColor的Alpha值设置为220,确保十字星的透明部分得以正确显示。
  • _PlaneColor的Alpha值设置为0,使平面背景完全透明。

做好的材质赋值给平面预制体AR Default Plane

上面基本完成了可视化平面的视觉效果更换!但是还可以进一步优化,让边缘平滑渐隐! 

2.创建一个普通C#脚本-边缘平滑渐隐

该脚本主要实现平面的渲染,并处理边界使其平滑渐隐。将AR Feathered Plane Mesh Visualizer挂载到AR Default Plane预制体上!

完成之后的预制体组件脚本应该如图3-5所示。编译运行,找一个富纹理平面进行平面检测,效果如图3-6所示。相比AR Foundation自带的平面可视化,个性化后的渲染视觉效果要好很多,而且在平面边界处也有一个渐隐的平滑过渡。

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.ARFoundation;[RequireComponent(typeof(ARPlaneMeshVisualizer), typeof(MeshRenderer), typeof(ARPlane))]
public class ARFeatheredPlaneMeshVisualizer : MonoBehaviour
{[Tooltip("The width of the texture feathering (in world units).")][SerializeField] float m_FeatheringWidth = 0.2f;public float featheringWidth{get { return m_FeatheringWidth; }set { m_FeatheringWidth = value; }}private ARPlaneMeshVisualizer m_PlaneMeshVisualizer;private ARPlane m_Plane;private MeshRenderer m_Renderer;private Material m_FeatheredPlaneMaterial;void Awake(){m_PlaneMeshVisualizer = GetComponent<ARPlaneMeshVisualizer>();m_Renderer = GetComponent<MeshRenderer>();m_FeatheredPlaneMaterial = m_Renderer.material;m_Plane = GetComponent<ARPlane>();}void OnEnable(){m_Plane.boundaryChanged += ARPlane_boundaryUpdated;}void OnDisable(){m_Plane.boundaryChanged -= ARPlane_boundaryUpdated;}void ARPlane_boundaryUpdated(ARPlaneBoundaryChangedEventArgs eventArgs){GenerateBoundaryUVs(m_PlaneMeshVisualizer.mesh);}void GenerateBoundaryUVs(Mesh mesh){int vertexCount = mesh.vertexCount;if (s_FeatheringUVs.Capacity < vertexCount) { s_FeatheringUVs.Capacity = vertexCount; }mesh.GetVertices(s_Vertices);Vector3 centerInPlaneSpace = Vector3.zero;for (int i = 0; i < vertexCount; i++){centerInPlaneSpace += s_Vertices[i];}centerInPlaneSpace /= vertexCount;float shortestUVMapping = float.MaxValue;for (int i = 0; i < vertexCount; i++){float vertexDist = Vector3.Distance(s_Vertices[i], centerInPlaneSpace);float uvMapping = vertexDist / Mathf.Max(vertexDist - featheringWidth, 0.001f);if (shortestUVMapping > uvMapping) { shortestUVMapping = uvMapping; }s_FeatheringUVs.Add(new Vector3(uvMapping, 0, 0));}m_FeatheredPlaneMaterial.SetFloat("_ShortestUVMapping", shortestUVMapping);mesh.SetUVs(1, s_FeatheringUVs);mesh.UploadMeshData(false);}static List<Vector3> s_FeatheringUVs = new List<Vector3>();static List<Vector3> s_Vertices = new List<Vector3>();
}

这是一个Unity C#脚本,名为`ARFeatheredPlaneMeshVisualizer`,用于为ARFoundation框架中的ARPlane对象添加一种特殊的视觉效果:根据平面边缘与中心的距离,为平面的顶点生成渐变的UV映射,从而实现类似羽毛边缘的过渡效果。该脚本依赖`ARPlaneMeshVisualizer`、`MeshRenderer`和`ARPlane`组件,并且通过响应ARPlane的边界变化事件来实时更新UV映射。下面为您详细解释脚本各部分的功能:

1. **命名空间和引用**:

   using System.Collections.Generic;
   using UnityEngine;
   using UnityEngine.XR.ARFoundation;
   ```
   引入所需命名空间,包括泛型集合、Unity基础类库以及ARFoundation相关API。

2. **类定义**:

   [RequireComponent(typeof(ARPlaneMeshVisualizer), typeof(MeshRenderer), typeof(ARPlane))]
   public class ARFeatheredPlaneMeshVisualizer : MonoBehaviour
   ```
   定义一个公共类`ARFeatheredPlaneMeshVisualizer`,继承自`MonoBehaviour`,并使用`[RequireComponent]`特性确保附着此脚本的游戏对象必须同时具有`ARPlaneMeshVisualizer`、`MeshRenderer`和`ARPlane`组件。

3. **属性定义**:

   [Tooltip("The width of the texture feathering (in world units).")]
   [SerializeField] float m_FeatheringWidth = 0.2f;
   public float FeatheringWidth
   {
       get { return m_FeatheringWidth; }
       set { m_FeatheringWidth = value; }
   }

   定义一个具有工具提示的私有变量`m_FeatheringWidth`,默认值为0.2f。使用`[SerializeField]`使其能在Unity Inspector面板中显示并编辑。同时提供一个公开的只读属性`FeatheringWidth`,用于外部访问和修改该值。`FeatheringWidth`决定了纹理边缘渐变过渡的宽度(以世界单位计)。

4. **成员变量**:

   private ARPlaneMeshVisualizer m_PlaneMeshVisualizer;
   private ARPlane m_Plane;
   private MeshRenderer m_Renderer;
   private Material m_FeatheredPlaneMaterial;
   ```
   定义私有变量,分别存储`ARPlaneMeshVisualizer`、`ARPlane`、`MeshRenderer`组件的引用以及关联的`Material`对象。

5. **Awake()**:

   void Awake()
   {
       m_PlaneMeshVisualizer = GetComponent<ARPlaneMeshVisualizer>();
       m_Renderer = GetComponent<MeshRenderer>();
       m_FeatheredPlaneMaterial = m_Renderer.material;
       m_Plane = GetComponent<ARPlane>();
   }
   `Awake()`方法在游戏对象初始化阶段调用,用于获取并存储所需组件的引用。

6. **生命周期方法**:

   void OnEnable()
   {
       m_Plane.boundaryChanged += ARPlane_boundaryUpdated;
   }

   void OnDisable()
   {
       m_Plane.boundaryChanged -= ARPlane_boundaryUpdated;
   }
   ```
   当组件启用时,注册`ARPlane.boundaryChanged`事件的处理函数`ARPlane_boundaryUpdated`。当组件禁用时,取消注册该事件,以避免内存泄漏和不必要的性能开销。

7. **ARPlane_boundaryUpdated()**:
   ```csharp
   void ARPlane_boundaryUpdated(ARPlaneBoundaryChangedEventArgs eventArgs)
   {
       GenerateBoundaryUVs(m_PlaneMeshVisualizer.mesh);
   }
   ```
   事件处理函数,当ARPlane的边界发生变化时调用。在此调用`GenerateBoundaryUVs`方法,传入`ARPlaneMeshVisualizer`组件提供的`Mesh`对象,以更新其UV映射。

8. **GenerateBoundaryUVs()**:
   ```csharp
   void GenerateBoundaryUVs(Mesh mesh)
   {
       // ... (详细解释见下文)
   }
   ```
   主要功能方法,负责计算并设置Mesh顶点的UV映射以实现羽毛边缘效果。下面详细解释内部逻辑:

   - 获取顶点数量和检查`s_FeatheringUVs`容量。
   - 使用`mesh.GetVertices`获取所有顶点坐标并存储在`s_Vertices`列表中。
   - 计算顶点集的中心点(质心)。
   - 初始化`shortestUVMapping`为最大浮点数,用于记录最小UV映射值。
   - 遍历每个顶点,计算其与中心点的距离(`vertexDist`),并据此计算UV映射值(`uvMapping`)。
     - UV映射值通过`vertexDist`与`featheringWidth`之差(取最大值为0.001f避免除以零)的比值得到,距离越远,UV映射值越大。
     - 如果当前UV映射值小于已记录的最小值,则更新`shortestUVMapping`。
   - 将计算得到的UV映射值(仅包含x分量,y和z设为0)添加到`s_FeatheringUVs`列表。
   - 将计算得到的最小UV映射值(`shortestUVMapping`)设置到材质的`_ShortestUVMapping`属性。
   - 使用`mesh.SetUVs`方法将`s_FeatheringUVs`列表中的UV映射值设置到Mesh的第二个UV通道(索引为1)。
   - 调用`mesh.UploadMeshData(false)`更新Mesh数据到GPU,完成UV映射设置。

9. **静态列表**:
   ```csharp
   static List<Vector3> s_FeatheringUVs = new List<Vector3>();
   static List<Vector3> s_Vertices = new List<Vector3>();
   ```
   定义两个静态列表,分别用于暂存计算得到的UV映射值和临时存储Mesh顶点坐标。

总结:`ARFeatheredPlaneMeshVisualizer`脚本为ARFoundation中的ARPlane添加了一种基于顶点距离的UV映射渐变效果,实现了类似羽毛边缘的过渡视觉效果。它监听ARPlane边界变化事件,动态更新Mesh的UV映射,确保在AR环境变化时能实时反映到渲染结果中。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring:事务(tx)

1. 简介 spring对jdbc进行封装&#xff0c;简化对数据库的操作 2. HelloWorld 1. 搭建模块 2.加入依赖 <dependencies><!--spring jdbc Spring 持久化层支持jar包--><dependency><groupId>org.springframework</groupId><artifactId>s…

力扣刷题--1528. 重新排列字符串【简单】

题目描述 给你一个字符串 s 和一个 长度相同 的整数数组 indices 。 请你重新排列字符串 s &#xff0c;其中第 i 个字符需要移动到 indices[i] 指示的位置。 返回重新排列后的字符串。 示例 1&#xff1a; 输入&#xff1a;s “codeleet”, indices [4,5,6,7,0,2,1,3] 输…

Clickhouse 嵌套数据类型总结—— Clickhouse 基础篇(三)

文章目录 创建嵌套类型的表插入读取数据在嵌套类型上使用数组函数 在 clickhouse 中存储嵌套类型的关键字是 Nested, 只支持一级嵌套。数据结构类似于在数据结构类似于在表的单元格里面嵌套“一张表格”&#xff0c;如下图所示&#xff1a; 嵌套类型是列存储&#xff0c;本质…

【传知代码】遵循人类指令的高质量图像修复(论文复现)

前言&#xff1a;在数字化时代的浪潮中&#xff0c;图像已成为我们生活中不可或缺的一部分。它们记录着我们的记忆&#xff0c;传递着信息&#xff0c;甚至塑造着我们的认知。然而&#xff0c;正如生活中难以避免的瑕疵&#xff0c;这些数字图像也时常因为各种原因出现损伤、失…

RangeNet++ 检测3D点云语义算法的详细配置和常见问题

配置环境&#xff1a; Ubuntu18.04 GPU&#xff1a;GeForce MX150 驱动&#xff1a;Ubuntu推荐的nvidia-driver-470 Cuda10.1 cudnn7.6.2 TensorRT 5.1.5.0GCC 7.5.0 运行代码&#xff1a; RangeNet 目录 目录 一、环境配置 1. Ubuntu 18.04 安装NVIDIA驱动 &…

基于Vue uni-app的自定义列表表格信息展示组件

摘要&#xff1a;随着软件技术的不断发展&#xff0c;前端开发面临着越来越多的挑战。特别是在业务场景复杂多变的情况下&#xff0c;如何提高开发效率和降低维护成本成为了关键。本文旨在探讨组件化开发在前端应用中的重要性&#xff0c;并以Vue uni-app自定义列表表格为例&am…

R语言lavaan结构方程模型(SEM)

结构方程模型&#xff08;Sructural Equation Modeling&#xff0c;SEM&#xff09;是分析系统内变量间的相互关系的利器&#xff0c;可通过图形化方式清晰展示系统中多变量因果关系网&#xff0c;具有强大的数据分析功能和广泛的适用性&#xff0c;是近年来生态、进化、环境、…

I.MX6ULL模仿 STM32 驱动开发格式实验

系列文章目录 I.MX6ULL模仿 STM32 驱动开发格式实验 I.MX6ULL模仿 STM32 驱动开发格式实验 系列文章目录一、前言二、模仿 STM32 寄存器定义2.1 STM32 寄存器定义简介2.2 I.MX6Ul 寄存器定义2.3硬件原理图2.4实验程序编写 三、编译下载验证 一、前言 使用 C 语言编写 LED 灯驱…

2024年中国金融行业网络安全市场全景图

网络安全一直是国家安全的核心组成部分&#xff0c;特别是在金融行业&#xff0c;金融机构拥有大量的敏感数据&#xff0c;包括个人信息、交易记录、财务报告等&#xff0c;这些数据的安全直接关系到消费者的利益和金融市场的稳定&#xff0c;因此金融行业在网络安全建设领域一…

SSL协议:网络安全通信的守护者

在网络通信迅猛发展的今天&#xff0c;数据安全和隐私保护变得尤为重要。安全套接层协议&#xff08;Secure Sockets Layer, SSL&#xff09;作为早期网络加密及身份验证的基石&#xff0c;为在线数据传输提供了安全保障。下面我们就来了解一下SSL协议。 SSL协议概述 SSL协议最…

[nextjs]推荐几个很好看的模板网站

最近在做网站,折腾了 vue 框架,然后发现了 nextjs 框架,感觉这个做出来的网站配色很好看,然后又开始研究这个 网站配色好看是因为用的 tailwindcss,找网站过程中,发现了几个很好看的模板网站,在这里推荐下,或许你也能用得上 推荐第一个网站是: https://tailspark.co/ 有组件,也…

前端项目性能优化:工程化环境中将图片转为base64(vite插件)

一、优化原理 通过将图片转为base64的形式来减少请求&#xff0c;实现性能优化。 考虑到过大的图片转为base64形式会导致加载时间过长&#xff0c;反而会影响性能&#xff0c;所以需要对转化的图片的大小进行限制。 每次去使用图片的时候都去手动转化一次是很麻烦的&#xf…

python--pycharm中将venv删除后怎么办

在终端中输入以下命令来创建一个新的虚拟环境&#xff08;可选&#xff09;&#xff1a; python -m venv venv 激活虚拟环境&#xff1a; Windows: .\venv\Scripts\activate选择自己项目的虚拟环境

Java 使用WebMagic爬取网页(简单示例)

框架简介 WebMagic是一个基于Java的开源网络爬虫框架&#xff0c;它提供了很多简单易用的API接口&#xff0c;可以帮助使用者快速构建出高效、可扩展的网络爬虫程序&#xff0c;WebMagic由四个组件(Downloader、PageProcessor、Scheduler、Pipeline)构成&#xff0c;核心代码非…

HLS入门(Xilinx Vivado 2019.2)——点亮LED仿真

HLS入门——点亮LED仿真 一、HLS简介&#xff08;一&#xff09;什么是HLS&#xff1f;&#xff08;二&#xff09;HLS能做什么&#xff1f;&#xff08;三&#xff09;HLS的使用&#xff08;四&#xff09;HLS的优势&#xff08;五&#xff09;HLS与VHDL/Verilog编程技术的关系…

在矩池云上使用StoryDiffusion的详细方法

StoryDiffusion 是由南开大学和字节跳动团队联合研发的&#xff0c;基于一致性自注意力机制生成长跨度图像和视频的新型扩散模型&#xff08;Consistent Self-Attention for Long-Range Image and Video Generation&#xff09;&#xff0c;使用者不需要进行额外训练&#xff0…

VBA技术资料MF158:获取系统的用户名

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套&#xff0c;分为初级、中级、高级三大部分&#xff0c;教程是对VBA的系统讲解&#…

ROS学习笔记(16):夹缝循迹

0.前言 在笔记的第15期对巡墙驾驶的原理进行了简单讲解&#xff0c;而这期我们来讲一下夹缝循迹&#xff0c;也常被叫follow the gap&#xff0c;也更新一些概念。 1.探索式路径规划与避障 1.概念 无预先建图的路径规划叫探索式路径规划&#xff0c;例如巡墙循迹和夹缝循迹&…

CTF网络安全大赛简单的web抓包题目:HEADache

题目来源于&#xff1a;bugku 题目难度&#xff1a;简单 题目 描  述: > Wanna learn about some types of headache? > Lets dig right into it! 下面是题目源代码&#xff1a; <!DOCTYPE html> <html> <head><meta charset"utf-8"&…

智能高效的IDE GoLand v2024.1全新发布 - 进一步升级AI辅助工具

GoLand 使 Go 代码的阅读、编写和更改变得非常容易。即时错误检测和修复建议&#xff0c;通过一步撤消快速安全重构&#xff0c;智能代码完成&#xff0c;死代码检测和文档提示帮助所有 Go 开发人员&#xff0c;从新手到经验丰富的专业人士&#xff0c;创建快速、高效、和可靠的…