Geçenlerde, Sanal gerçeklik web’e geliyor, arkasındaki temel kavramları tanıtan bir makale yayınladım. WebXR Cihaz API’sı. Ayrıca bir XR oturumu istemek, girmek ve sonlandırmak için talimatlar verdim.
Bu makale, içeriğin tekrar tekrar ekrana çekildiği, kullanıcı aracısı tarafından kontrol edilen sonsuz bir döngü olan çerçeve döngüsünü açıklamaktadır. İçerik, çerçeve adı verilen ayrı bloklar halinde çizilir. Çerçevelerin ardışıklığı, hareket yanılsaması yaratır.
Bu makale ne değildir? #
WebGL ve WebGL2, bir WebXR Uygulamasında bir çerçeve döngüsü sırasında içerik oluşturmanın tek yoludur. Neyse ki birçok çerçeve, WebGL ve WebGL2’nin üzerinde bir soyutlama katmanı sağlar. Bu tür çerçeveler şunları içerir: üç.js, babylonjsVe PlayCanvassırasında A Çerçevesi Ve Tepki 360 WebXR ile etkileşim için tasarlanmıştır.
Bu makale ne bir WebGL ne de bir çerçeve öğreticisidir. Sürükleyici Web Çalışma Grubu’nun Sürükleyici VR Oturumu örneğini kullanarak bir çerçeve döngüsünün temellerini açıklar (gösteri, kaynak). WebGL’ye veya çerçevelerden birine dalmak istiyorsanız, internet büyüyen bir makale listesi sağlar.
Oyuncular ve oyun #
Çerçeve döngüsünü anlamaya çalışırken ayrıntılarda kaybolmaya devam ettim. Oyunda çok sayıda nesne var ve bunlardan bazıları yalnızca diğer nesnelerdeki referans özelliklerine göre adlandırılıyor. Düz tutmanıza yardımcı olmak için, ‘oyuncular’ olarak adlandırdığım nesneleri açıklayacağım. Sonra nasıl etkileşim kurduklarını anlatacağım, buna ‘oyun’ adını veriyorum.
Oyuncular #
XRViewer Poz #
Poz, bir şeyin 3 boyutlu uzaydaki konumu ve yönüdür. Hem izleyicilerin hem de giriş cihazlarının bir pozu vardır, ancak burada ilgilendiğimiz izleyicinin pozudur. Hem izleyici hem de giriş cihazı pozlarının bir transform
bir vektör olarak konumunu ve orijine göre bir dördey olarak yönelimini tanımlayan öznitelik. Orijin, arama sırasında istenen referans uzay tipine göre belirtilir. XRSession.requestReferenceSpace()
.
Referans alanlarını açıklamak biraz zaman alır. Artırılmış gerçeklikte bunları derinlemesine işliyorum. Bu makale için temel olarak kullandığım örnek, bir 'local'
referans alanı, başlangıç noktasının oturum oluşturma sırasında iyi tanımlanmış bir zemin olmadan izleyicinin konumunda olduğu ve kesin konumunun platforma göre değişebileceği anlamına gelir.
XRView #
Görünüm, sanal sahneyi görüntüleyen bir kameraya karşılık gelir. Bir görünümün ayrıca bir transform
bir vektör olarak konumunu ve yönünü açıklayan nitelik. Bunlar hem bir vektör/dördey çifti hem de eşdeğer bir matris olarak sağlanır; kodunuza en uygun olana bağlı olarak her iki gösterimi de kullanabilirsiniz. Her görünüm, izleyiciye görüntü sunmak için bir cihaz tarafından kullanılan bir ekrana veya ekranın bir bölümüne karşılık gelir. XRView
nesneler bir dizide döndürülür XRViewerPose
nesne. Dizideki görüntüleme sayısı değişir. Mobil cihazlarda bir AR sahnesinin, cihaz ekranını kaplayabilen veya kapsamayan tek bir görünümü vardır. Kulaklıkların tipik olarak her bir göz için bir tane olmak üzere iki görünümü vardır.
XRWebGLLayer #
Katmanlar, bir bitmap görüntüleri kaynağı ve bu görüntülerin cihazda nasıl işleneceğine ilişkin açıklamalar sağlar. Bu açıklama, bu oyuncunun ne yaptığını tam olarak yansıtmıyor. Bunu bir cihaz ile bir cihaz arasında bir aracı olarak düşünmeye başladım. WebGLRenderingContext
. MDN, ikisi arasında ‘bir bağlantı sağladığını’ belirterek hemen hemen aynı görüşü benimsiyor. Bu nedenle, diğer oyunculara erişim sağlar.
Genel olarak WebGL nesneleri, 2B ve 3B grafikleri işlemek için durum bilgilerini depolar.
WebGLFramebuffer #
Bir çerçeve arabelleği, görüntü verilerini WebGLRenderingContext
. dan aldıktan sonra XRWebGLLayer
basitçe geçerli olana iletirsiniz WebGLRenderingContext
. aramaktan başka bindFramebuffer()
(daha sonra bunun hakkında daha fazla bilgi) bu nesneye asla doğrudan erişemeyeceksiniz. Sadece onu geçeceksin XRWebGLLayer
WebGLRenderingContext’e.
XRViewport #
Bir görüntü alanı, görüntüdeki dikdörtgen bir bölgenin koordinatlarını ve boyutlarını sağlar. WebGLFramebuffer
.
WebGLRenderingContext #
Oluşturma bağlamı, bir tuval (üzerinde çizim yaptığımız alan) için programlı bir erişim noktasıdır. Bunu yapmak için hem bir WebGLFramebuffer
ve bir XRViewport.
arasındaki ilişkiye dikkat edin XRWebGLLayer
Ve WebGLRenderingContext
. Biri izleyicinin cihazına, diğeri ise web sayfasına karşılık gelir. WebGLFramebuffer
Ve XRViewport
birinciden ikinciye geçilir.
XRWebGLLayer
Ve WebGLRenderingContext
Oyun #
Artık oyuncuların kim olduğunu bildiğimize göre, oynadıkları oyuna bakalım. Her karede baştan başlayan bir oyun. Çerçevelerin, temeldeki donanıma bağlı bir hızda gerçekleşen bir çerçeve döngüsünün parçası olduğunu hatırlayın. VR uygulamaları için saniyedeki kare sayısı 60 ile 144 arasında olabilir. Android için AR saniyede 30 kare hızında çalışır. Kodunuz belirli bir kare hızını varsaymamalıdır.
Çerçeve döngüsü için temel işlem şöyle görünür:
- Arama
XRSession.requestAnimationFrame()
. Yanıt olarak, kullanıcı aracısı şunu çağırır:XRFrameRequestCallback
sizin tarafınızdan tanımlanır. - Geri arama işlevinizin içinde:
- Arama
XRSession.requestAnimationFrame()
Tekrar. - İzleyicinin pozunu alın.
- İletmek (‘bağlamak’)
WebGLFramebuffer
danXRWebGLLayer
içinWebGLRenderingContext
. - Her birini yineleyin
XRView
nesne, onun alınmasıXRViewport
danXRWebGLLayer
ve ona geçirmekWebGLRenderingContext
. - Framebuffer’a bir şey çizin.
- Arama
Önceki makalede 1. ve 2a adımları ele alındığından, 2b adımından başlayacağım.
İzleyicinin pozunu alın #
Muhtemelen söylemeye gerek yok. AR veya VR’de herhangi bir şey çizmek için, izleyicinin nerede olduğunu ve nereye baktığını bilmem gerekiyor. İzleyicinin konumu ve yönü, bir XRViewerPose nesnesi. İzleyicinin pozunu arayarak alıyorum XRFrame.getViewerPose()
Geçerli animasyon karesinde. Oturumu kurduğumda edindiğim referans alanını aktarırım. Bu nesne tarafından döndürülen değerler her zaman geçerli oturuma girdiğimde talep ettiğim referans uzayına göredir. Hatırlayacağınız üzere poz isterken mevcut referans alanını geçmek zorunda kalıyorum.
function onXRFrame(hrTime, xrFrame) {
let xrSession = xrFrame.session;
xrSession.requestAnimationFrame(onXRFrame);
let xrViewerPose = xrFrame.getViewerPose(xrRefSpace);
if (xrViewerPose) {
// Render based on the pose.
}
}
Kullanıcının genel konumunu temsil eden bir izleyici pozu vardır; bu, izleyicinin kafası veya akıllı telefon söz konusu olduğunda telefon kamerası anlamına gelir. Poz, uygulamanıza izleyicinin nerede olduğunu söyler. Gerçek görüntü oluşturma kullanımları XRView
birazdan değineceğim nesneler.
Devam etmeden önce, sistemin takibi kaybetmesi veya gizlilik nedenleriyle pozu engellemesi durumunda izleyici pozunun döndürülüp döndürülmediğini test ediyorum. İzleme, XR cihazının kendisinin ve/veya giriş cihazlarının çevreye göre nerede olduğunu bilme yeteneğidir. İzleme birkaç şekilde kaybolabilir ve izleme için kullanılan yönteme göre değişir. Örneğin, kulaklıktaki veya telefondaki kameralar cihazı izlemek için kullanılırsa, ışığın az olduğu veya hiç olmadığı durumlarda veya kameraların kapalı olup olmadığı durumlarda nerede olduğunu belirleme yeteneğini kaybedebilir.
Gizlilik nedenleriyle pozu engellemeye bir örnek, kulaklığın izin istemi gibi bir güvenlik iletişim kutusu göstermesi durumunda tarayıcının bu olurken uygulamaya poz sağlamayı durdurabilmesidir. Ama ben zaten aradım XRSession.requestAnimationFrame()
böylece sistem kurtarılabilirse, çerçeve döngüsü devam edecektir. Değilse, kullanıcı aracısı oturumu sonlandırır ve end
olay işleyicisi.
Kısa bir sapma #
Bir sonraki adım, oturum kurulumu sırasında oluşturulan nesneleri gerektirir. Bir tuval oluşturduğumu ve ona çağrı yaparak aldığım XR uyumlu bir Web GL oluşturma bağlamı oluşturma talimatı verdiğimi hatırlayın. canvas.getContext()
. Tüm çizimler WebGL API, WebGL2 API veya Three.js gibi WebGL tabanlı bir çerçeve kullanılarak yapılır. Bu bağlam, oturum nesnesine şu yolla iletildi: updateRenderState()
yeni bir örneği ile birlikte XRWebGLLayer
.
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’ı iletin (‘bağlayın’) #
bu XRWebGLLayer
için bir çerçeve arabelleği sağlar. WebGLRenderingContext
WebXR ile kullanım için özel olarak sağlanır ve işleme bağlamlarının varsayılan çerçeve arabelleğinin yerini alır. Buna WebGL dilinde ‘bağlama’ denir.
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
}
}
Her XRView nesnesi üzerinde yineleme yapın #
Pozu aldıktan ve framebuffer’ı bağladıktan sonra, sıra vitrinleri almaya geliyor. bu XRViewerPose
her biri bir ekranı veya bir ekranın bir bölümünü temsil eden bir dizi XRView arayüzü içerir. Görüş alanı, göz ofseti ve diğer optik özellikler gibi cihaz ve görüntüleyici için doğru şekilde konumlandırılmış içeriği işlemek için gereken bilgileri içerirler. İki göz için çizdiğim için, her biri için ayrı bir görüntü çizdiğim ve içinden geçtiğim iki görünümüm var.
Telefon tabanlı artırılmış gerçeklik için uygularken, yalnızca bir görünümüm olurdu ama yine de bir döngü kullanırdım. Tek bir görünümde yineleme yapmak anlamsız görünse de, bunu yapmak, sürükleyici deneyimler yelpazesi için tek bir işleme yoluna sahip olmanızı sağlar. Bu, WebXR ve diğer sürükleyici sistemler arasındaki önemli bir farktır.
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 nesnesini WebGLRenderingContext’e geçirin #
Bir XRView
nesne, bir ekranda gözlemlenebilir olanı ifade eder. Ancak bu görünümü çizmek için cihazıma özel koordinatlara ve boyutlara ihtiyacım var. Framebuffer’da olduğu gibi, onları XRWebGLLayer
ve onları 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 #
Bu makaleyi yazarken, birkaç meslektaşımla isim konusunda tartıştım. webGLRenContext
nesne. Örnek betikler ve çoğu WebXR kodu bu değişkeni basitçe çağırır gl
. Örnekleri anlamaya çalışırken, ne olduğunu unutmaya devam ettim. gl
anılır. onu aradım webGLRenContext
bunun bir örnek olduğunu öğrenirken size hatırlatmak için WebGLRenderingContext
.
Bunun nedeni, kullanılması gl
yöntem adlarının, derlenmiş dillerde VR oluşturmak için kullanılan OpenGL ES 2.0 API’sindeki karşılıkları gibi görünmesini sağlar. OpenGL kullanarak VR uygulamaları yazdıysanız bu gerçek açıktır, ancak bu teknolojide tamamen yeniyseniz kafa karıştırıcıdır.
Framebuffer’a bir şey çizin #
Kendinizi gerçekten hırslı hissediyorsanız, doğrudan WebGL’yi kullanabilirsiniz, ancak bunu önermiyorum. Çerçevelerden birini kullanmak çok daha basit en üstte listelenmiş.
Çözüm #
Bu, WebXR güncellemelerinin veya makalelerinin sonu değil. bulabilirsin WebXR’nin tüm arayüzleri ve üyeleri için referans MDN’de. Arayüzlerin kendilerinde yapılacak geliştirmeler için, şu adresteki özellikleri tek tek takip edin: Chrome Durumu.
fotoğrafı çeken JESHOOTS.COM Açık Unsplash