日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

网页调用摄像头_【WebAR】虚拟现实来到网页——WebXR Device API第二部分

發(fā)布時(shí)間:2024/9/30 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 网页调用摄像头_【WebAR】虚拟现实来到网页——WebXR Device API第二部分 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

作者:Joe Medley

原文:https://web.dev/vr-comes-to-the-web-pt-ii/

本文介紹幀循環(huán)(frame loop),這是一個(gè)無(wú)限循環(huán),內(nèi)容被重復(fù)繪制到屏幕上。內(nèi)容繪制在幀中,一系列的幀創(chuàng)造了運(yùn)動(dòng)的效果。

前言

WebGL和WebGL2是在WebXR App的幀循環(huán)期間呈現(xiàn)內(nèi)容的唯一方法。幸運(yùn)的是,許多框架在WebGL和WebGL2的基礎(chǔ)上提供了一層抽象。這樣的框架包括three.js, babylonjs和 PlayCanvas,而A-Frame和React 360設(shè)計(jì)用于與WebXR進(jìn)行交互。

本文既不是WebGL教程,也不是框架教程。本文使用Immersive VR Session示例解釋幀循環(huán)的基礎(chǔ)。

玩家和游戲

當(dāng)理解幀循環(huán)時(shí),我試圖減少一些細(xì)節(jié)。有很多對(duì)象在起作用,但其中一些僅由其他對(duì)象上的屬性來(lái)命名。我將描述被稱(chēng)為“玩家”的對(duì)象。然后,我將描述它們?nèi)绾蜗嗷プ饔?#xff0c;我稱(chēng)之為“游戲”。

玩家

XRViewerPose

姿勢(shì)(Pose)是物體在3D空間中的位置和方向。觀看者和輸入設(shè)備都有一個(gè)姿勢(shì),但我們?cè)谶@里關(guān)注觀看者的姿勢(shì)。觀看者和輸入設(shè)備的姿勢(shì)都具有一個(gè)transform屬性,該屬性將其位置描述為矢量,并將其方向描述為相對(duì)于坐標(biāo)原點(diǎn)的四元數(shù)。調(diào)用XRSession.requestReferenceSpace()時(shí),將根據(jù)請(qǐng)求的參考空間類(lèi)型指定起點(diǎn)。

對(duì)于參考空間,需要一些解釋。在我的文章中介紹過(guò)它們。我用作本文的示例使用一個(gè)'local'參考空間,這意味著起點(diǎn)位于會(huì)話創(chuàng)建時(shí)查看者的位置,而沒(méi)有清晰的界定,并且其精確位置可能因平臺(tái)而異。

XRView

視圖對(duì)應(yīng)于查看虛擬場(chǎng)景的相機(jī)。視圖具有transform描述其作為矢量的位置及其方向的 屬性。這些以向量、四元數(shù)、矩陣等形式提供,您可以根據(jù)哪種最適合您的代碼來(lái)使用任一種表示形式。每個(gè)視圖對(duì)應(yīng)于設(shè)備用來(lái)向觀看者呈現(xiàn)圖像的顯示器或顯示器的一部分。XRView對(duì)象從XRViewerPose對(duì)象以數(shù)組形式返回。數(shù)組中的視圖數(shù)量有所不同。在移動(dòng)設(shè)備上,AR場(chǎng)景具有一個(gè)視圖,該視圖可能會(huì)或不會(huì)覆蓋設(shè)備屏幕。耳機(jī)通常有兩種視圖,每只眼睛一個(gè)。

XRWebGLLayer

圖層提供了位圖圖像的來(lái)源,以及如何在設(shè)備中渲染這些圖像的描述。此描述并不能完全反映出該玩家的功能。我開(kāi)始把它看作是設(shè)備和設(shè)備之間的中間人 WebGLRenderingContext。MDN持相同觀點(diǎn),稱(chēng)其“提供了兩者之間的聯(lián)系”。這樣,它提供了對(duì)其他玩家的訪問(wèn)。

通常,WebGL對(duì)象存儲(chǔ)用于渲染2D和3D圖形的狀態(tài)信息。

WebGLFramebuffer

幀緩沖器將圖像數(shù)據(jù)提供給WebGLRenderingContext。從XRWebGLLayer中獲取后,您只需將其傳遞給當(dāng)前 WebGLRenderingContext。除了調(diào)用bindFramebuffer()之外,您將永遠(yuǎn)不會(huì)直接訪問(wèn)此對(duì)象。您只需將其從傳遞XRWebGLLayer到WebGLRenderingContext。

XRViewport

視口提供了矩形區(qū)域在WebGLFramebuffer的坐標(biāo)和尺寸。

WebGLRenderingContext

渲染上下文是畫(huà)布(我們?cè)谄渖侠L制的空間)的程序入口。為此,它需要一個(gè)WebGLFramebuffer和一個(gè)XRViewport。

