visionOS空间计算实战开发教程Day 5 纹理和材质
在Day 4中我们使用了ImmersiveSpace并在其中添加了一个立方体,但对这个立方体我们只配置了长宽高,并没有做进一步的操作。
本文中我们会通过纹理和材质对这个立方体的六个面分别进行不同的绘制。首先我们将ImmersiveView分拆出来,先新建一个ImmersiveView.swift文件,这是一个视图文件,所以请选择User Interface下的Swift View完成创建,其中的内容待我们编写完ViewModel中的代码后再进行修改。
我们通过点击界面来打开沉浸式视图,所以需要一个ContentView.swift文件来编写常规的窗口页面,在其中添加一个Toggle开关,用于打开和关闭沉浸式视图。
import SwiftUI
import RealityKitstruct ContentView: View {@State var showImmsersiveSpace = false@Environment(\.openImmersiveSpace) var openImmersiveSpace@Environment(\.dismissImmersiveSpace) var dismissImmersiveSpacevar body: some View {NavigationStack {VStack {Toggle("Show ImmersiveSpace", isOn: $showImmsersiveSpace).toggleStyle(.button)}.padding()}.onChange(of: showImmsersiveSpace) { _, newValue inTask {if newValue {await openImmersiveSpace(id: "ImmersiveSpace")} else {await dismissImmersiveSpace()}}}}
}#Preview {ContentView()
}
首先我们定义了一个showImmsersiveSpace变量供Toggle按钮开关时使用。然后要打开和关闭沉浸式空间,我们可以分别使用@Environment中的openImmersiveSpace和dismissImmersiveSpace,通过onChange修饰符来监控showImmsersiveSpace变量的变化,在切换到打开时,就打开沉浸式空间。我们需要知道打开哪一个视图,所以使用了id参数,这个参数应与应用入口文件中所设置的一致。
接下来就编写入口文件:
import SwiftUI@main
struct visionOSDemoApp: App {var body: some Scene {WindowGroup() {ContentView()}ImmersiveSpace(id: "ImmersiveSpace") {ImmersiveView()}}
}
注意这里ImmersiveSpace中所添加的id与之前ContentView中的要保持一致,我们在后面会学到在同一个应用中也可以添加多个WindowGroup,同样通过配置id进行区分。
接下来是核心文件ViewModel.swift,
import SwiftUI
import RealityKit@MainActor class ViewModel: ObservableObject {private var contentEntity = Entity()func setupContentEntity() -> Entity {return contentEntity}func addCube() {guardlet texture1 = try? TextureResource.load(named: "Number_1"),let texture2 = try? TextureResource.load(named: "Number_2"),let texture3 = try? TextureResource.load(named: "Number_3"),let texture4 = try? TextureResource.load(named: "Number_4"),let texture5 = try? TextureResource.load(named: "Number_5"),let texture6 = try? TextureResource.load(named: "Number_6")else {fatalError("Unable to load texture.")}let entity = Entity()var material1 = SimpleMaterial()var material2 = SimpleMaterial()var material3 = SimpleMaterial()var material4 = SimpleMaterial()var material5 = SimpleMaterial()var material6 = SimpleMaterial()material1.color = .init(texture: .init(texture1))material2.color = .init(texture: .init(texture2))material3.color = .init(texture: .init(texture3))material4.color = .init(texture: .init(texture4))material5.color = .init(texture: .init(texture5))material6.color = .init(texture: .init(texture6))entity.components.set(ModelComponent(mesh: .generateBox(width: 0.5, height: 0.5, depth: 0.5, splitFaces: true),materials: [material1, material2, material3, material4, material5, material6]))entity.position = SIMD3(x: 0, y: 1, z: -2)contentEntity.addChild(entity)}
}
同样我们创建了setupContentEntity()方法,但并没有在方法里添加任何模型,而是将添加的工作交给了addCube()方法,整个方法虽然很长,但有大量重复的代码,分别为六个面设置不同的图片。
- 通过
TextureResource.load()方法设置了不同的纹理 - 接着使用
SimpleMaterial()创建了六个材质 - 通过材质的
color属性分别添加前面配置好的纹理
Number_1.jpg等图片请见我们GitHub的演示代码,我们先来说一下visionOS中的材质,常见的材质请见下图:

