国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

VR進(jìn)化論|教你搭建通用的WebVR工程

liujs / 3110人閱讀

摘要:本文旨在介紹如何搭建工程以支持多場(chǎng)景開(kāi)發(fā)。有了公用,我們希望這樣開(kāi)發(fā)應(yīng)用,即一個(gè)場(chǎng)景對(duì)應(yīng)一個(gè)腳本,形如繼承父類,開(kāi)發(fā)每一個(gè)場(chǎng)景啟動(dòng)渲染之前,創(chuàng)建場(chǎng)景模型場(chǎng)景資源加載完畢,可執(zhí)行音頻播放等。

本文旨在介紹如何搭建WebVR工程以支持多場(chǎng)景開(kāi)發(fā)。

首先,作為一個(gè)基本的前端工程來(lái)說(shuō),我們需要讓代碼“工程化”,不僅要提供編譯構(gòu)建、壓縮打包功能,還要讓每個(gè)頁(yè)面模塊化;
延伸到WebVR工程,我們也需要考慮就必須考慮“多頁(yè)面”模塊化,即提供多個(gè)場(chǎng)景模塊化開(kāi)發(fā),因?yàn)橐粋€(gè)完整的WebVR App不僅僅只有一個(gè)場(chǎng)景。這里可以參考google的WebVR多場(chǎng)景示例:https://vr.chromeexperiments....

多場(chǎng)景開(kāi)發(fā),最簡(jiǎn)單的方式就是,一個(gè)場(chǎng)景對(duì)應(yīng)一份html、css、js,多個(gè)頁(yè)面需要多個(gè)html,每次頁(yè)面跳轉(zhuǎn)需要重新進(jìn)行VR渲染進(jìn)行初始化。
實(shí)際上我們?cè)诙鄨?chǎng)景中,場(chǎng)景初始化只需要執(zhí)行一次(比如,創(chuàng)建一個(gè)場(chǎng)景->創(chuàng)建相機(jī)->創(chuàng)建渲染器),我們只需要一個(gè)index.html作為入口頁(yè)面,將VR場(chǎng)景初始化、創(chuàng)建、回收、切換封裝成公用組件。

在首次進(jìn)入場(chǎng)景時(shí)進(jìn)行初始化,在需要場(chǎng)景切換時(shí)進(jìn)行場(chǎng)景回收和按需加載,這樣一來(lái),用戶切換場(chǎng)景時(shí),不用把時(shí)間浪費(fèi)在等待html和初始化場(chǎng)景上。基于以上思路,本人總結(jié)的一套WebVR工程搭建方案,供各位參考。

項(xiàng)目地址:https://github.com/YorkChan94...
Demo:https://yorkchan94.github.io/...
相關(guān)技術(shù)棧:three.jswebpack2es6/7
想詳細(xì)了解WebVR開(kāi)發(fā)步驟,也歡迎參考我的文章《VR大潮來(lái)襲——前端開(kāi)發(fā)能做些什么》

實(shí)現(xiàn)功能

VR多場(chǎng)景模塊化開(kāi)發(fā)

支持VR場(chǎng)景創(chuàng)建、回收、切換

項(xiàng)目自動(dòng)化構(gòu)建與壓縮打包

支持es7/6

WebVR相關(guān)庫(kù)

three.js

vrcontrols.js

vreffect.js

webvr-manager.js

webvr-polyfill.js

three-onevent.js