注意XRWebGLLayer和WebGLRenderingContext之間的關(guān)系。一個(gè)對(duì)應(yīng)于觀看者的設(shè)備,另一個(gè)對(duì)應(yīng)于網(wǎng)頁(yè)。 WebGLFramebuffer和XRViewport被從前者傳遞到后者。

游戲

現(xiàn)在我們知道了玩家是誰(shuí),讓我們看看他們玩的游戲。這是一個(gè)從每一幀開(kāi)始的游戲。回想一下,幀是幀循環(huán)的一部分,該循環(huán)的發(fā)生速率取決于硬件。對(duì)于VR應(yīng)用程序,每秒的幀數(shù)可以在60到144之間。Android的AR的運(yùn)行速度為每秒30幀。您的代碼不應(yīng)采用任何特定的幀速率。

幀循環(huán)的基本過(guò)程是:

  • 調(diào)用XRSession.requestAnimationFrame()。作為響應(yīng),調(diào)用您定義的XRFrameRequestCallback。
  • 在回調(diào)函數(shù)內(nèi)部:
  • 調(diào)用XRSession.requestAnimationFrame()一次
  • 獲取觀看者的姿態(tài)。
  • 傳遞WebGLFramebuffer從XRWebGLLayer到WebGLRenderingContext。
  • 遍歷每個(gè)XRView對(duì)象,XRViewport從中搜索其XRWebGLLayer并將其傳遞給WebGLRenderingContext。
  • 在幀地緩沖區(qū)中繪制一些內(nèi)容。
  • 因?yàn)樯弦黄恼陆榻B了步驟1,所以我將從步驟2開(kāi)始。

    獲得觀看者的姿勢(shì)

    要在AR或VR中繪制任何內(nèi)容,我需要知道觀看者在哪里以及他們?cè)诳词裁础S^看者的位置和方向由XRViewerPose對(duì)象提供。我通過(guò)在當(dāng)前動(dòng)畫(huà)幀調(diào)用XRFrame.getViewerPose()來(lái)獲得觀看者的姿勢(shì)。我將設(shè)置會(huì)話時(shí)獲得的參考空間傳遞給它。該對(duì)象返回的值始終相對(duì)于進(jìn)入當(dāng)前會(huì)話時(shí)請(qǐng)求的參考空間。您可能還記得,請(qǐng)求姿勢(shì)時(shí)我必須傳遞當(dāng)前參考空間。

    function onXRFrame(hrTime, xrFrame) {let xrSession = xrFrame.session;xrSession.requestAnimationFrame(onXRFrame);let xrViewerPose = xrFrame.getViewerPose(xrRefSpace);if (xrViewerPose) {// Render based on the pose.} }

    一個(gè)觀看者的姿勢(shì)代表用戶的整體位置,對(duì)于智能手機(jī)而言,這意味著觀看者的頭部或手機(jī)攝像頭。姿勢(shì)告訴您的應(yīng)用程序查看者在哪里。實(shí)際的圖像渲染使用 XRView對(duì)象,我將稍后介紹。

    在繼續(xù)之前,我檢測(cè)了是否返回了觀察者的姿勢(shì),以防系統(tǒng)由于隱私原因失去跟蹤或阻止姿勢(shì)。跟蹤是XR設(shè)備知道其輸入設(shè)備相對(duì)于環(huán)境的位置的能力。跟蹤可能會(huì)以幾種方式丟失,并且會(huì)根據(jù)跟蹤所使用的方法而有所不同。例如,如果使用頭戴式耳機(jī)或手機(jī)上的攝像頭來(lái)跟蹤設(shè)備,則該設(shè)備可能無(wú)法確定光線不足或沒(méi)有光線的情況下的位置,或者是否遮蓋了攝像頭。

    出于隱私原因阻止姿勢(shì)的例子:如果耳機(jī)顯示安全對(duì)話框(例如權(quán)限提示),瀏覽器可能會(huì)在這種情況下停止向應(yīng)用程序提供姿勢(shì)。但是我已經(jīng)調(diào)用XRSession.requestAnimationFrame(),如果系統(tǒng)可以恢復(fù),則幀循環(huán)將繼續(xù)。否則,將結(jié)束會(huì)話并調(diào)用 end事件處理程序。

    繞行

    下一步需要在會(huì)話建立期間創(chuàng)建對(duì)象。回想一下,我創(chuàng)建了一個(gè)畫(huà)布,并指示它創(chuàng)建與XR兼容的Web GL渲染上下文,可以通過(guò)調(diào)用來(lái)獲得它c(diǎn)anvas.getContext()。所有繪圖都是使用WebGL API,WebGL2 API或基于WebGL的框架(如Three.js)完成的。該上下文被傳遞給會(huì)話對(duì)象,通過(guò)updateRenderState()和一個(gè)XRWebGLLayer的新實(shí)例。

    let canvas = document.createElement('canvas'); // The rendering context must be based on WebGL or WebGL2 let webGLRenContext = canvas.getContext('webgl', { xrCompatible: true }); xrSession.updateRenderState({baseLayer: new XRWebGLLayer(xrSession, webGLRenContext)});

    傳遞WebGLFramebuffer

    XRWebGLLayer為WebGLRenderingContext提供了一個(gè)framebuffer,用于與WebXR使用,并替換默認(rèn)的framebuffer。在WebGL語(yǔ)言中,這稱(chēng)為“綁定(bind)”。

    function onXRFrame(hrTime, xrFrame) {let xrSession = xrFrame.session;xrSession.requestAnimationFrame(onXRFrame);let xrViewerPose = xrFrame.getViewerPose(xrRefSpace);if (xrViewerPose) {let glLayer = xrSession.renderState.baseLayer;webGLRenContext.bindFramebuffer(webGLRenContext.FRAMEBUFFER, glLayer.framebuffer);// Iterate over the views} }

    遍歷每個(gè)XRView對(duì)象

    在獲得姿勢(shì)并綁定framebuffer之后,就該獲取視口了。該XRViewerPose包含的XRView接口數(shù)組的每一個(gè),表示一個(gè)顯示器或顯示器的一部分。它們包含渲染內(nèi)容所需的信息,這些內(nèi)容相對(duì)于設(shè)備和觀看者而言,例如視野,眼睛偏移(eye offset)和其他光學(xué)特性。由于我為兩只眼睛畫(huà)圖,所以我有兩個(gè)視圖,這些視圖將循環(huán)遍歷并為每個(gè)視圖繪制一個(gè)單獨(dú)的圖像。

    當(dāng)基于手機(jī)的增強(qiáng)現(xiàn)實(shí)時(shí),我只有一個(gè)視圖,但是我仍然會(huì)使用循環(huán)。盡管遍歷一個(gè)視圖似乎沒(méi)有意義,但是這樣做可以讓您擁有一條呈現(xiàn)各種沉浸式體驗(yàn)的渲染路徑。這是WebXR與其他沉浸式系統(tǒng)之間的重要區(qū)別。

    function onXRFrame(hrTime, xrFrame) {let xrSession = xrFrame.session;xrSession.requestAnimationFrame(onXRFrame);let xrViewerPose = xrFrame.getViewerPose(xrRefSpace);if (xrViewerPose) {let glLayer = xrSession.renderState.baseLayer;webGLRenContext.bindFramebuffer(webGLRenContext.FRAMEBUFFER, glLayer.framebuffer);for (let xrView of xrViewerPose.views) {// Pass viewports to the context}} }

    將XRViewport對(duì)象傳遞給WebGLRenderingContext

    一個(gè)XRView對(duì)象指在屏幕上觀察到什么。但是要繪制該視圖,我需要基于我的設(shè)備的坐標(biāo)和尺寸。與framebuffer一樣,我請(qǐng)求它們并將它們XRWebGLLayer傳遞給WebGLRenderingContext。

    function onXRFrame(hrTime, xrFrame) {let xrSession = xrFrame.session;xrSession.requestAnimationFrame(onXRFrame);let xrViewerPose = xrFrame.getViewerPose(xrRefSpace);if (xrViewerPose) {let glLayer = xrSession.renderState.baseLayer;webGLRenContext.bindFramebuffer(webGLRenContext.FRAMEBUFFER, glLayer.framebuffer);for (let xrView of xrViewerPose.views) {let viewport = glLayer.getViewport(xrView);webGLRenContext.viewport(viewport.x, viewport.y, viewport.width, viewport.height);// Draw something to the framebuffer}} }

    webGLRenContext

    在寫(xiě)本文時(shí),我與幾個(gè)同事就webGLRenContext對(duì)象的命名進(jìn)行了辯論。示例腳本和大多數(shù)WebXR代碼簡(jiǎn)單地調(diào)用此變量gl。當(dāng)我努力理解示例代碼時(shí),我一直忘了gl所指的是什么。我把它命名為webGLRenContext的目的是提醒您,這是一個(gè)WebGLRenderingContext實(shí)例。

    原因是使用gl允許方法名稱(chēng)看起來(lái)像OpenGL ES 2.0 API中的對(duì)應(yīng)名稱(chēng),后者用于以編譯語(yǔ)言創(chuàng)建VR。如果您使用OpenGL編寫(xiě)VR應(yīng)用程序,這就很明顯,但是如果您是該技術(shù)的新手,則會(huì)感到困惑。

    畫(huà)點(diǎn)什么東西到framebuffer

    如果您真的有野心,可以直接使用WebGL,但我不建議這樣做。使用框架要簡(jiǎn)單得多。

    WebXR的文章尚未結(jié)束。

    總結(jié)

    以上是生活随笔為你收集整理的网页调用摄像头_【WebAR】虚拟现实来到网页——WebXR Device API第二部分的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。