从踩坑到填坑|淘宝Web 3D应用与游戏开发实战

简介: 本文是淘宝前端技术专家——徐乾伟(烧鹅)分享的淘宝 Web 3D 应用与游戏开发实战,这个话题在业界被谈及得比较少。今天将会从移动、3D、游戏三种交叉的话题来和大家探讨。接下来我们一起从初试 Web 3D、使用 WebGL、工作流相关的游戏编辑器三个部分来了解吧~

image.png

作者|徐乾伟(烧鹅)
出品|阿里巴巴新零售淘系技术部

导读:本文是淘宝前端技术专家——徐乾伟(烧鹅)分享的淘宝 Web 3D 应用与游戏开发实战,这个话题在业界被谈及得比较少。今天将会从移动、3D、游戏三种交叉的话题来和大家探讨。接下来和小编一起从初试 Web 3D、使用 WebGL、工作流相关的游戏编辑器三个部分来了解吧~

讲师介绍

image.png

徐乾伟(烧鹅)-淘宝前端技术专家,来自淘宝虚拟互动团队,这个团队主攻 3D /游戏/ VR / AR 。其中,我们有一个小团队叫斜杠实验室,主攻 Web 方向上的动画和 3D 技术。

为什么我们会在这样交叉领域去发力做一些事情?去年的双十一淘宝去年交易额多少?一千多亿,其中有 80% 的 GMV 是来自移动端的,简单地理解就是说我们公司在电商领域 80% 的钱是通过手机客户端赚取的,而不是 PC 。这就是为什么在我们要在移动端做 3D/VR/AR 的应用。

初试Web 3D

有一句话叫:给我一个支点,我就能撬动地球。

很多人都做过 2D 游戏, 3D 最大的区别就是多了一根 Z 轴,而给我一个 Z 轴我就能创造 3D 世界。很多做前端的同学对 3D 这个事情是有误解的,比如说 HTML5 中的 Canvas 有两个上下文,大家认为 2d Context 只能画 2D,WebGL context 才能画 3D ,这是一种误解。

image.png

其实 3D 和 2D 并不是由绘图引擎来决定的,而是由数学家决定的。假如我们要画这样的曲面会怎么画呢?

首先有描述这个面的公式,这个公式根据 X、Y 入参算出 Z 的坐标值,假设 Z 越大颜色越红,Z 越小颜色越绿,画出来是这样的。如果 X、Y、Z 乘以一种神奇的东西叫矩阵(矩阵是数学家发明的),这是 3×3 的旋转矩阵,把每个点都乘一下,然后画到屏幕上得到的结果就是这样的。

大家是不是一脸懵逼呀~

关于如何用 Canvas 2d 绘制 3D 曲面,以后再详细讲解,我有一段时间写过 CSS3D 的库,就是用 glMatrix 数学库做出非常酷炫的效果。

使用 Web GL

image.png

2016 年双十一我们做过一个小游戏,不知道大家有没有玩过?

这个游戏是用 Canvas 2d 绘制,就是用的 glMatrix 数学库画实现 3D 效果。当时为什么用 Canvas 2d 呢?我们淘宝市场部的同学说我们要做 3D ,因为 pokemongo 做了一个 3D 的,但是你这个东西最后要给我搞到 iPhone 4 上去。大家知道 iPhone 4是不支持 WebGL 的,而当时开发时间非常紧张,我只能用 Canvas 2d 的方案。

如果点了主场景中的猫,就会进入一个 AR 捉猫的环境。这个不是 web 渲染,因为当时移动端的 web 还不具备获取摄像头数据的能力,所以当时 AR 只能用 Native 的 3D 引擎渲染,叫 T3D,顾名思义 Taobao 3D 。另外还有一个比较有趣的 AR 场景,叫“黄金猫”。黄金猫在双十一前后三天会出现在银泰或者苏宁的商场上方,你只要抢到了这只猫至少有一百块钱的红包奖励。

难点一:建筑模型的制作,我们的设计师是个平面设计师,不会做 3D ,他当时给我的图是这样的,你看着办吧,我当时花了整整一天时间做模型。
**
难点二:地面算法**,这个地面是六边型的结构,要把地面从地球坐标系转换成 3D 世界里的场景,会分几步。我们小时候都看过世界地图,怎样把一个球形的面投射到平面上呢?