其中PhysicallyBasedMaterial也即PBR和SimpleMaterial是带光照信息的,而UnlitMaterial和VideoMaterial都是不带光照信息的。
在ModelComponent方法中,我们使用了mesh和materials参数,mesh参数我们同样使用了MeshResource.generateBox来创建一个立方体,不同的是这次我们指定了splitFaces参数,该参数设为true表示顶点不进行合并,因为我们要对六个面分别设置颜色或图像,不指定该参数六个面都会使用相同的材质,在本例中也就是都显示为1。
最后我们配置了position,这里x, y, z坐标轴方向示意如下:

接下来我们修改ImmersiveView.swift的内容如下:
import SwiftUI
import RealityKitstruct ImmersiveView: View {@StateObject var model = ViewModel()private var contentEntity = Entity()var body: some View {RealityView { content incontent.add(model.setupContentEntity())model.addCube()}}
}
这里的代码相对简单,就是在RealityView中展示ViewModel中所添加的模型。
在运行应用前将Info.plist文件中的Preferred Default Scene Session Role切换回Window Application Session Role。
点击Show ImmersiveSpace按钮,会得到如下界面:

再次点击按钮就会收起这个模型。
示例代码:GitHub仓库
其它相关内容请见虚拟现实(VR)/增强现实(AR)&visionOS开发学习笔记
相关文章:
visionOS空间计算实战开发教程Day 5 纹理和材质
在Day 4中我们使用了ImmersiveSpace并在其中添加了一个立方体,但对这个立方体我们只配置了长宽高,并没有做进一步的操作。 本文中我们会通过纹理和材质对这个立方体的六个面分别进行不同的绘制。首先我们将ImmersiveView分拆…...
低代码PaaS开发平台
目录 一、低代码概念 低代码目的 低代码核心功能 二、PaaS平台 PaaS服务的低代码平台 1.私有化部署,为数据安全保驾护航 2.业内领先技术,为开发强势赋能 3.超强集成能力,系统对接无忧 4.源代码交付,实现二开自由 三、小结 一、低代…...
阿里云99元服务器ECS经济型e实例性能如何?测评来了
阿里云服务器优惠99元一年,配置为云服务器ECS经济型e实例,2核2G配置、3M固定带宽和40G ESSD Entry系统盘,CPU采用Intel Xeon Platinum架构处理器,2.5 GHz主频,3M带宽下载速度384KB/秒,上传速度1028KB/秒&am…...
vue3-生命周期
🌈个人主页:前端青山 🔥系列专栏:Vue篇 🔖人终将被年少不可得之物困其一生 依旧青山,本期给大家带来vue篇专栏内容:vue3-生命周期 目录 vue3生命周期 vue3生命周期钩子 1.1 onMounted() 1.2 onUpdated() 1.3 onU…...
23. 深度学习 - 多维向量自动求导
Hi, 你好。我是茶桁。 前面几节课中,我们从最初的理解神经网络,到讲解函数,多层神经网络,拓朴排序以及自动求导。 可以说,最难的部分已经过去了,这节课到了我们来收尾的阶段,没错,生…...
挺扎心!好不容易有了一个offer,就因为背调出之前有仲裁记录,offer黄了,这已经是第二次了!...
仲裁记录会影响之后求职吗? 最近有一位程序员向我们讲述了他的遭遇: 大环境不好,好不容易有了一个offer,却因为背调出跟之前公司有仲裁经历,offer黄了,这已经是第二次因为这个原因黄offer了。 他说自己快抑…...
【brpc学习实践四】异步请求案例详解
注意 使用的还是源码的案例,添加个人注解。在前面的篇章我们讲解了客户端、服务端rpc构造的基本流程及同步、异步的案例基础之后,再理解此案例就容易了。 想直接看案例实现请看: server端实现 client端实现 服务端要点概览 controller ser…...
git命令 cherry-pick
参考:https://blog.csdn.net/weixin_42585386/article/details/128256149 https://blog.csdn.net/weixin_44799217/article/details/128279250 merge和cherry-pick的区别: merge:是把某一个代码分支完全合并到当前的代码分支。完全合并的意…...
手动添加扩展到composer中
如果拓展包第三方没有提供composer安装方式,可以将扩展包手动添加到vendor目录下 将拓展包复制到vendor文件夹下 拓展包需要配置好composer.json文件中的autoload和包里面的命名空间 配置vendor/composer/autoload_psr4.php文件 xx\\xx\\ > array($vendorDir…...
TCP/IP
分层模型 TCP 传输控制协议 UDP 用户数据包协议 四层 应用层 负责发送/接收消息 传输层 负责拆分和组装 .期间会有编号 网络层 TCP/UDP 属于网络层, 不会判断和处理编号 数据链路层 以太网 ,网络设备 TCP 连接 TCP连接需要端口,进行通信 Java 通过Socket 接收消息 发送 …...
NX二次开发UF_CAM_set_clear_plane_data 函数介绍
文章作者:里海 来源网站:https://blog.csdn.net/WangPaiFeiXingYuan UF_CAM_set_clear_plane_data Defined in: uf_cam_planes.h int UF_CAM_set_clear_plane_data(tag_t object_tag, double origin [ 3 ] , double normal [ 3 ] ) overview 概述 De…...
如何在 ASP.NET Core 中使用 Quartz.NET
当我们在web开发中,常常会遇到这么一个需求,在后台执行某一项具体的任务,具体的说就是这些任务必须在后台定时执行。 Quartz.NET 是一个开源的 JAVA 移植版,它有着悠久的历史并且提供了强大的 Cron 表达式,这篇我们就…...
阿里云3M固定带宽服务器速度快吗?是否够用?
阿里云服务器3M带宽下载速度是384KB/秒,上传速度是1280KB/s(折合1.25M/秒),3M固定带宽够用吗?对于一般流量不是太大的个人博客、企业官网、论坛社区、小型电商网站或搭建个人学习环境或测试环境是完全够用的࿰…...
跨越行业边界,CodeMeter护航AI领域安全与合规
在人工智能(AI)技术如ChatGPT的推动下,工业视觉、医疗诊断和智能驾驶等领域正在经历重大变革。这些技术不仅扩大了应用范围,也带来了数据安全、软件授权保护和合规性等新挑战。 AI工业视觉正在推动制造和自动化的快速发展&#x…...
地磁传感器在城市交通智能监控系统的作用
地磁传感器的功能作用 地磁传感器的功能是相当强大的:当驾驶员把车辆停在车位上,地磁传感器能自动感应车辆的到来并开始计时;待车辆要离开时,传感器会自动把停车时间传送到中继站进行计费。因此,解决停车收费效率低下…...
自动解决IP冲突的问题 利用批处理更改末位IP循环+1直到网络畅通为止 解放双手 事半功倍
好久没出来写点什么了,难道今天有点时间,顺便把这两天碰到的问题出个解决方法吧。 这几天去客户那儿解决网络问题,因为客户的网络是固定的静态IP,因为没做MAC绑定,IP固定在本地电脑上,只要上不了网…...
目标检测 Faster RCNN全面解读复现
Faster RCNN 解读 经过R-CNN和Fast RCNN的积淀,Ross B. Girshick在2016年提出了新的Faster RCNN,在结构上,Faster RCNN已经将特征抽取(feature extraction),proposal提取,bounding box regression(rect refine)&…...
HarmonyOS ArkTS 基础组件的使用(四)
1 组件介绍 组件(Component)是界面搭建与显示的最小单位,HarmonyOS ArkUI声明式开发范式为开发者提供了丰富多样的UI组件,我们可以使用这些组件轻松的编写出更加丰富、漂亮的界面。 组件根据功能可以分为以下五大类:…...
elasticsearch 7安装
问题提前报 max virtual memory areas error max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144] 如果您的环境是Linux,注意要做以下操作,否则es可能会启动失败 1 用编辑工具打开文件/etc/sysctl.conf 2 …...
opencv 存储bgr格式/同理可类推yuv
需求背景 开发rk3588 音视频硬件编解码,然后看见他的输入文件格式。。 只能是裸的文件。不能是压缩过的。就是不能是jpg/png这种格式,只能是以下的图像/视频 的存储格式.那么我没有这个格式的,以前hi3559的bgr格式和他要的也不太一致&#x…...
抖音视频批量下载难题如何破解?高效工具让你的内容收集效率提升10倍
抖音视频批量下载难题如何破解?高效工具让你的内容收集效率提升10倍 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser f…...
虫草贵族变平价?深圳福田这家店做到了
家人们,养生界搞大事了!金尊草带着IP金小尊空降深圳福田——第2家门店(皇庭广场店)正式开业。这一次,金尊草让冬虫夏草从“保健品刺客”变成了“人人都吃得起滋补品”。金尊草品牌slogan“吃得到的冬虫夏草”尊嘟假嘟&…...
HCIA考试题型 题量详解,考生必看
今天咱们来聊聊HCIA考试最实在的问题:到底考什么题型?题量多少?怎么备考才不踩坑?一、HCIA 考试基础整体概况所有 HCIA 专业方向都是统一标准:考试形式:线下闭卷机考,只考一门理论笔试ÿ…...
从星巴克不进意大利,聊聊广告拍卖里的‘帕累托最优’:为啥平台总想让你多赢一点?
从星巴克不进意大利,聊聊广告拍卖里的‘帕累托最优’:为啥平台总想让你多赢一点? 走在米兰的街头,你会发现一个有趣的现象——这座以咖啡文化闻名的城市,竟然找不到一家星巴克。这并非偶然,而是星巴克主动选…...
高速数字设计中的信号完整性挑战与解决方案
1. 信号完整性基础概念解析信号完整性(Signal Integrity)是高速数字系统设计中最为核心的工程挑战之一。简单来说,它描述的是电信号在传输路径中保持其原始时序、幅度和波形特性的能力。在理想情况下,数字信号应当具有干净快速的跳…...
从零开始将OpenClaw助手工具接入Taotoken的完整步骤
从零开始将OpenClaw助手工具接入Taotoken的完整步骤 1. 获取Taotoken API Key与模型ID 在开始配置前,需要先在Taotoken平台获取API Key和模型ID。登录Taotoken控制台后,在「API密钥」页面可以创建新的密钥,建议为OpenClaw单独创建一个密钥以…...
从GroundingDino推理到Open-GroundingDino训练:我的环境配置与验证集精度为0的踩坑实录
从推理到训练:Open-GroundingDino实战中的环境配置与验证集精度问题深度解析 当我在深夜第三次尝试启动Open-GroundingDino训练脚本时,终端上闪烁的"validation AP: 0.000"让我陷入了沉思。这不是一个简单的环境配置问题,而是一系…...
Phi-3-mini-4k-instruct-gguf惊艳效果:中文谜语创作+难度分级+谜底提示生成
Phi-3-mini-4k-instruct-gguf惊艳效果:中文谜语创作难度分级谜底提示生成 1. 模型简介与部署验证 Phi-3-Mini-4K-Instruct是一个38亿参数的轻量级开源模型,采用GGUF格式提供。这个模型在参数少于130亿的模型中展现出最先进的性能,特别擅长常…...
APA 7th格式终极解决方案:3个技巧解决Word引用难题
APA 7th格式终极解决方案:3个技巧解决Word引用难题 【免费下载链接】APA-7th-Edition Microsoft Word XSD for generating APA 7th edition references 项目地址: https://gitcode.com/gh_mirrors/ap/APA-7th-Edition 还在为APA 7th格式调整而烦恼吗…...
本地AI应用实践:基于开源模型与伦理框架的隐私优先解决方案
1. 项目概述:一个社区驱动的本地AI应用实践平台 如果你和我一样,对大型语言模型(LLM)的能力感到兴奋,但又对完全依赖云端服务心存疑虑——无论是出于数据隐私的考虑,还是对服务稳定性和成本的担忧——那么“…...
