VR基础及其在页面级应用(4) — 场景搭建
书接上文 VR基础及其在页面级应用(3) — 场景基础。 上篇文章是不是觉得有点单调了,内容不多,东西也没说明白,就有一个“很晕”的例子,挺无趣的。实际上该系列讲到这里,能用文字说明的内容已经越多越少了,VR 的基础原理都是从3D建模和3D视觉原理过来的,这个东西本身就非常抽象,学习重点是培养感觉,不像是逻辑代码,你可以一行一行的表达出来。而这里的代码表现只是结果,是整个过程的最后一环,所以没有原理认知,把代码背下来也没什么用。 场景篇的文字说明还是会不多,只给出几个建模的思路,尽量做出有互动性的例子,看图比读文字有效多。
继续此系列的风格 —— “点击这里”先查看例子。本篇的例子会“有意思”一点。
本文应该是本系统的最后基础一讲,内容是实际在三维空间中布置物体和背景。
先说场景物体,这个包括空间中的房子、路、各种小物件等。立体形状都是由平面构成的,但是在页面中,因为面的默认方向都是都是和“显示器”在同一平面上,无法像高级的3D编辑软件,可以直接“画”出各种方向、角度的平面。
这成就增加了页面3D建模的复杂度,而且单纯用 transform
无法做出曲面,只能是一些矩形元素。下面给出两类基本的建造方式,一个是常规矩形,一个是背景的“圆”。
矩形
第一篇中就出现的“骰子”,在这里还是会有,因为它很有代表性,页面 transform
变形得到一切物体都可以在它身上找到影子。
还是以它为例,简单说一个完整矩形如何造出来。先看它的 html
结构:
<div class="wrapper">
<div class="container">
<div class="stage">
<section class="ceil" style="transform: rotateX(90deg) translateZ(150px);">天</section>
<section class="floor" style="transform: rotateX(-90deg) translateZ(150px);">地</section>
<section class="wall" style="transform: rotateY(0deg) translateZ(150px);">北</section>
<section class="wall" style="transform: rotateY(90deg) translateZ(150px);">东</section>
<section class="wall" style="transform: rotateY(180deg) translateZ(150px);">南</section>
<section class="wall" style="transform: rotateY(270deg) translateZ(150px);">西</section>
</div>
</div>
</div>
方位变换
以下是步骤(正方体):
stage
是舞台,也是矩形6个面的方位基准。将6个面都以absolute
的布局模式“层叠”在stage
里;- 拉开空间距离:
transform: translateZ(150px);
,这一步可以将一个“屏幕”中的平面“拉”出来,同时也会确定矩形一边的长度; - 旋转到东南西北四个方位:
transform: rotateX([0 - 360]deg);
,上面变换都是对全部的平面,在这一步,就要有差别性的对待,拿出四个面将它向以y轴方向旋转,组成矩形的四边;
- 同样的原理,将“天地”两个面以x轴的方向旋转到上下两侧,将剩下的两个面补全。
这样就把一个完整的矩形做出来了,当然网上也有其它的方式,个人总结出来此方法相比之下有几个优点:
- 变换基准很稳定,要移动矩形只需控制
stage
就行; - 矩形中心点明确,就是
stage
的中心; - 代码量少,而且一致,唯一差异化的就是
rotate
部分,也容易理解。
这样,一个基础矩形就做完了,然后通过控制 stage
和视距,下面来控制它的摆放位置。
空间位置
通过控制 wrapper
和 container
来让上面做好的矩形放置在空间的任意位置。还是举两个典型的例子。
1. 任意维度的摆放
这个比较简单,只要对 stage
进行 translate3d
变换就行,具体看实际需求。
2. 将自己置身矩形中
这实际是上一种情况的加强版,如何做到这样的效果呢?看下图:
满足以下公式时(当视距 > 目标矩形的总 translateZ
),就会把自己放在矩形空间中,这也是做类似进入房子等效果时需要的情况。
.wrapper'persperctive <= .stage'translateZ + section'translateZ
矩形的建模大致就这些了,上面的例子为了方便理解都是以正文体为例的,如果是长宽高不一致的矩形,就需要其它的一些计算了,在最后的例子中有所动态体现,具体可以去认真看一下。
“圆形背景”
上面的矩形建模可以解决物体、房间等的构建。但是遇到背景就麻烦了,矩形的有棱有角在随着目光进行旋转时会出现明显的“漏洞”,一看就是“方”的,效果很差,正常的背景应该抽象成一个很大的圆柱形,你站在中间,这样目光转动时,正前方视距的感觉才能是一致的。
但是,页面是无法画出曲面的,怎么解决背景旋转时的漏洞呢?
其实,如果你对计算机3d建模有一定了解的话,就会明白,不论是在哪个高大上的3D建模软件里,还是相对弱的页面里,计算机本身就画不出什么曲面来。 你所看到的那些平滑的曲线,都是靠非常多个平面拼接出来的,而拼接平面的数量就决定了曲面的平滑程度。
上大学时常捣鼓硬件,从显卡了解到一个“曲面细分”的画面优化技术,知道了显示绘3D图的原理。
页面背景的圆,也是一样的,我们需要用较多个平面拼接出来。这里先以8分的圆举例说明,当然分的越多越好,做近似圆的方法。
- 找一个可以头尾对接的大图,至少图要长;
- 将图以长边平均分成8份,这里有两个方法,一个是用PS人切片工具进行物理裁切,另一种是图不变,通过各平台的
background-size + background-position
选择性的进行显示裁切,效果都是一样的,但性能有较大的差别,笔者在这里没有具体测试; - 计算拉开
stage
的距离:离stage距离 = (切片长度 / 2) / (sin(360 / 切片数 / 2 / 180 * PI)) - 计算各个平台依次旋转的度数:切片i = i * (360 / 切片数)
这样做出的近似圆,会将背景旋转时落点视距的“波动”降到最低。做为背景的圆做的越大越好,用上一篇的知识将“自己”放置在圆的中心,这样一个优美的背景图就做好了。
具体的可以看文章最后的例子。
展示的例子
总结
该系列到这就暂时结束了,主要围绕 VR 最最基本的知识点进行了简要说明,但这此知识的灵活应用足以在页面上做出你想要的效果。 笔者也在计划写一到两篇的进阶篇。
同时也听有人说,现在页面 H5(canvas) 的3D引擎也那么多,能做的东西比这个仅通过变换凑成的场景华丽的多,要看这个干什么。 “呵呵~~~”,说这个的一定是彻底不了解原理和没玩过3D引擎的人了,我只能说“3D效果结果的华丽和过程的复杂一定是成正比的”,你连这个都没弄明白别奢求在大型引擎里堆海量代码了,你去用过就知道。
VR 现在被运用的越来越多,慢慢呈现暴发式的增长,在以后的视觉编程和体验上必将成为一个重点。