这种投影叫做墨卡托投影(Mercator projection)。这个投影算法的代码是服务端拷给我的,因为要保持前后端算法一致,我复制了后端的投影算法。相比墨卡托投影,这是简化的算法,因为要求看到周围的猫是在五十米左右,所以精度并不是特别高,简单的算法就能够满足了。

image.png

当时的视角是这样的,以用户当前的位置经纬度为中心,辐射一圈就可以看到周围有多少只猫。

这里的六边型地面如果用 X、Y 两个轴的算法去计算其实是比较慢的,我当时看了一篇论文,这是一个斯坦福的同学花了二十年研究六边型的算法,他本质上是以夹角为 120 度的 X、Y、Z 三个轴为坐标轴算,相比算 X、Y 两个轴的算法快很多。上面还有很多基于这个基础算法拓展的算法如寻路等。

好不容易跨过了双十一的坎,我们已经看到 Canvas 2d 的方案在模型输入和绘制性能方面都是非常弱的。
如何继续开发 3D 类的游戏呢?可能大家会问,WebGL 在 PC 上都不行,在手机上行不行呀?我跟大家说,现在完全没问题,我们在上亿台同时在线的设备上都试过了,前提是要做一下 WebGL 能力检测。 PC 还有一些古董浏览器不支持 WebGL ,反而手机比 PC 发展快得太多。

image.png

大家之前理解了 3D 的概念, 3D 不是绘图引擎的功能, 3D 是数学的概念。那 CPU 绘图与 GPU 绘图有什么区别呢?GPU 是并行处理每一个像素的。

我们刚开始尝试 WebGL 小心翼翼,因为怕给手淘带来影响,事实上也造成比较大的 Crash 。

2016 年的圣诞节,市场部同学说要不在手淘里下一场雪吧,那就下了。后面我会和大家介绍下这场雪的代价。我们还尝试做类似于右边这种模型粒子动画,这是一只天猫的模型。这两个都是粒子系统,因为我们刚开始不知道怎么做复杂的 3D 渲染,我们只能从最基础的绘制“点”出发去尝试。

image.png

我们团队有一种叫 PopLayer 的技术,可以在当前 Native View 上面随时弹出一层 Web View。比如之前搜一下鹿晗出弹幕,还有明星打电话,都是通过 PopLayer 技术实现的。

上文提到,在淘宝首页的 Poplayer 里 下一场雪导致了大面积的客户端Crash 。原因是 iOS 下的 UIWebView 使用 webgl 渲染时,WebCore 会调用到 OpenGL ES 进行渲染,而苹果发现有在后台调用 OpenGL ES,就会直接结束 App。

知道 RequestAnimationFrame API 吗?解法就是监测当前用户退出后台或当前页面不可见时,会把 RequestAnimationFrame 停止。

小倩也提到过 Page Visibility 方面的 API ,我们发现安卓是支持这个 API 的, 但 IOS 还是需要调 Js Bridge接口来监听 App 的是否退后台的状态。接着,我把游戏主循环(或者动画主循环)停下来之后还发现一些用户会 Crash 。最后我发现一件非常神奇的事情~这个代码大家都知道,它是用来获取Canvas的WebGL context,这行代码为什么Crash呢?我们翻了 Webkit 的源码发现它有一个 reshape 函数,reshape 会通过 GPU 获取当前画布的高宽,所以它还是会 Crash 。

接下来将会分享 3D 之旅我们的心情,以及我的思维是如何进化的。

2017 年的造物节时我们做了真正意义上的 3D 应用,当时跟英国一家设计公司合作叫 FRAMESTORE ,这个电影(《奇异博士》)大家知道吧,特效就是他们设计制作的。

image.png