主要目錄結(jié)構(gòu)
webpack
|-- webpack.config.js       # 公共配置
|-- webpack.dev.js          # 開(kāi)發(fā)配置
|-- webpack.prod.js         # 生產(chǎn)配置
src                         # 項(xiàng)目源碼
|-- page                    # WebVR場(chǎng)景目錄       
|   |-- index.js            # WebVR入口場(chǎng)景              
|   |-- page1.js
|   |-- page2.js                                            
|-- common                  # 公共目錄,包括webvr封裝類和polyfill
|   |-- VRCore.js
|   |-- VRPage.js
|   |-- vendor.js
|-- lib                     # vr三方插件,包括相機(jī)控制器和分屏器
|   |-- vrcontrol.js 
|   |-- vreffect.js 
|-- assets                  # 素材目錄,包括3d模型、紋理、音頻等
|   |-- audio                      
|   |-- model
|   |-- texture
|-- index.html              # WebVR公用頁(yè)面
package.json                        
READNE.md

我們先來(lái)看看index.html,其實(shí)整個(gè)body就只有一個(gè)dom,用來(lái)append我們的canvas,畢竟所以場(chǎng)景都在canvas里運(yùn)行。




    
    
    webVR-INDEX


  

有了公用html,我們希望這樣開(kāi)發(fā)WebVR應(yīng)用,即一個(gè)場(chǎng)景對(duì)應(yīng)一個(gè)js腳本,形如:

// 繼承VRPage父類,開(kāi)發(fā)每一個(gè)場(chǎng)景
import VRPage from "common/js/VRPage";

class Page1 extends VRPage {
    start() { // 啟動(dòng)渲染之前,創(chuàng)建場(chǎng)景3d模型
        let geometry = new THREE.CubeGeometry(5,5,5);
        let material = new THREE.MeshBasicMaterial( { color:0x00aadd} );
        this.box = new THREE.Mesh(geometry,material);
        this.box.position.set(3,-2,-3);
        WebVR.Scene.add(this.box);
    }
    loaded() { // 場(chǎng)景資源加載完畢,可執(zhí)行音頻播放等。
    }
    update(delta) { // 開(kāi)啟渲染之后,執(zhí)行模型動(dòng)畫(huà)
        this.box.rotation.y += 0.05;
    }
}
export default (() => {
    return new Page1();
})();

這里參照了類似Unity3d和React的開(kāi)發(fā)模式,在start方法里創(chuàng)建3d模型,在update方法里處理3d動(dòng)畫(huà),這樣的好處在于:

每一個(gè)場(chǎng)景都可以進(jìn)行獨(dú)立開(kāi)發(fā)而互不影響;

一旦VR環(huán)境初始化之后,不需要在每次場(chǎng)景跳轉(zhuǎn)切換時(shí)重新初始化一遍。

VRCore.js作為公用模塊管理整個(gè)webvr應(yīng)用的所有子場(chǎng)景,包括場(chǎng)景初始化、VR相機(jī)渲染、場(chǎng)景切換、場(chǎng)景回收等靜態(tài)函數(shù)。
VRPage.js作為每個(gè)場(chǎng)景的工廠類,支持不同3d頁(yè)面(場(chǎng)景)之間的代碼獨(dú)立。
每一個(gè)VR頁(yè)面的生命周期都是:創(chuàng)建物體->加載模型->啟動(dòng)渲染的過(guò)程,因此,需要?jiǎng)?chuàng)建一個(gè)基類,來(lái)實(shí)現(xiàn)每一個(gè)VR場(chǎng)景實(shí)例的生命周期。

//common/VRPage.js
import * as WebVR from "VRCore.js" //管理所有場(chǎng)景的公用模塊
// VR場(chǎng)景工廠
export default class VRPage {
    constructor(options={}) {
        // 創(chuàng)建場(chǎng)景,如果場(chǎng)景已初始化
        WebVR.createScene(options);
        this.start();
        this.loadPage();
    }
    loadPage() {
        THREE.DefaultLoadingManager.onLoad = () => {
            // 模型加載完畢,即開(kāi)啟渲染
            WebVR.renderStart(this.update);
            this.loaded(); 
        }
    }
    start() { 
         // 實(shí)例的start方法將在啟動(dòng)渲染之前,場(chǎng)景相機(jī)初始化后執(zhí)行。
    }
    loaded() {
        // 實(shí)例的loaded方法將在場(chǎng)景資源加載后執(zhí)行。
    }
    update(delta) { 
        // 實(shí)例的update方法將在渲染器每一次渲染時(shí)執(zhí)行。
    }
}

