淘宝人生专属“小屋”——虚拟人和虚拟场景技术探索

简介: 本文将分享来自淘宝人生团队齐力打造的新玩法——“人生小屋”背后的技术方案,详细介绍如何使用3D渲染引擎从0到1搭建虚拟场景、控制虚拟角色、实现人景交互、优化渲染效果等。笔者在其中主要负责了小屋3D室内场景的搭建部分。非常欢迎大家给我们提出建议,探讨交流。

image.png

淘宝人生,是一款手机淘宝App内可以玩转虚拟形象的轻游戏,包含了捏脸、穿搭、美颜、拍照等功能,逛街、家园等玩法。在它核心玩法日益成熟后,我们希望虚拟角色可以和虚拟场景进行交互互动,提供一些新的社交场景和玩法。因此,我们向虚拟人和虚拟场景方向展开了新的技术探索,开发“人生小屋”玩法。(上图展示了淘宝App中人生小屋的入口路径:搜淘宝人生跳转 -> 右侧去旅行 -> 人生小屋icon,欢迎大家前来体验!!

  1. 增加游戏的可玩性。给淘宝人生提供一个“家”的场景,在该场景中可以进行室内家具摆放、装饰,人与家具交互,成为用户串门的场所,提供新的社交场景和玩法。
  2. 丰富淘宝人生旅行玩法。通过旅行玩法,用户可获取家具材料,合成家具,在【家】中进行摆放,提升旅行玩法的游戏性和时长。


image.png

人生小屋基于我们团队的自研web3d渲染引擎Hilo3d开发,使用webgl渲染到前端的canvas画布上。笔者的主要工作内容即为绿框中的业务功能,概括来讲,可以划分为:室内场景搭建、角色管理、游戏逻辑开发 三大块。下面,将会分享在一步步搭建过程中,考虑以及采用的各个技术方案。


 室内场景

  • Step 1:加载室内场景

首先,从场景搭建开始。


image.png

如何加载房屋3D模型,整个过程概括来讲,大致经历这几个步骤:


  1. 首先使用一些3d软件,比如MAYA,制作出3d房屋模型,把过程产物暂存在OSS,并提供预览工具
  2. 给模型上贴图,用Photoshop制作贴图,把贴图上传至CDN
  3. 导出一个USD文件
  4. 使用houdini 程序化生成阴影和lod类型的gltf
  5. 我们使用GLTF作为我们的资产标准
  6. 最后,使用hilo3d 引擎,通过GLTF Importer导入glTF模型

image.png

  • Step2:加载家具模型


同理,使用和房间模型相似的步骤,可以用同样的方式去加载各个家具的模型:


image.png

在加载了所需的各个模型后,开始搭建整个场景的结构:


初始化一个场景节点作为根节点,然后,把各个平面节点加入场景节点中,再把属于各个平面的家具放入平面节点中。之所以会按照平面先划分平面节点,是为了便于统一操作平面节点,比如在某些情况下,我们想将地板的家具全部隐藏,那么选择直接隐藏地板节点即可。


image.png

  • Step 3:加载相机


3d场景渲染的核心三要素:scene, camera, renderer ⇒ render the scene with camera我们所看到的的场景内的画面,就是渲染器render根据新的相机对象参数渲染出场景图像,更简单的来讲,即将相机捕捉到的场景帧,通过渲染器渲染到画布上展示给用户。

相机选择

下一步,加载相机。在相机的选择方面,有两个最常用的相机:透视相机和正交相机。

正交相机:元素在屏幕上的大小与离相机的距离无关,按照正投影算法自动计算几何体的投影结果。

image.png

透视相机:透视相机看见的结果除了与几何体的角度有关,还和距离相关。透视相机能够更模拟出人眼所看到的世界,有一种近大远小的效果。比如你观察一条铁路距离越远你会感到两条轨道之间的宽度越小。在3D场景的渲染中,往往会使用透视投影照相机。


image.png

image.png

视场角:相机视锥体的两端的夹角。视场角的大小决定了视野范围,视场角越大,视野就越大。目标物体超过这个角就不会被收在镜头里。


image.png

相机控件OrbitControl


在选好了相机后,现在在画布上已经可以看见当前相机视角捕捉的3d室内场景了,但是这是一个静态的模型。我们下一个需求点,肯定是希望这个模型可以随着鼠标转起来,也就是我们鼠标左右移动,可以切换视角,看到房屋的各个角落。于是,我们引入orbitcontrol控件。


orbitControl可以使相机可以围绕目标进行轨道运动,以场景中心为中心,左右拖动屏幕会让镜头围绕着场景中心旋转,镜头始终会看着中心点。


它的原理是OrbitControls可以控制浏览器实时监控鼠标或键盘触发事件,比如鼠标左键发生拖动,那么拖动的距离就会改变相机的数据:比如位置和拍摄角度, 渲染器就会根据新的相机对象参数渲染,渲染出来的图像就会变化。

观察视频,我们有了新的需求点:当相机在房间顶部,俯视这个房间的时候,视野可不可以变大,可以看见整个房间,这就涉及到相机视野的变换。

相机视野变换:调整FOV

image.png

由于我们使用的是webgl默认的右手坐标系,其实相机的上下移动,可以认为是绕着x轴的旋转角度。


因此,在实现的时候,我们把相机的fov和相机在x轴的旋转角度rotationX关联起来。


  • Step 4:特定mesh隐藏


至此,我们可以看一下我们加载的室内模型:

我们可能会提出一些疑问:

  1. 为什么相机旋转到墙壁背后的时候,墙壁自动被隐藏了?这是因为我们在搭建3d模型的时候,把墙壁建成了单面墙,也就是只能在墙壁的正面才能看见墙。
  2. 当我们的视角切换到入户门后时,但是这个门框并没有被隐藏?怎么也能隐藏掉门框?


image.png

 角色控制


  • Step 1:加载虚拟人并使用摇杆操控


如何创建一个虚拟角色,这是一个有很多可以探究的领域,我们团队在第十六届D2论坛上分享过关于【虚拟偶像诞生记】的专题分享,如果大家感兴趣可以去更详细的了解一下,附上相关文章链接:《虚拟数字人行业现状和技术研究》


加载虚拟人后,我们使用joystick摇杆去操控人物在室内场景内的自由移动:

在这里,我们发现了问题:操控人物走动起来后,这个相机的视角没有转动,那么操控人物就能自由的走出我们的视野。


  • Step 2:相机跟随


因此,为了能让人物能始终在我们的视野中,我们让相机跟随人物节点移动。具体做法:

把场景的相机挂载到人物node节点上,以它为父节点。相对于人物节点,相机有一个固定的偏移量,让相机始终位于人物的正前方,并且距离人物一定的距离。那么当操控人物节点移动的时候,相机的节点也就会同步跟随移动,并且始终保持人物在最中心。


我们来看看最终实现的虚拟角色控制:

 游戏逻辑


在完成了室内场景加载和虚拟角色加载后,我们来到了游戏逻辑开发部分。首先,我们来实现对家具的操作,先来看看家具是如何选中的?


  • Step 1: 家具选中


我们考虑到了一种业界非常通用的方法:raycast光线投射。


raycast多用于实现物体选择或相交。用一句话概括来讲:通过三维空间中相机视点与鼠标在屏幕上的位置的连线,形成一条直线,捕获与此直线相交的空间中的物体,即为选中的物体。
具体计算步骤:

  1. 第一步,需要确定射线方向,也就是确定射线的起点(比如常用的相机世界原点)
  2. 然后确定射线终点:也就是鼠标点击处。计算点击像素点坐标是世界坐标中的位置
  3. 知道起点和方向就可以得到一条无限长的射线,使用点击的像素点的世界坐标减去相机位置,标准化后得到方向矢量(射线的方向)
  4. 再把射线先和检测物体的包围和求交,检测是否相交。
  5. 如果一条射线和多个物体相交,则把相交的物体按照深度排序返回。


所以怎么去选中家具?
在鼠标点击处投射出屏幕射线,检测物体为家具,返回与家具碰撞的结果


  • Step 2:家具拖拽移动


第二步: 如何能拖拽家具,在我们的小屋内进行移动?

最核心的点在于:如何得知鼠标拖拽位置的世界坐标?从而实现家具随着用户触摸点的移动而移动的效果(拖拽效果)。

我们同样可以使用raycast,创建出一条相机到点击处的射线,只是此时,检测物体变成了地板。那么,当鼠标/触摸点移动的时候,就可以获取到鼠标在地板上的具体位置,然后把家具中心移动过去,实现家具拖拽的效果。


0:10


  • Step 3:人物与家具碰撞方案


第三步,当人物移动后,人物与家具如何实现碰撞?


我们首先考虑了是否可以采用上一节所讲的raycast方法,上一节讲了raycast是一种检测碰撞相交的方案。更具体的来讲,在这种情况下,射线的发射源变成了人物,射线方向变成人物走动的方向,而检测物体变成了场景内摆放的所有家具或墙壁。以这种方法,我们可以检测到人物在走动过程中,与各个家具的碰撞情况。

image.png

然而,我们不得不考虑到一个问题:随着室内家具的逐渐增加,每次碰撞检测都会需要遍历检测物体,即场景内全部家具的节点-> 这会带来一个问题:性能不佳。经过我们实验,当室内有大量家具时,低端机达不到30fps。


因此,我们寻求了其他的方案:格子碰撞。

我们会以地砖格子为单位,使用二维数组去描述地砖信息,保存地砖上相应家具信息。


我们保存了一张看不见的逻辑层。这个层的大小和地板等大,并且也进行了格子划分,主要目的就是为了碰撞检测,使用一个数组描述信息。


我们会以地砖格子为单位,比如将地板划分为n*n个格子,使用二维数组去描述地砖信息,假设家具所占地砖面积为x*y,那么就在这一片的地砖上保存相应家具信息。用这种方式,我们就可以实现人物和家具的碰撞,检测地图中人物是否碰到了NPC或者障碍物。


  • Step 4:人物与家具交互


至此,我们的人物可以与家具发生碰撞了。下一步,碰撞到的家具若是床,若是椅子,我们自然希望我们的人物可以实现与家具的交互:上床躺下 / 椅子坐下。

于是,我们在家具可以交互的位置,比如床的两侧,添加了动作触发点。当人物走动到足够靠近家具的动作触发点,出现动作按钮,点击后,将以动画播放的形式,让人物实现上床的一系列动作。


假设说场景内有n个光源:

第一个光源,spotlight,也就是视频中地上这个圆圈的光源,它会对整个场景产生一个shadow map。

第二个光源,directional light,它也会产生一个shadow map。

......


若有n个光源,则有n个shadow map。

最终将n次渲染的阴影结果进行合并,每个mesh渲染的时候,都会读取n个shadow map。

这也就是为什么这个天猫的模型,它同时会拥有来自spot light和来自directional light这两个阴影。

因此实际上,阴影可以被认为是贴图的叠加。

然而,这种传统的实时渲染,大家可以预见到,由于每个mesh渲染都要读取n个shadow map,它会需要大量的计算和性能。


  • what is a shadow map?


因此,我们可以回过头看看对于Shadow map 阴影贴图的概念定义。所谓 ”贴图“,你可以想象成 ”一层层窗户纸“。

假设现在有一个窗户,你可以一层一层的粘贴不同透明度的窗户纸,每一层窗户纸都会叠加到之前的那一层,最终窗户纸所呈现的效果是所有窗户纸最终合并后一块呈现的效果。


  • 如何降低阴影所需性能?(小屋中家具阴影)


如前面讲的,传统的实时渲染会需要大量的计算和性能,有降低阴影所需性能的方案吗?

方案1:可以有多个灯光,但只有一个平行光可产生阴影

方案2:使用 光照贴图 或 环境光照遮挡贴图 来预先计算离线照明的效果 --- 比如:床缝间的这些家具自阴影

方案3:使用 假阴影,添加一个平面放到物体下方的地面上,同时赋予一个看着像阴影的纹理图片材质。具体做法,会添加一个面光源,置于家具的顶部,向下投影出家具底部的阴影。


:20可以看出,在小屋中添加家具阴影时,对针对单个家具,进行离线渲染烘焙,因此大大降低了所需性能。


  • 小屋中人物阴影渲染


同理,我们在添加人物阴影时,可以在人物的头顶放一个面光源,投射到地面上,添加一个平面放到人下方的地面上,同时赋予一个看着像阴影的纹理图片材质。


然而,不同于家具阴影允许的离线渲染,人物阴影必须要求一个实时渲染。因为人物在各个动作、姿势、服饰变化的时候,底部的渲染阴影会随之变化。如何实现人物阴影实时渲染?我们使用离屏渲染Off-Screen Rendering。在这里不再非常详细展开,感兴趣的可以去了解一下GPU屏幕渲染的两种方式:

  1. On-Screen Rendering
  2. Off-Screen Rendering

相关文章
掌握销售之道:深入学习ERP系统的销售与客户关系管理模块
掌握销售之道:深入学习ERP系统的销售与客户关系管理模块
952 8
|
6月前
|
前端开发 测试技术 API
一文掌握软件分支管理
本文详细介绍了软件分支管理的实践经验,结合具体项目案例,从版本号、分支命名、标签管理到合并策略等方面展开。通过清晰的规则和流程图示,帮助团队避免版本混乱,提升研发效率。强调主干与开发分支的核心作用,同时提醒合理控制分支数量,确保协作顺畅。适用于不同类型的项目,助力团队建立适合自身的版本管理体系。
995 69
一文掌握软件分支管理
|
8月前
|
缓存 安全 API
API 接口开发与合理利用:构建高效、安全、可维护的数字桥梁
本文全面解析API接口的设计、优化与安全维护。API作为系统间交互的标准化契约,核心价值在于解耦系统、提升复用性和构建开放生态。设计时需遵循六大原则:明确输入输出、关注单一职责、实现自我表达、确保功能无重叠、保障幂等性及合理版本化。性能优化从批量处理、异步调用、并行执行等方面入手,同时结合缓存、池化技术和SQL优化提升效率。安全性涵盖加密传输、加签验签、Token认证、防重放攻击及限流熔断等十大要点。最后,通过文档自动生成、日志体系和版本管理确保接口可持续迭代。优秀的API应以契约优先、演进思维和防御心态为核心,成为系统的数字资产,支持内外部高效协作与生态建设。
|
9月前
|
存储 人工智能 物联网
云计算助力医疗信息化,推动智慧医疗新模式。
云计算正深刻改变医疗行业,通过高效数据存储、管理与共享,优化医疗资源分配,推动远程医疗发展。它解决了“数据孤岛”问题,强化了数据安全与隐私保护,同时助力智慧医疗建设,降低信息化成本并提升服务效率。未来,云计算将与5G、AI等技术融合,进一步促进医疗服务智能化与规范化,为医疗行业带来全新可能。
480 7
|
7月前
|
数据采集 Web App开发 JavaScript
Python爬虫如何获取JavaScript动态渲染后的网页内容?
Python爬虫如何获取JavaScript动态渲染后的网页内容?
|
传感器 物联网 数据挖掘
新技术趋势与应用:物联网与虚拟现实的未来发展###
随着科技的迅猛发展,物联网(IoT)和虚拟现实(VR)已成为引领未来的重要技术趋势。本文旨在探讨这两项新兴技术的发展趋势和应用场景,通过分析当前技术现状、挑战及未来前景,揭示物联网和虚拟现实在各领域的潜在影响和应用价值。研究表明,物联网在智能家居、智慧城市、工业自动化等方面具有广泛的应用前景;而虚拟现实则在游戏娱乐、教育培训、医疗健康等领域展现出巨大的潜力。本文认为,随着技术的不断进步,物联网和虚拟现实将深度融合,为社会经济发展带来新的机遇和挑战。 ###
527 59
|
人工智能 机器人 vr&ar
Midjourney高效使用技巧总结(二)
这篇文章总结了Midjourney AI绘画工具的高效使用技巧,包括常用指令/参数、实操案例和参考网站,帮助用户更好地掌握如何使用Midjourney进行艺术创作。
Midjourney高效使用技巧总结(二)
|
缓存 负载均衡 算法
HTTPS对性能的一些影响
HTTPS对性能的一些影响
752 9
|
存储 编解码 Linux
rodert教你学FFmpeg实战这一篇就够了 - 音视频处理入门篇
rodert教你学FFmpeg实战这一篇就够了 - 音视频处理入门篇
293 1
|
设计模式 安全 API
C++视角下的Qt按钮:从基础应用到高级定制(三)
C++视角下的Qt按钮:从基础应用到高级定制
863 0