FRAMESTORE 当时给我的东西是这样的,俯视图是这样的,灯光是这样打的。虽然他们在影视特效领域非常牛逼,但是他们也没做过 Web 应用。而我当时也不知道怎么和设计团队合作,还是我的老方法手写代码。他们给我的模型,我当时也不知道其他高级的格式,只知道 Obj + Mtl 。如果发现 WebGL 渲染有问题,我们就去代码里找原因,模型引用的材质对不对,贴图对不对。我们要翻代码看一下是不是引用错了。工作流的问题在这个项目中没有解决,但是促使我开始寻找问题的解法。

这个项目还有一个性能问题,广告牌发光效果,我第一个想到的是后处理(Post Processing),大家不理解的话,可以把它当作实时滤镜,如果在手机屏幕这么大的 Bloom 滤镜是会卡死的。我当时的方案是在每块广告牌上写一个独立的 Shader ,这样在iphone6上至少是可以流畅渲染的。

游戏编辑器

上面讲了这么多,痛苦和迷茫。其实我之前做的东西也不能称之为真正的游戏,只能算是营销互动类游戏。

我们还是觉得做游戏要向业界规范的方案靠拢,所以 游戏编辑器是必须要做的。虽然我今天并没有做出一款游戏编辑器,我会跟大家分享为什么我要做游戏编辑器(现在已经正在做了),这中间的坎坷是今天要讲的重点。

image.png

和英国团队合作之后我非常难过,他们的设计做得那么酷,而我只能实现成这样。我在中国环顾一圈,没有看到 Web 3D 游戏方面比较好的方案,因为在中国做 WebGL 的都凤毛麟角。

2017 年我去澳洲参加了 Web 3D 大会,他们当时用了 X3dom 像 HTML 一样用标签地描述 3D 世界。
这是一种非常陈旧的技术,虽然也是基于 WebGL 渲染。这个方案已经推了十几年了,老外也不知道为什么这么执着,有几十个 Paper 都是讲这个的。他们讲的东西都非常学术,我觉得对我们的帮助并不是很大。

然后我又去工业界寻找解决方案。这是前索尼 PlayStation 的一位同学做的应用,他用的技术大家可能会大吃一惊,他用了Unity。第一次看到 Unity 和 Web 嫁接起来是非常令我震惊的。我当时用的是 iphone6 ,运行这个 demo 都是 60 fps 满帧,他是怎么做到的呢?我去查了一下它的代码,虽然代码是压缩过的,但是为了突破这个技术难关,我阅读了压缩后的代码并且理解了它背后的实现。

image.png

我发现里面有各种各样的新颖的技术。比如,Unity 可以合并 3D 模型的贴图。

合并贴图这件事情是很重要的。做前端的同学都知道雪碧图,为什么做雪碧图?大家都知道是为了减少网络请求数,但是其实合并贴图对运行时的性能有很大影响。
GPU 读一张图快还是读十张图快?计算机资源是非常宝贵的,图片要适度合并尽量压缩。一张 200K 的图片,可能占用 3-4 倍的显存。 JS 优化半年减少 30K ,图片批量压缩减少个几兆都是有可能的,所以要把时间花在能够快速见效的事情上面。

下图的 Texture Baker 就是用来烘培并且合并图片。这个是 ITween Path 是 Unity 做路径动画的插件。
Unity还有一个插件叫 Collada Exporter 。Collada 是标准的 3D 模型格式,看到这里我们已经抛弃了之前 Obj+Mtl 的老方案。而Runtime根据我之前的开发经验封装了一套 MVC 的方案。

基于这套工作流,我们做了 2017 年双十一切红包项目。我们经常调侃:腾讯做游戏和阿里做有戏有什么区别?腾讯做游戏是收钱,我们做游戏是发钱。用 Unity 带来的好处是能够直接导入设计师给的源文件,如 Maya 源文件、 Photoshop 源文件。这里我们看到,红包模型是预先切开的,大家知道切水果也是这样做的,即使你竖着切菠萝它还是横着裂开的。

image.png

至于红包的特效,我会经常逛一些国外的网站,这是某个游戏开发者写的 Shader 特效,我就照着他的思路来写了一个类似的。

大家看到一个红包在天上飞,上面有光在流动,其实整个场景中一盏灯都没有打。光照计算,特别是点光源的计算是非常耗性能的。所以大家做 3D 应用的时候尽量要少放光源。这种效果其实只要在像素着色器中写一行代码就解决了。