這里使用THREE.DefaultLoadingManager.onLoad方法監(jiān)聽(tīng)場(chǎng)景是否加載完畢,一旦加載完畢,便啟動(dòng)渲染。

WebVR場(chǎng)景首次渲染

主要包括四個(gè)步驟

新建場(chǎng)景

創(chuàng)建VR相機(jī)

加載場(chǎng)景腳本與資源

開(kāi)啟動(dòng)畫(huà)渲染

VR環(huán)境初始化
function createScene({domContainer=document.body,fov=70,far=4000}) {
    // 創(chuàng)建場(chǎng)景
    Scene = new THREE.Scene();
    // 創(chuàng)建相機(jī)
    Camera = new THREE.PerspectiveCamera(fov,window.innerWidth/window.innerHeight,0.1,far);
    Camera.position.set( 0, 0, 0 );
    Scene.add(Camera);
    // 創(chuàng)建渲染器
    Renderer = new THREE.WebGLRenderer({ antialias: true } );
    Renderer.setSize(window.innerWidth,window.innerHeight);
    Renderer.shadowMapEnabled = true;
    Renderer.setPixelRatio(window.devicePixelRatio);
    domContainer.appendChild(Renderer.domElement);
    initVR();
    resize();
}

首先是three.js開(kāi)發(fā)三部曲,創(chuàng)建場(chǎng)景、相機(jī)、渲染器,接著調(diào)用initVR函數(shù)來(lái)完成VR場(chǎng)景分屏和陀螺儀控制,WebVR基本開(kāi)發(fā)步驟可以參考。

function initVR() {
    // 初始化VR分屏器和控制器
    Effect = new THREE.VREffect(Renderer);
    Controls = new THREE.VRControls(Camera);
    // 初始化VR管理器
    Manager = new WebVRManager(Renderer, Effect);
    window.addEventListener( "resize", e => {
        // 調(diào)整渲染器和相機(jī)以適應(yīng)窗口拉伸時(shí)寬高變動(dòng)
        Camera.aspect = window.innerWidth / window.innerHeight;
        Camera.updateProjectionMatrix();
        Effect.setSize(window.innerWidth, window.innerHeight);
    }, false );
}
開(kāi)啟動(dòng)畫(huà)渲染
// VRCore.js
function renderStart(callback) {
    // 設(shè)置loopID變量記錄每一幀ID
    loopID = 0;
    const loop = () => {
        if(loopID === -1) return;
        loopID = requestAnimationFrame(loop);
        callback();
        Controls.update();
        Manager.render(Scene, Camera);
    };
    loop();
}

這里傳入?yún)?shù)動(dòng)畫(huà)渲染做了三件事,使用loopID作為整個(gè)VR應(yīng)用的全局變量,記錄每一幀動(dòng)畫(huà)的更新;更新相機(jī)控制器和VR渲染器,

WebVR場(chǎng)景切換

主要包括四個(gè)步驟

暫停渲染

清空當(dāng)前場(chǎng)景物體

請(qǐng)求并加載目標(biāo)場(chǎng)景腳本與資源

重啟渲染

暫停動(dòng)畫(huà)渲染
function renderStop() {
    if (loopID !== -1) {
        window.cancelAnimationFrame(loopID);
        loopID = -1;
    }
}
回收當(dāng)前場(chǎng)景
function clearScene() {
    for(let i = Scene.children.length - 1; i >= 0; i-- ) {
        Scene.remove(Scene.children[i]);
    }
}
按需加載

切換到下一場(chǎng)景,我們需要請(qǐng)求對(duì)應(yīng)的場(chǎng)景腳本,這里使用webpack2的import函數(shù)進(jìn)行代碼分離,當(dāng)然你也可以使用require.ensure(filename => {require(filename)})方法。

