20.WebAR那些事:一個40行的ARDemo
緊接上文
WebVR+Three.js可以快速高效的搭建VR場景,降低了初學者的准入門檻,節省多平臺重複開發,開始了H5在VR的新時代。
本次Demo所需二維碼
使用者可以本地啟動HTTP服務,將URL填寫到播放路徑
本次demo已經整合到APK中,使用者可以點選《AR地球》來體驗
AR地球
環境準備
- Demo使用r82版本,向下相容
- Three.js 到http://www.threejs.org下載最新原始碼,這裡使用three.min.js作為渲染引擎。
- WebVR.js WebVR的工具庫,用於切換VR狀態(three.js的原始碼包中,自己拷貝)
- VREffect.js WebVR的展示庫,用於分屏展示(three.js的原始碼包中,自己拷貝)
- VRControls.js WebVR的控制庫,用於監控陀螺儀、Camera、重力等(three.js的原始碼包中,自己拷貝)
紋理準備
可以使用其他3D模型,為了方便起見,我們使用老的模型
- 地球紋理,在網上可以找到最新的地圖紋理,最好使用4k,比較清晰
相容性準備
常見的瀏覽器對攝像頭的支援,良莠不齊,這裡只是簡單的支援了一種API標準
捕獲音視訊介面: Navigator.getUserMedia
點選進入: Mozilla官方使用文件
使用方法:
var params = { video: true, video: { width: 1280, height: 720 } };
window.navigator.getUserMedia(params, function(stream) {
var video = document.querySelector(`video`);
video.src = window.URL.createObjectURL(stream);
video.onloadedmetadata = function(e) {
video.play();
};
});
相容性分析
Navigator.getUserMedia介面目前Safari是不支援的,常見的瀏覽器使用攝像頭,往往通過Flash外掛來完成。所以這些程式碼不一定能夠成功執行在使用者的瀏覽器上,但沒有關係,我們的的WebVRSDK已經提供了支援,開發者可以放心的使用。
Navigator.getUserMedia已經廢棄了,使用MediaDevices.getUserMedia來取代。因為我對Promise原理不是很清楚,所以暫時只支援Navigator.getUserMedia。
開發者需要提前申請App的Camera許可權,Android6.0以後支援動態許可權管理,開發者需要確保App擁有Camera的使用許可權,最直接的的辦法是在設定中手動的開啟許可權,否則背景會出現黑屏。
準備空白的html
我們會將所有JS程式碼寫在單獨的index.js中,因此index.html只是提供JS執行的環境,這一步為程式碼遷移到WebVRSDK做準備。程式碼如下:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebGL Earth</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000; }
</style>
</head>
<body>
<script src="three.js"></script>
<script src="WebVR.js"></script>
<script src="VREffect.js"></script>
<script src="VRControls.js"></script>
<script src="index.js"></script>
</body>
</html>
index.js核心程式碼
- 程式碼行數控制在40行以內
- 渲染器,使用WebGL渲染three.js中的3D物件
- 載入器,使用XMLHttpRequest或者Image,非同步載入圖片紋理
- 攝像機,模擬觀察者的位置和方向,從不同角度來觀看3D世界
- 控制器,接受使用者點選、觸控、滑鼠等事件,控制攝像機的引數,實現人機互動
- 材料,任何3D物件,是由骨骼和影像組成,材料就像油漆,粉刷過的物件更加真實
- 幾何,3D物件的結構描述,這裡只用球狀幾何
- 場景,用來管理所有需要展示的3D物件,以及他們之間的層級和關係
- video標籤,用於承載攝像頭內容的呈現
程式碼如下
var w = window.innerWidth;
var h = window.innerHeight;
var renderer = new THREE.WebGLRenderer(); // 建立渲染器
renderer.setSize(w, h); // 設定渲染器為全屏
document.body.appendChild(renderer.domElement); // 將渲染器新增到body上
var camera = new THREE.PerspectiveCamera(45, w / h, 0.01, 100);
var effect = new THREE.VREffect(renderer); // 控制器,用來控制VR渲染
var loader = new THREE.TextureLoader(); // 載入器,用於非同步載入圖片
var control = new THREE.VRControls(camera); // 控制器,用來控制攝像機
var mater = { map : new THREE.TextureLoader().load(`earth_map.jpg`) };
var earth = new THREE.Mesh(new THREE.SphereGeometry(20, 32, 32), new THREE.MeshBasicMaterial(mater));
earth.position.x = -100;
var scene = new THREE.Scene(); // 建立場景
scene.add(earth); // 新增地球
scene.add(new THREE.AmbientLight(0xFFFFFF)); // 建立環境光
window.navigator.getUserMedia({ audio : true, video: { width: w, height: h }}, function(stream) {
var video = document.createElement(`video`);
video.src = stream;
video.play();
var image = new THREE.VideoTexture(video);
image.generateMipmaps = false;
image.format = THREE.RGBAFormat;
image.maxFilter = THREE.NearestFilter;
image.minFilter = THREE.NearestFilter;
scene.background = image; // 背景視訊紋理
}, null);
animate();
function animate() {
effect.requestAnimationFrame(animate);
control.update();
earth.rotation.y += 0.002;
effect.render(scene, camera);
}
用瀏覽器開啟index.html
在Safari上是無法開啟的,因為navigator沒有成員函式:getUserMedia
開發者可以新增判斷,因為WebVRSDK我新增了支援,所以就不判斷了,程式碼如下:
navigator.getUserMedia = navigator.getUserMedia ||
navigator.mozGetUserMedia ||
navigator.webkitGetUserMedia;
if (navigator.getUserMedia) {
....
}
效果展示
懸浮的3D地球
暢想
AR距離我們很近
AR翻譯過來是擴增實境,簡單一點說,就是在攝像頭捕獲的視訊或者圖片中,加入3D效果,並融入背景。就像二次元或者三次元一樣,給使用者帶來更多的歡樂。
如果我們把3D地球換成一隻可愛的貓咪,是不是就是淘寶雙十一的抓貓貓遊戲了?
下一回
我們把地球換成一個複雜的3D模型,並想辦法讓TA動起來,就像淘寶雙十一的AR抓貓貓一樣,會動會跳,還會發紅包。
相關文章
- 21.WebAR那些事:ARDemo之《天馬行空》Web
- 《那些年啊,那些事——一個程式設計師的奮鬥史》——26程式設計師
- Oracle技術嘉年華的一個案例,redo的那些事,連載一Oracle
- 《那些年啊,那些事——一個程式設計師的奮鬥史》——125程式設計師
- String是一個很普通的類 - Java那些事兒Java
- 開發一個 Web App 必須瞭解的那些事WebAPP
- Oracle技術嘉年華的一個案例,redo的那些事,連載二Oracle
- Oracle技術嘉年華的一個案例,redo的那些事,連載三Oracle
- 一個輪子搞定 Fragment 和狀態列那些事Fragment
- Synchronized的那些事synchronized
- webassembly 的那些事Web
- ViewPager的那些事Viewpager
- 那些年啊,那些事——一個程式設計師的奮鬥史 開始預售了程式設計師
- 聊一聊Iterable與Iterator的那些事!
- 【JS基礎】原型物件的那些事(一)JS原型物件
- Java 混淆那些事(六):Android 混淆的那些瑣事JavaAndroid
- Redis那些事(一) — Redis簡介Redis
- 每個Javascript開發者都應當知道的那些事JavaScript
- iOS CollectionView 的那些事iOSView
- 微服務的那些事微服務
- webpack的那些事兒Web
- HTTP 2.0 的那些事HTTP
- HTTP 2.0的那些事HTTP
- Ubuntu的那些事兒Ubuntu
- 一文聊透 IP 地址的那些事
- 關於大資料的那些事兒(一)大資料
- 有關指標的那些事兒《一》指標
- 聊一聊 IP 地址那些事兒
- rem那些事REM
- JavaScript那些事JavaScript
- mysql那些事MySql
- GCD那些事GC
- 程式設計師一定要投資的那些事程式設計師
- IT風雲15年的那些人那些事
- 文字渲染的那些事(一)字型是如何儲存的?
- 敏捷開發的那些事敏捷
- https的那些事兒HTTP
- 關於Cookie的那些事Cookie