红包是怎么切中的呢?Picking 这个话题对没有开发过游戏的人也许比较陌生,切红包的游戏里我当时做了两种方案:一种叫做 CPU Picker ,另一种是 GPU Picker 。

CPU Picker:在每个红包上面套上一个包围盒,计算射线有没有击中这个包围盒,因为 CPU Picker 的计算成本和场景的复杂度正相关, 用包围盒会比较快;

GPU Picker:通过拾取离屏画布上面的颜色值就行了。

虽然感觉 GPU Picker 性能会特别好,但在移动端性能表现却不佳,因为拾取颜色的过程实际上是 CPU 和 GPU 通信的过程,这个过程会比较慢。所以,CPU Picker 性能会更好一点。

image.png

还有一点就是 Dom 操作,在 Web 游戏开发中,Dom 操作就是魔鬼。我抓了比较慢的一帧花了 25 毫秒(约 40 帧)。

游戏逻辑加上 Web GL 渲染就花了那么几毫秒,而 DOM 操作却耗掉很长的时间,而且还引发了重绘(紫色部分)。

所以 Dom在游戏里是不合适的,GUI 部分需要用 2D 的 Canvas 或者 Web GL 渲染去解决。

image.png

最后讲一下音效,我个人非常喜欢游戏中声音给我带来的奖励。我做切红包的时候注意到了上面几点,这也是我上周去北京 Unity 大会上听到关于 CRIWare 的声音中间件的内容:

  • 背景音乐要有渐有渐出,这样用户体验比较好;
  • 用户做一些操作或者比较重要操作的时候,当前声音要强调一下,背景音乐减弱一下;
  • 声音要有变化,比如说很多射击的游戏,如果枪声都一样,用户听觉会疲劳的,我们切红包时左切和右切都是不一样的。

这个软件叫 bfxr,是一款制作游戏音效的小软件,在线和客户端版本都有,人人都可以设计音效。

image.png

讲了那么多技术点,我们总要看一下业界真正做游戏的人是怎么做的。我大概探索了一两年,发现 Playcanvas 引擎是 Web 世界上最健全的游戏引擎。它的引擎代码是开源的,但是编辑器不开源。我分析了一下它的引擎源码,大概有几部分组成:

  • ECS 的架构,Unity 也是采用这样的设计模式。
  • PBR,基于物理的渲染模型,看起来更像真实世界的渲染。物理引擎也是很重要的,还有输入设备,比如说你的游戏手柄、手机都是输入设备。

Playcanvas 和 Threejs 有什么区别?

Threejs 只是一个 3D 渲染库。游戏还有一个非常重要的东西叫编辑器,这是 Playcanvas 在线的编辑器,我看了这个游戏之后就觉得一定要做编辑器,因为编辑器是引擎的载体。如果没有编辑器,我们每次开发游戏要注意的工程和技术问题太多。

编辑器架构

最后讲一下我们团队思考的编辑器的架构,现在只是一张工程架构图。

游戏最后发布的内容是什么?就是一堆资源,图片、模型、音频、脚本,在 Web 开发环境中最后都要发上 CDN 。

游戏里的大部分资源如音频、全景图、模型这些都是第三方软件输入的,模型资源的序列化、减面、合并、烘培等操作我们暂时可能不会去做(还是交给 Unity 做),中间 GUI 部分就是编辑器的面板操作,最后 Script 组件和 Shader 可以通过 Vscode 来编辑。这张图是我一两年的心得,大家可以留言区交流~

image.png

想了解更多技术干货,关注「淘系技术」微信公众号~

屏幕快照 2019-06-21 上午10.23.52.png