import(`page/${fileName}.js`);

最終將清空當(dāng)前場(chǎng)景與請(qǐng)求加載目標(biāo)場(chǎng)景功能封裝為forward跳轉(zhuǎn)方法,就可以在頁(yè)面里直接調(diào)用了。

// common/VRCore.js
function forward(fileName) {
    renderStop();
    clearScene();
    import(`page/${fileName}.js`);
}
// page/index.js
...
class Index extends VRPage {
    start() {
        let geometry = new THREE.CubeGeometry(5,5,5);
        let material = new THREE.MeshBasicMaterial({ 
            color: 0x00aadd
        });
        this.box = new THREE.Mesh(geometry,material);
        this.box.position.set(3,-2,-3);
        // add gaze eventLisenter
        this.box.on("gaze",mesh => { // gazeIn trigger
            WebVR.forward("page2.js");
        });
        WebVR.Scene.add(box);
    }
}
...
// page2.js
class page2 extends VRPage {
    start() {
        this.addPanorama(1000, ASSET_TEXTURE_SKYBOX);
    }
    addPanorama(radius,path) {
        // create panorama
        let geometry = new THREE.SphereGeometry(radius,50,50);
        let material = new THREE.MeshBasicMaterial( { map: new THREE.TextureLoader().load(path),side:THREE.BackSide } );
        let panorama = new THREE.Mesh(geometry,material);
        WebVR.Scene.add(panorama);
        return panorama;
    }
}
export default (() => {
    return new page2();
})();

我們?cè)趫?chǎng)景里創(chuàng)建一個(gè)立方體,當(dāng)凝視到該物體時(shí),執(zhí)行forward方法跳轉(zhuǎn)至page2場(chǎng)景。

至此,我們的WebVR工程已經(jīng)完成了一半,接下來(lái),我們使用Webpack2來(lái)構(gòu)建我們的工程。

webpack配置

開(kāi)發(fā)環(huán)境和生產(chǎn)環(huán)境下webpack配置略有不同,這里主要給出webpack的基本配置,具體可參考項(xiàng)目地址。

const path = require("path");
const CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ProvidePlugin = require("webpack/lib/ProvidePlugin");

