前言
填坑了,填坑了,之前因为写XR-FRAME
博客的时候突然被老板叫走干活了,博客写了一半就挂了,然后一直没继续写,现在来补上,看本篇文章之前先把之前的文章需要看一下。
地址: https://myblog-5g89ixpbbf1fbfad-1316695488.ap-shanghai.app.tcloudbase.com/2024/04/18/wx-xr-frame/
本篇文章内容主要记录我根据官方文档步骤依次实现过的内容,大家也可以跟着官方文档玩一下:
官方地址:https://developers.weixin.qq.com/miniprogram/dev/framework/xr-frame/
添加环境贴图
这里使用一下系统自带的贴图
1
| <xr-env env-data="xr-frame-team-workspace-day"></xr-env>
|
添加视频纹理
1 2 3 4 5 6 7 8
| <xr-asset-load type="video-texture" asset-id="office" src="https://mmbizwxaminiprogram-1258344707.cos.ap-guangzhou.myqcloud.com/xr-frame/demo/videos/office-skybox.mp4" options="autoPlay:true,loop:true" > </xr-asset-load> <xr-env env-data="xr-frame-team-workspace-day" sky-map="video-office" />
|
2D 背景
XR-FRAME
支持 2D 背景,这个在做一些商品展示的时候会比较有用:
1 2 3 4 5 6
| <xr-asset-load type="texture" asset-id="weakme" src="https://mmbizwxaminiprogram-1258344707.cos.ap-guangzhou.myqcloud.com/xr-frame/demo/weakme.jpg" > </xr-asset-load>
|
JS 加载纹理
在 js 文件中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| data: { avatarTextureId:"white" },
/** * 组件的方法列表 */ methods: { handleReady({detail}){ this.scene = detail.value; this.scene.assets.loadAsset({ type: 'texture', assetId: 'avatar', src: 'https://img.tukuppt.com/photo-big/00/10/88/6195e346747293216.jpg' }).then(()=>this.setData({avatarTextureId:'avatar'})); },
}
|
然后给我们的地面加上这个纹理
1 2 3 4 5 6 7 8 9 10
| <xr-mesh node-id='plane' geometry="plane" position="0 -1 0" scale="4 1 4" receive-shadow anim-keyframe="anim" anim-autoplay="clip:plane" uniforms="u_baseColorMap: {{avatarTextureId}}" ></xr-mesh>
|
此时还需要给场景绑定事件
1 2 3 4
| <xr-scene bind:ready="handleReady"> ...xxx ...xxxx </xr-scene>
|
通过 JSON 添加动画
目前我们的整个场景还是静态的,接下来我们会加入一些动画让其丰富起来。这里要使用帧动画资源,让我们先创建一个资源目录,在其下创建一个 json 文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| { "keyframe": { "plane": { "0": { "rotation.y": 0, "material.u_baseColorFactor": [0.2, 0.6, 0.8, 1] }, "50": { "material.u_baseColorFactor": [0.2, 0.8, 0.6, 1] }, "100": { "rotation.y": 6.28, "material.u_baseColorFactor": [0.2, 0.6, 0.8, 1] } }, "cube": { "0": { "position": [-1, 0, 0] }, "25": { "position": [-1, 1, 0] }, "50": { "position": [1, 1, 0] }, "75": { "position": [1, 0, 0] } } }, "animation": { "plane": { "keyframe": "plane", "duration": 4, "ease": "ease-in-out", "loop": -1 }, "cube": { "keyframe": "cube", "duration": 4, "ease": "steps", "loop": -1, "direction": "both" } } }
|
然后加载它,并引用到场上的两个物体中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <xr-asset-load asset-id="anim" type="keyframe" src="/assets/animation.json"/>
<xr-mesh node-id="cube" cast-shadow anim-keyframe="anim" anim-autoplay="clip:cube,speed:2" geometry="cube" uniforms="u_baseColorMap: waifu,u_metallicRoughnessValues:1 0.1" /> <xr-mesh node-id="plane" position="0 -1 0" scale="4 1 4" receive-shadow anim-keyframe="anim" anim-autoplay="clip:plane" geometry="plane" uniforms="u_baseColorMap: {{avatarTextureId}}" />
<xr-camera position="0 1 6" target="plane" background="skybox" clear-color="0.4 0.8 0.6 1" camera-orbit-control />
|
这里我们将 xr-camera 的 target 设置到了 plane 上,以防其跟随 cube 乱动。
注意因为是包内的 json 文件,所以需要在 project.config.json 的 setting 字段中增加 “ignoreDevUnusedFiles”: false 和”ignoreUploadUnusedFiles”: false 配置参数! 配置完成之后记得重启微信开发者工具
此时的效果如下
载入模型
看着这个场景,你可能也觉得缺了点什么,不错——都是方方正正的几何体,还是太单调了。所以在这里,我们将加载并使用 glTF 模型,来让场景更加丰富。为了让场景简洁,我们去掉原场景的所有物体,调整相机的 target:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| <xr-scene bind:ready="handleReady"> <xr-assets bind:progress="handleAssetsProgress" bind:loaded="handleAssetsLoad"> <xr-asset-load type="gltf" asset-id="damage-helmet" src="https://mmbizwxaminiprogram-1258344707.cos.ap-guangzhou.myqcloud.com/xr-frame/demo/damage-helmet/index.glb" > </xr-asset-load> <xr-asset-load type="gltf" asset-id="miku" src="https://mmbizwxaminiprogram-1258344707.cos.ap-guangzhou.myqcloud.com/xr-frame/demo/miku.glb"
> </xr-asset-load> </xr-assets> <xr-light type="ambient" color="1 1 1" intensity="1"></xr-light> <xr-light type="directional" intensity="3" rotation="40 70 0" cast-shadow></xr-light>
<xr-env env-data="xr-frame-team-workspace-day"></xr-env> <xr-gltf node-id="damage-helmet" model="damage-helmet" /> <xr-gltf node-id='miku' model="miku" position="-0.15 0.75 0" scale="0.07 0.07 0.07" rotation="0 180 0" anim-autoplay
/>
<xr-camera position="0 1.5 4" target="damage-helmet" background="skybox" clear-color="0.4 0.8 0.6 1" camera-orbit-control /> </xr-scene>
|
事件交互
渲染部分到这里说的就差不多了,但作为一个应用,和用户的交互必不可少。很多场景下开发者可能需要点击场景中的物体来做一些逻辑,所以我们提供了 shape 系列组件:
1 2 3 4 5 6 7 8
| <xr-gltf node-id="damage-helmet" model="damage-helmet" id="helmet" mesh-shape bind:touch-shape="handleTouchModel" /> <xr-gltf model="miku" position="-0.15 0.75 0" scale="0.07 0.07 0.07" rotation="0 180 0" anim-autoplay id="miku" cube-shape="autoFit:true" shape-gizmo bind:touch-shape="handleTouchModel" />
|
我们给几个模型设置了 id,添加上了不同形状的 shape,一个 mesh-shape 可以完全匹配模型,但开销较高并有顶点限制,一个 cube-shape 开销较低,还可以打开 debug 开关 shape-gizmo 将它显示出来。最后,我们并绑定了对应的点击事件,之后便可以在脚本里写逻辑,完成相应的操作了:
1 2 3 4 5
| handleTouchModel(event){ const target=event.target const id = target.id; wx.showToast({title: `${id}`}); },
|
组件通信,加上HUD
虽然有了交互,但总不能让交互都是这种弹窗吧。很多时候我们会让交互和UI元素互相影响,但目前xr-frame尚未支持和小程序的UI元素混写(会在未来版本支持),但我们可以使用同层方案,而同层方案,就必然涉及到组件通信了。
xr-frame组件和父级的通信与传统组件基本一致,这里让我们用小程序的UI元素实现一下HUD。这里可能会有一些3D变换的知识,但不要紧,只是调用接口而已。
首先,让我们修改组件的wxml,为场景添加tick事件,并且为模型和相机都加上id方便索引。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <xr-scene bind:ready="handleReady" bind:tick="handleTick"> ...... <xr-gltf node-id="damage-helmet" model="damage-helmet" id="helmet" mesh-shape bind:touch-shape="handleTouchModel" /> <xr-gltf model="miku" position="-0.15 0.75 0" scale="0.07 0.07 0.07" rotation="0 180 0" anim-autoplay id="miku" cube-shape="autoFit:true" shape-gizmo bind:touch-shape="handleTouchModel" /> <xr-camera id="camera" position="0 1.5 4" target="damage-helmet" background="skybox" clear-color="0.4 0.8 0.6 1" camera-orbit-control /> </xr-scene>
|
之后在组件的脚本中处理事件,编写逻辑:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| handleReady: function ({detail}) { this.scene = detail.value; const xrFrameSystem = wx.getXrFrameSystem(); this.camera = this.scene.getElementById('camera').getComponent(xrFrameSystem.Camera); this.helmet = {el: this.scene.getElementById('helmet'), color: 'rgba(44, 44, 44, 0.5)'}; this.miku = {el: this.scene.getElementById('miku'), color: 'rgba(44, 44, 44, 0.5)'}; this.tmpV3 = new (xrFrameSystem.Vector3)(); }, handleAssetsLoaded: function ({detail}) { this.triggerEvent('assetsLoaded', detail.value); }, handleTick: function({detail}) { this.helmet && this.triggerEvent('syncPositions', [ this.getScreenPosition(this.helmet), this.getScreenPosition(this.miku) ]); }, handleTouchModel: function ({detail}) { const {target} = detail.value; this[target.id].color = `rgba(${Math.random()*255}, ${Math.random()*255}, ${Math.random()*255}, 0.5)`; }, getScreenPosition: function(value) { const {el, color} = value; const xrFrameSystem = wx.getXrFrameSystem(); this.tmpV3.set(el.getComponent(xrFrameSystem.Transform).worldPosition); const clipPos = this.camera.convertWorldPositionToClip(this.tmpV3); const {frameWidth, frameHeight} = this.scene; return [((clipPos.x + 1) / 2) * frameWidth, (1 - (clipPos.y + 1) / 2) * frameHeight, color, el.id]; }
|
这里我们在ready事件中通过id索引获取了需要的实例并存了下来,然后在每帧的tick事件中实时获取物体的世界坐标,将其转换为屏幕的位置,并且还加上了在用户点击时改变颜色color的效果。在最后,我们通过this.triggerEvent,从组件向页面发起了通信,一个是资源加载完成的事件assetsLoaded,一个是坐标更新的事件syncPositions。让我们看看在场景的脚本中是如何处理这些事件的
1 2 3 4 5 6 7 8 9 10 11 12
| data: { width: 300, height: 300, renderWidth: 300, renderHeight: 300, loaded: false, positions: [[0, 0, 'rgba(44, 44, 44, 0.5)', ''], [0, 0, 'rgba(44, 44, 44, 0.5)', '']], }, handleLoaded: function({detail}) { this.setData({loaded: true}); }, handleSyncPositions: function({detail}) { this.setData({positions: detail}); },
|
可见只是简单地接受了事件,然后将其设置为data而已,那么这个data用在哪里呢,来看看页面的wxml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <view> <xr-start disable-scroll id="main-frame" width="{{renderWidth}}" height="{{renderHeight}}" style="width:{{width}}px;height:{{height}}px;" bind:assetsLoaded="handleLoaded" bind:syncPositions="handleSyncPositions" />
<block wx:if="{{loaded}}" wx:for="{{positions}}" wx:for-item="pos" wx:key="*this"> <view style="display: block; position: absolute;left: {{pos[0]}}px;top: {{pos[1]}}px;background: {{pos[2]}};transform: translate(-50%, -50%);"> <view style="text-align: center;color: white;font-size: 24px;padding: 8px;">{{pos[3]}}</view> </view> </block> </view>
|
也很简单,就是在xr-start组件上加上了事件的绑定,然后下面多了一些UI,在模型加载完毕后显示,并按照位置和颜色跟随模型移动,这可以认为是基于DOM的HUD。整个完成了,用户点击物体,会让这些HUD变色,效果如下:
注意这里的左侧效果截图是真机截图P上去的,因为工具暂不支持同层渲染
虚拟 x 现实,追加AR能力
接下来的部分效果我将采用官方给的效果,我自己是试过的,效果都是可以实现,人和房子比较丑,就不露面了。
到这里,我们实现了3D场景的渲染和交互,但框架毕竟是叫做XR-frame,所以接下来我们就用内置的AR系统来改造一下这个场景,让它具有AR能力吧。改造非常简单,我们首先将所有的无关物体移除,然后使用ar-system和ar-tracker,并修改一下xr-camera的相关属性is-ar-camera和background=”ar”就好:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <xr-scene ar-system="modes:Plane" bind:ready="handleReady"> <xr-assets bind:loaded="handleAssetsLoaded"> <xr-asset-load type="gltf" asset-id="anchor" src="https://mmbizwxaminiprogram-1258344707.cos.ap-guangzhou.myqcloud.com/xr-frame/demo/ar-plane-marker.glb" /> <xr-asset-load type="gltf" asset-id="miku" src="https://mmbizwxaminiprogram-1258344707.cos.ap-guangzhou.myqcloud.com/xr-frame/demo/miku.glb" /> </xr-assets>
<xr-env env-data="xr-frame-team-workspace-day" /> <xr-light type="ambient" color="1 1 1" intensity="1" /> <xr-light type="directional" rotation="40 70 0" color="1 1 1" intensity="3" cast-shadow />
<xr-ar-tracker mode="Plane"> <xr-gltf model="anchor"></xr-gltf> </xr-ar-tracker> <xr-node node-id="setitem" visible="false"> <xr-gltf model="miku" anim-autoplay scale="0.08 0.08 0.08" rotation="0 180 0"/> </xr-node>
<xr-camera clear-color="0.4 0.8 0.6 1" background="ar" is-ar-camera /> </xr-scene>
|
注意这里我们开启的ar-system的模式为Plane,即平面识别,这种模式下相机不能被用户控制,需要将控制器、target等都删掉,同时ar-tracker的mode要和ar-system的完全一致。之后再脚本中写一点简单的逻辑即可:
1 2 3 4 5 6
| handleAssetsLoaded: function({detail}) { wx.showToast({title: '点击屏幕放置'}); this.scene.event.add('touchstart', () => { this.scene.ar.placeHere('setitem', true); }); }
|
目前AR系统只能在真机预览时生效,所以我们可以将其提交预览,最终效果如下(AR的案例效果都是P的):
识别人脸,给自己戴个面具
在初步了解了AR系统后,我们便可以尝试更多不同的模式来玩做一些好玩的效果。接下来的是人脸识别模式,为此我们只需要在上面的代码中改几句,就可以给自己带上Joker的面具(逃):
⚠️ 手势、人脸、躯体识别都需要基础库v2.28.1以上。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <xr-scene ar-system="modes:Face;camera:Front" bind:ready="handleReady" bind:tick="handleTick"> <xr-assets bind:loaded="handleAssetsLoaded"> <xr-asset-load type="gltf" asset-id="mask" src="https://mmbizwxaminiprogram-1258344707.cos.ap-guangzhou.myqcloud.com/xr-frame/demo/jokers_mask_persona5.glb" /> </xr-assets>
<xr-env env-data="xr-frame-team-workspace-day" /> <xr-light type="ambient" color="1 1 1" intensity="1" /> <xr-light type="directional" rotation="40 70 0" color="1 1 1" intensity="3" />
<xr-ar-tracker mode="Face" auto-sync="43"> <xr-gltf model="mask" rotation="0 180 0" scale="0.5 0.5 0.5" /> </xr-ar-tracker>
<xr-camera clear-color="0.4 0.8 0.6 1" background="ar" is-ar-camera /> </xr-scene>
|
这里我们将ar-system的modes改为了Face,并且新增设置了camera属性为Front,表示开启前置相机(注意前置相机在客户端8.0.31后才支持,这里仅做演示)。同时在ar-tracker这边,我们将mode改为了和ar-system一样的Face,并追加了属性auto-sync,这是一个数字数组,表示将识别出的面部特征点和对应顺序的子节点绑定并自动同步,具体的特征点可见组件文档详细描述。最终效果如下:
手势,给喜欢的作品点赞
除了人脸之外,我们也提供了躯体和人手识别,用法都大同小异,但人手除了上面所属的特征点同步,还提供了“手势”识别,这个比较有趣,让我们来看看:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <xr-scene ar-system="modes:Hand" bind:ready="handleReady" bind:tick="handleTick"> <xr-assets bind:loaded="handleAssetsLoaded"> <xr-asset-load type="gltf" asset-id="cool-star" src="https://mmbizwxaminiprogram-1258344707.cos.ap-guangzhou.myqcloud.com/xr-frame/demo/cool-star.glb" /> </xr-assets>
<xr-env env-data="xr-frame-team-workspace-day" /> <xr-light type="ambient" color="1 1 1" intensity="1" /> <xr-light type="directional" rotation="40 70 0" color="1 1 1" intensity="3" cast-shadow />
<xr-ar-tracker id="tracker" mode="Hand" auto-sync="4"> <xr-gltf model="cool-star" anim-autoplay /> </xr-ar-tracker>
<xr-camera clear-color="0.4 0.8 0.6 1" background="ar" is-ar-camera /> </xr-scene>
|
wxml这里我们换了个模型,并且将ar-system和ar-tracker的模式都换成了Hand,并修改了ar-tracker的特征点还加上了个id方便索引,最后还给scene绑定了tick事件,而接下来就是js逻辑了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| handleAssetsLoaded: function ({detail}) { this.setData({loaded: true});
const el = this.scene.getElementById('tracker'); this.tracker = el.getComponent(wx.getXrFrameSystem().ARTracker); this.gesture = -1; }, handleTick: function() { if (!this.tracker) return; const {gesture, score} = this.tracker; if (score < 0.5 || gesture === this.gesture) { return; }
this.gesture = gesture; gesture === 6 && wx.showToast({title: '好!'}); gesture === 14 && wx.showToast({title: '唉...'}); }
|
最重要的是handleTick方法,在每一帧我们拿到tracker的引用,然后获得它的属性gesture和score,其中gesture为手势编号而score为置信度。具体的手势编号可见组件文档,这里我先用置信度过滤了一遍,随后依据手势gesture的值(6为赞,14为踩)来提示不同信息,效果如下:
OSDMarker,给现实物体做标记
人体之外还有的能力就是两个marker了。其一是OSD Marker,一般以一个现实中物体的照片作为识别源,来识别出这个物体的在屏幕中的二维区域,我们已经做好了到三维空间的转换,但开发者需要自己保证tracker下模型的比例是符合识别源的。OSD模式在识别那些二维的、特征清晰的物体效果最好,比如广告牌。
这里是默认示例资源,你可以换成自己的照片和视频,如果只是想要尝试,直接复制访问src的地址到浏览器打开即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <xr-scene ar-system="modes:OSD" bind:ready="handleReady"> <xr-assets bind:loaded="handleAssetsLoaded"> <xr-asset-material asset-id="mat" effect="simple" uniforms="u_baseColorFactor: 0.8 0.6 0.4 0.7" states="alphaMode:BLEND" /> </xr-assets>
<xr-node> <xr-ar-tracker mode="OSD" src="https://mmbizwxaminiprogram-1258344707.cos.ap-guangzhou.myqcloud.com/xr-frame/demo/marker/osdmarker-test.jpg" > <xr-mesh geometry="plane" material="mat" rotation="-90 0 0" /> </xr-ar-tracker> </xr-node>
<xr-camera clear-color="0.4 0.8 0.6 1" background="ar" is-ar-camera /> </xr-scene>
|
这里我们把ar-system的模式改为了OSD,相应的ar-tracker的模式也改为了OSD,这种模式下需要提供src,也就是要识别的图像。并且这次我们使用了一个效果为simple的材质,因为不需要灯光,同时为了更好看效果,在material的states设置了alphaMode:BLEND,即开启透明混合,然后将uniforms设置颜色u_baseColorFactor,并且注意其透明度为0.7。最终效果如下:
2DMarker+视频,让照片动起来
最后的能力就是2D Marker,其用于精准识别有一定纹理的矩形平面,我们可以将其配合视频纹理,只需要非常简单的代码就可以完成一个效果,首先是wxml:
这里是默认示例资源,你可以换成自己的照片和视频,如果只是想要尝试,直接复制访问src的地址到浏览器打开即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <xr-scene ar-system="modes:Marker" bind:ready="handleReady"> <xr-assets bind:loaded="handleAssetsLoaded"> <xr-asset-load type="video-texture" asset-id="hikari" options="loop:true" src="https://mmbizwxaminiprogram-1258344707.cos.ap-guangzhou.myqcloud.com/xr-frame/demo/xr-frame-team/2dmarker/hikari-v.mp4" /> <xr-asset-material asset-id="mat" effect="simple" uniforms="u_baseColorMap: video-hikari" /> </xr-assets>
<xr-node wx:if="{{loaded}}"> <xr-ar-tracker mode="Marker" bind:ar-tracker-switch="handleTrackerSwitch" src="https://mmbizwxaminiprogram-1258344707.cos.ap-guangzhou.myqcloud.com/xr-frame/demo/xr-frame-team/2dmarker/hikari.jpg" > <xr-mesh node-id="mesh-plane" geometry="plane" material="mat" /> </xr-ar-tracker> </xr-node>
<xr-camera clear-color="0.4 0.8 0.6 1" background="ar" is-ar-camera /> </xr-scene>
|
这里我们把ar-system的模式改成了Marker,随后将ar-tracker的类型也改为了Marker,并且换了一个识别源,然后加载一个准备好的视频纹理,并将simple材质的颜色换为了纹理u_baseColorMap,同时关闭了混合。注意我们使用了变量loaded来控制ar-tracker的显示并绑定了事件ar-tracker-switch,这是为了在脚本中处理:
1 2 3 4 5 6 7 8
| handleAssetsLoaded: function ({detail}) { this.setData({loaded: true}); }, handleTrackerSwitch: function ({detail}) { const active = detail.value; const video = this.scene.assets.getAsset('video-texture', 'hikari'); active ? video.play() : video.stop(); }
|
在视频加载完成后再显示内容,并且在ar-tracker-switch事件也就是识别成功后在播放视频,优化体验,最终效果如下
加上魔法,来点粒子
光是播放视频似乎还是有点单调,这里我们可以请出粒子系统制造一些魔法来让整个场景更加生动:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| ...... <xr-asset-load type="texture" asset-id="point" src="https://mmbizwxaminiprogram-1258344707.cos.ap-guangzhou.myqcloud.com/xr-frame/demo/particles/point.png" /> ...... <xr-node wx:if="{{loaded}}"> <xr-ar-tracker mode="Marker" bind:ar-tracker-switch="handleTrackerSwitch" src="https://mmbizwxaminiprogram-1258344707.cos.ap-guangzhou.myqcloud.com/xr-frame/demo/xr-frame-team/2dmarker/hikari.jpg" > <xr-mesh node-id="mesh-plane" geometry="plane" material="mat" /> <xr-particle capacity="500" emit-rate="20" size="0.03 0.06" life-time="2 3" speed="0.04 0.1" start-color="1 1 1 0.8" end-color="1 1 1 0.2" emitter-type="BoxShape" emitter-props="minEmitBox:-0.5 0 0.5,maxEmitBox:0.5 0.2 0,direction:0 0 -1,direction2:0 0 -1" texture="point" /> </xr-ar-tracker> </xr-node> ......
|
在上一步2DMarker视频的基础上,我们加上了xr-particle元素,使用了新加载的贴图point和boxShape发射器以及其他参数来生成粒子,最终效果如下:
后处理,让画面更加好玩
在主体渲染结束后,好像还是有些单调,缺乏一种和现实世界的明确分离感,这时候就可以用全屏后处理来实现一些更好玩的效果:
1 2 3 4 5 6 7 8
| ...... <xr-asset-load asset-id="anim" type="keyframe" src="/assets/animation.json"/> ...... <xr-asset-post-process asset-id="vignette" type="vignette" data="intensity:1,smoothness:4,color:1 0 0 1" anim-keyframe="anim" anim-autoplay /> <xr-camera clear-color="0.4 0.8 0.6 1" background="ar" is-ar-camera post-process="vignette" />
|
这里我为相机应用了一个渐晕vignette后处理效果,并为其加上了帧动画控制参数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| { "keyframe": { "vignette": { "0": { "asset-post-process.assetData.intensity": 0 }, "100": { "asset-post-process.assetData.intensity": 1 } } }, "animation": { "vignette": { "keyframe": "vignette", "duration": 2, "ease": "ease-in-out", "loop": -1, "direction": "both" } } }
|
最终效果
分享给你的好友吧!
好,终于到了这里,当我们做出了一些令人满意的效果后最重要的什么?当然是分享给好友!下面就让我们用xr-frame内置的分享系统来完成这个功能:
1 2 3
| ...... <xr-mesh node-id="mesh-plane" geometry="plane" material="mat" cube-shape="autoFit:true" bind:touch-shape="handleShare" /> ......
|
1 2 3
| handleShare: function() { this.scene.share.captureToFriends(); }
|
给识别后显示的视频Mesh加上了上面说过的shape绑定了触摸事件,然后在事件处理函数中直接用this.scene.share.captureToFriends()即可,效果如下:
当然,很多时候我们只是需要图片,然后用它接入微信的其他分享接口比如onShareAppMessage生命周期,此时使用share.captureToLocalPath接口即可,详细可见组件文档。
结语
本篇文章就到这里了,本文主要援引官方文档,我跟着自己试了一下wx-xr-frame
的功能,大家也可以自己去玩一下,感觉还是比较有意思的,更多内容敬请期待,债见~