相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
相关文章
|
23天前
|
前端开发 JavaScript 安全
前端性能调优:HTTP/2与HTTPS在Web加速中的应用
【10月更文挑战第27天】本文介绍了HTTP/2和HTTPS在前端性能调优中的应用。通过多路复用、服务器推送和头部压缩等特性,HTTP/2显著提升了Web性能。同时,HTTPS确保了数据传输的安全性。文章提供了示例代码,展示了如何使用Node.js创建一个HTTP/2服务器。
37 3
|
23天前
|
设计模式 前端开发 数据库
Python Web开发:Django框架下的全栈开发实战
【10月更文挑战第27天】本文介绍了Django框架在Python Web开发中的应用,涵盖了Django与Flask等框架的比较、项目结构、模型、视图、模板和URL配置等内容,并展示了实际代码示例,帮助读者快速掌握Django全栈开发的核心技术。
124 45
|
1天前
|
前端开发 JavaScript UED
在数字化时代,Web 应用性能优化尤为重要。本文探讨了CSS与HTML在提升Web性能中的关键作用及未来趋势
在数字化时代,Web 应用性能优化尤为重要。本文探讨了CSS与HTML在提升Web性能中的关键作用及未来趋势,包括样式表优化、DOM操作减少、图像优化等技术,并分析了电商网站的具体案例,强调了技术演进对Web性能的深远影响。
10 5
|
10天前
|
缓存 安全 网络安全
HTTP/2与HTTPS在Web加速中的应用
HTTP/2与HTTPS在Web加速中的应用
|
13天前
|
SQL 安全 前端开发
PHP与现代Web开发:构建高效的网络应用
【10月更文挑战第37天】在数字化时代,PHP作为一门强大的服务器端脚本语言,持续影响着Web开发的面貌。本文将深入探讨PHP在现代Web开发中的角色,包括其核心优势、面临的挑战以及如何利用PHP构建高效、安全的网络应用。通过具体代码示例和最佳实践的分享,旨在为开发者提供实用指南,帮助他们在不断变化的技术环境中保持竞争力。
|
18天前
|
前端开发 API 开发者
Python Web开发者必看!AJAX、Fetch API实战技巧,让前后端交互如丝般顺滑!
在Web开发中,前后端的高效交互是提升用户体验的关键。本文通过一个基于Flask框架的博客系统实战案例,详细介绍了如何使用AJAX和Fetch API实现不刷新页面查看评论的功能。从后端路由设置到前端请求处理,全面展示了这两种技术的应用技巧,帮助Python Web开发者提升项目质量和开发效率。
33 1
|
21天前
|
SQL 负载均衡 安全
安全至上:Web应用防火墙技术深度剖析与实战
【10月更文挑战第29天】在数字化时代,Web应用防火墙(WAF)成为保护Web应用免受攻击的关键技术。本文深入解析WAF的工作原理和核心组件,如Envoy和Coraza,并提供实战指南,涵盖动态加载规则、集成威胁情报、高可用性配置等内容,帮助开发者和安全专家构建更安全的Web环境。
39 1
|
24天前
|
前端开发 安全 应用服务中间件
前端性能调优:HTTP/2与HTTPS在Web加速中的应用
【10月更文挑战第26天】随着互联网的快速发展,前端性能调优成为开发者的重要任务。本文探讨了HTTP/2与HTTPS在前端性能优化中的应用,介绍了二进制分帧、多路复用和服务器推送等特性,并通过Nginx配置示例展示了如何启用HTTP/2和HTTPS,以提升Web应用的性能和安全性。
24 3
|
1月前
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
113 3
|
4天前
|
开发框架 JavaScript 前端开发
TypeScript 是一种静态类型的编程语言,它扩展了 JavaScript,为 Web 开发带来了强大的类型系统、组件化开发支持、与主流框架的无缝集成、大型项目管理能力和提升开发体验等多方面优势
TypeScript 是一种静态类型的编程语言,它扩展了 JavaScript,为 Web 开发带来了强大的类型系统、组件化开发支持、与主流框架的无缝集成、大型项目管理能力和提升开发体验等多方面优势。通过明确的类型定义,TypeScript 能够在编码阶段发现潜在错误,提高代码质量;支持组件的清晰定义与复用,增强代码的可维护性;与 React、Vue 等框架结合,提供更佳的开发体验;适用于大型项目,优化代码结构和性能。随着 Web 技术的发展,TypeScript 的应用前景广阔,将继续引领 Web 开发的新趋势。
18 2
下一篇
无影云桌面