module.exports = {

  entry: {
    "vendor": "./src/common/js/vendor.js",
    "app": "./src/page/index.js"
  },

  output: {
    path: path.resolve(__dirname, "../dist/"),
    filename: "[name].js",
    sourceMapFilename: "[name].map",
    chunkFilename: "[id]-chunk.js",
    publicPath: "/"
  },

這里我們將webvr首個(gè)場(chǎng)景src/page/index.js作為項(xiàng)目打包入口,同時(shí)將page目錄下的文件也作為多帶帶chunk,配合按需加載來(lái)支持場(chǎng)景切換。

  module: {
    rules: [
      {
        test: /.js/,
        exclude: /node_modules/,
        use: [
          { loader:"babel-loader",options: { 
            presets: ["latest",["es2015", {"modules": false}]] 
          }
        ]
      },
      {
        test: /.css/,
        use: ["style-loader","css-loader"]
      },
      {
        test: /.(jpg|png|mp4|wav|ogg|obj|mtl|dae)$/,
        loader: "file-loader"
      }
    ]

  },

這里引入file-loader,這樣就能在場(chǎng)景里直接import需要用到的素材,如下。

//page/page2.js
import ASSET_TEXTURE_SKYBOX from "assets/texture/360_page2.jpg";

webpack相關(guān)的plugin配置如下

  plugins: [
    new CommonsChunkPlugin({
      name: ["app", "vendor"],
      minChunks: Infinity
    }),
    new ProvidePlugin({
      "THREE": "three",
      "WebVR": path.resolve(__dirname,"../src/common/js/VRCore.js")
    }),
    new HtmlWebpackPlugin({
      inject: true,
      template: path.resolve(__dirname, "../src/index.html"),
      favicon: path.resolve(__dirname, "../src/favicon.ico")
    })
  ]

};

使用ProvidePluginthree.js作為公用模塊輸出,以省去在每個(gè)腳本import THREE from "three"的重復(fù)工作,同時(shí)將管理所有場(chǎng)景的核心模塊VRCore.js作為全局公用模塊輸出。
使用HtmlWebpackPlugin將公用的html打包到dist目錄下。

polyfill配置

最后是polyfill配置,我們需要引入webvr-polyfill和babel-polyfill來(lái)分別支持webvr API和ES6 API,并作為一個(gè)頁(yè)面獨(dú)立腳本。

// common/vendor.js
import "babel-polyfill";
import "webvr-polyfill";

以上WebVR工程已經(jīng)基本搭建完畢,歡迎各位提出寶貴意見(jiàn),后續(xù)我們將探索daydream和Oculus在webvr上的開(kāi)發(fā)模式,敬請(qǐng)期待。

最后,獻(xiàn)上前幾天在google開(kāi)發(fā)者網(wǎng)站上看到的:預(yù)測(cè)未來(lái),不如創(chuàng)造未來(lái)。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/83025.html

相關(guān)文章

  • SegmentFault 技術(shù)周刊 Vol.35 - WebGL:打開(kāi)網(wǎng)頁(yè)看大片

    摘要:在文末,我會(huì)附上一個(gè)可加載的模型方便學(xué)習(xí)中文藝術(shù)字渲染用原生可以很容易地繪制文字,但是原生提供的文字效果美化功能十分有限。 showImg(https://segmentfault.com/img/bVWYnb?w=900&h=385); WebGL 可以說(shuō)是 HTML5 技術(shù)生態(tài)鏈中最為令人振奮的標(biāo)準(zhǔn)之一,它把 Web 帶入了 3D 的時(shí)代。 初識(shí) WebGL 先通過(guò)幾個(gè)使用 Web...

    objc94 評(píng)論0 收藏0
  • 筆記 - 收藏集 - 掘金

    摘要:目錄如何用提高效率后端掘金經(jīng)常有人說(shuō)我應(yīng)該學(xué)一門(mén)語(yǔ)言,比如之類,但是卻不知道如何入門(mén)。本文將通過(guò)我是如何開(kāi)發(fā)公司年會(huì)抽獎(jiǎng)系統(tǒng)的后端掘金需求出現(xiàn)年會(huì)將近,而年會(huì)抽獎(jiǎng)環(huán)節(jié)必不可少,但是抽獎(jiǎng)系統(tǒng)卻還沒(méi)有。 云盤(pán)一個(gè)個(gè)倒下怎么辦?無(wú)需編碼,手把手教你搭建至尊私享云盤(pán) - 工具資源 - 掘金微盤(pán)掛了,360倒了,百度云盤(pán)也立了Flag。能讓我們?cè)谠贫藘?chǔ)存分享文件的服務(wù)越來(lái)越少了。 買(mǎi)一堆移動(dòng)硬盤(pán)...

    Alex 評(píng)論0 收藏0
  • 淺談 WebVR

    摘要:它與智能手機(jī)相連接,將顯示變成顯示。廠商滑配式設(shè)備包括谷歌和三星。作為一款獨(dú)立的計(jì)算設(shè)備,整合式設(shè)備將配備一整套零部件,價(jià)格甚至高于普通。廠商微軟對(duì)于想初步體驗(yàn)或入門(mén)的用戶,推薦谷歌的或國(guó)內(nèi)的性價(jià)比高的滑配式設(shè)備。 本文轉(zhuǎn)自凹凸實(shí)驗(yàn)室:https://aotu.io/notes/2016/08... showImg(https://segmentfault.com/img/bVC2cm...

    yexiaobai 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<